Wednesday, August 15, 2012

Deploying your Symfony 2.0 web app to the production server « James Borden

Deploying your Symfony 2.0 web app to the production server « James Borden

I am developing a Symfony 2.0 web app. I wanted to get my app running on the production server as soon as possible so that I know that it will work there. I couldn’t find an article on the web that presents a straight forward howto for deploying the production environment of a Symfony 2.0 web app to a remote production server. After a bit of hacking, I figured out how to do it. This article details the quick and dirty method I used to get a Symfony 2.0 web app onto a production server.
It should be mentioned that there are tools which try to automate the deployment process such ascapifony, though I personally couldn’t get capifony to work for me. Besides, I want to understand the process by which a Symfony 2.0 app can be manually migrated from the development environment on my machine to the production environment on a remote server before I start relying on tools to automate the process for me.

Development Environment

System: Mac OS X 10.6
HTTP Server: Apache 2.2.17 running mod_php
PHP: 5.3.4
Symfony2 Project dir: /Library/WebServer/Documents/symfony2
This is my local machine where I develop my web app.

Remote Production Server

System: Linux 2.6.18-374.3.1.el5.lve0.8.44 (results from uname -a on my account)
HTTP Server: Apache 2.2.21
PHP: 5.3.10 (running as a cgi process)
Symfony2 Project dir: /home/james/symfony2
This is a shared hosting account at Arvixe web hosting.
I can access my shared hosting account via ssh and run commands from a bash shell. Before I began, I created a ~/symfony2 dir on the remote server where my Symfony2 webapp will reside. I set the root dir of my domain name to point to ~/symfony2/web. Getting httpd to do this is beyond the scope of this article.
In this article, all relative paths are relative to the main symfony2 project dir. For example, web/ refers to /Library/WebServer/Documents/symfony2/web on my local machine and to ~/symfony2/web on my remote server.

Deploying the project

Check the remote environment

Note: While the following information specifically mentions my shared hosting provider, it should be relevant everywhere. If you are the admin of your own server, you are of course responsible for installing and configuring php 5.3 yourself.
You may find that your remote host does not yet have php 5.3.2 installed. This is a requirement for a Symfony2 project and you should have your site admin install it for you, if it isn’t hiding somewhere on your remote account already. The default command line (cli) php on Arvixe is PHP 5.2.17.
$ php --version
PHP 5.2.17 (cli) (built: Dec 22 2011 01:10:30)
You may have to do some digging for yourself in order to find where php53 lives on your remote host. Here is a hint on how to find it:
$ find / -name "php53" -print
I setup an alias in my .profile file that points to the php 5.3 bin:
alias php="/usr/local/php53/bin/php"
Now when I type ‘php’ in my shell I see this:
$ php --version
PHP 5.3.10 (cli) (built: Feb  5 2012 13:35:22) 
After this, I uploaded the script in app/check.php and ran it
$ php check.php
to make sure that Symfony2 will actually run. Everything was OK.
Arvixe provides php 5.3 as an option for web applications, which must be run by modifying my .htaccess file in my web/ dir. See this article for more information. Your server will probably have a similar setup and a line to add to your .htaccess file. You can always verify which php version your web server uses by running the simple script on your remote server in your browser:

Transfer the project dir via rsync

I wanted to keep things as simple as possible, so I used rsync. I created a /Library/WebServer/Documents/symfony2/app/config/rsync_exclude.txt file whose content is:
- app/cache/*
- app/logs/*
- web/.htaccess
- app/config/parameters.ini
I transfered the files using the rsync command on my local machine:
$ rsync -avz /Library/WebServer/Documents/symfony2 username@hostname:~/\
You could do something similar using sftp or even ftp. All you have to do is get your project directory onto your remote account. In my case, this means getting /Library/WebServer/Documents/symfony2 to ~/symfony2 .

Edit parameters.ini

I had to make changes to my app/config/parameters.ini file. As I am using Doctrine with a MySQL database backend, I needed to change my parameters to reflect those of the localhost. This is a pretty straight forward process and beyond the scope of this article to show you how to do this.

Create routing_prod.yml

I had to create a routing file for my production environment in app/config/. I copied “routing_dev.yml” to “routing_prod.yml” and took out any extraneous routes that I didn’t need for my production environment. You must be sure to remove the routes for:
I also needed to add the following lines to my app/config/config_prod.yml file:
    router: { resource: "%kernel.root_dir%/config/routing_prod.yml" }
so that the new routing parameters will be used by my app.

Console commands

After I made the changes to my configuration files, I needed to run some console commands to get everything working. Make sure that when you are running the app/console program that you do it from your main symfony2 project dir on your remote account.
First, I had to publish my assets
$ php app/console assets:install --symlink web --env=prod
Then I created the database that I referenced in my parameters.ini file with the command:
$ php app/console doctrine:database:create --env=prod
Finally, I had to update my schema so that the tables were created in the database for my models
$ php app/console doctrine:schema:update --force --env=prod
I had to use the “–force” option because app/console is hesitant to create tables in the production environment database.
That is all! If I missed a crucial step… please let me know so that I can update this post. Otherwise, happy hacking and good luck developing your Symfony 2 apps!

More than 3 requests, I'll translate this to Chinese.


Christophe Laumond said...


There are two things which looks wrong to me ( doesn't mean there are actually wrong ;)

I don't think you need the routing_prod.yml.

Usually, the routes common to all environment are in route.yml, and the routes specific to the dev environment are the routing_dev.yml

That means that you should have only routing_dev.yml importing routing.yml, and in production, it will use directely routing.yml, so your routes specifics to dev won't be there.

The second is about the publishing of your assets.

I don't think the --symlink option is planned to be used in production, but is more a trick for dev environment.

Usually for production, the assets are dumped in web/ when the --symlink is not used.

Best regards,

ALGO said...

well, first of all, this article is written by some1 else. I copied over as a reference.

I personally use the deploy bundle to do the trick.

I agree the routing_prod.yml is not necessary in this case.

but I'm not sure about the symlink. If you use symlink in dev env, that means you have to publish your assets after sync anyway, I would say then symlink or not won't be an issue.

If you do not use symlink in dev env, this is not a problem anyway.