Symfony and Docker

Hi there. Today we are going to setup a Symfony project based on Docker. Microservices are very popular this day. I will show you how easily you can run your Symfony application on docker containers.

Setup docker containers

First of all, we need to think what we need in our application. I chose very basic setup with Nginx, Postgres as database server and RabbitMq. Moreover, I decided to use a docker-compose application to make all the setup and maintenance even easier. How to installing Docker and docker-compose you can find in the documentation.

The very first step is to add docker-compose.yml file. The file keeps information about docker containers we want to use and how looks relations between them. We will open some ports, too to be able to view our website and connect for example to Postgres or RabbitMq outside containers. Our new docker-compose.yml file looks as follows:

As you can see I added all required components. Some components use images (for example Postgres) and some of them use builds. What’s the difference? When we use a ready image the docker-compose will just download it. He does not have anything to do with it. They are provided by other developers via dockerhub. The builds say we will use some ready container but we want to add some tweaks to it to feet your needs. That’s what we will do next.

In the web container, we defined docker/nginx. We need to create a new folder with the same name in our project root directory. Inside of it create a new file named Dockerfile. It is the specific file where we define our container. In our case the file should look similar to:

All we do here is just say we want to use the latest version of the Nginx and we want to copy symfony.conf file to Nginx configuration folder. The file does not exist, so we need to create it in path /docker/nginx/symfony.conf as follows:

We define a new virtual host in Nginx to work well with Symfony.

Our web server is configured, so we need to install PHP. I will install PHP7 using php-fpm. Do not wait end create a new file /docker/php-fpm/Dockerfile.

We use PHP7 FPM image and install required dependencies. In 6th row, we download the latest version of Composer.

Setup Symfony project

Now, we need to install RabbitMq bundle to our Symfony application. To do that register the bundle by adding it to the kernel.

We are almost ready to run the services and see Symfony welcome page. To do that we need to build the containers (Nginx and PHP7) and run them. All we need is type in the console following command:

It will download all the images and build them (if needed). Now we need to add some configurations to Symfony itself. Update your app/config/parameters.yaml.dist file with the following content

As you can see the host for Postgres is ‘postgres’. It is the same name we used in docker-compose.yml file. The name we provided there is the name of the host in the network between containers. We granted access to the host thanks to ‘links’ parameters.

Now you can see that the PHP container has access to postgres and rabbitmq containers and can connect to them using TCP/UDP protocols. Cool, yeah? We did the same thing with Nginx and PHP. We granted Nginx access to connect to PHP container. All the credentials to the services are default.

OK, it is time to create another configuration file in app/config/rabbit.yml. I like separating configurations files into parts because it improves readability of the files. You can read how to create proper settings in the docs. Oh, remember to add the file to the app/config/config.yml.

Now, add IP ‘172.17.0.1’ to an array in the app_dev.php file to have access to the development version of you application. The next step is installing all Symfony dependencies and RabbitMq bundle.

Notice we use Composer installed in the container. It is needed because of file permissions to vendor/cache etc folders. Please remember about it and always use Composer in the Docker container.

Ready? Set! Go!

Now it is time to run all the stuff! It cannot be easier. Just type:

The ‘d’ parameter says we want to run it as a daemon (in the background). We are ALMOST ready to see the project in our browser. In Nginx, we defined virtual host with domain symfony.dev. We need to add the domain to our /etc/hosts file, but what IP should I put there? We need to get container ID to identify the container with Nginx installation and get it’s IP. Here is how you can do this.

Find the container with ‘web’ in its name. In the first column, you will get its ID. All you need is copy it and paste to the command below instead of THE_ID text.

When you do that you will see the IP we need. Just copy it and put to the /etc/hosts file. The only thing left is to open your browser and type http://symfony.dev.

Summary

As you can see it is not so difficult to run Symfony application in docker containers. You can try to add some other stuff like Logstash, Kibana and so on. I hope it will help you in development! If you have any questions or suggestions do not be shy, just ask.

About author

Hi! I am Bartek. I'm a PHP developer but I other languages are not scary to me. My hobby is security and I try to learn as much as it's possible how to not be hacked. I like to know how things work. After hours I like playing Dota2 :)
  • Foo

    While your site seems to be reasonably responsive and works on mobile devices, that annoying modal isn’t.

    • adminek

      true, I will fix it asap.

  • Grzegorz

    Great job!

  • Peter

    Is there a reason to separate nginx and PHP into individual containers, other than to provide 3 containers for the tutorial? Would you do this in production?

    • adminek

      Thanks for the comment.
      I am not sure what you are asking about.
      The idea behind containers is to keep them small. That’s why you should keep only 1 service in only 1 container. Thanks to this you can use the same container, in our example php7 in different variants. In this example, I used php7 with Nginx but you can use the same with apache2 or another web server.

      • Peter

        Thanks for the reply. I was thinking of a ‘container’ in terms of a website – so you’d bundle the Symfony code, PHP and webserver together for one deployment. Then if you upgrade the versions of any of these, it only affects this particular site.

        Splitting off the database, Redis etc makes a lot of sense to me as these could be shared (and persistent storage in Docker for the database still makes me nervous)

  • audayls

    Hello adminek!

    First, thank you for your post.

    Your article does not show how do you manage the consumers with Docker. Do you launch consumers into the “php” container or do you use a specific container for that?

    • Enleur

      It should be separate containers for each consumer. So you can easily scale it across your claster

      • adminek

        You are right. My solution is mostly for development or testing env.

  • Saphy

    Hello, nice tutorial!
    If you have multiple microservices (let’s say 3) and you want to run them all for do the FE, do you have to set up at least 3 web + 3 fpm and all them mounting a volumen ?

  • Pingback: webMASTAH.weekly.022 - Dobre praktyki dla początkującego programisty - webMASTAH()

  • Paweł

    Nie udało mi się, mam błąd COPY symfony.conf /etc/nginx/conf.d/symfony.conf
    ERROR: Service ‘web’ failed to build: lstat symfony.conf: no such file or directory
    Gdzie ma być aplikcja symfonowa w jakim folderze? Mam zainstalowanego apache2 mogę jakoś doinstalować tego nginx, to znaczy w taki sposób żeby apache2 nadal działało i żeby przejść ten tutorial?

    • Paweł

      dobra przeszło copy, nie może być spacji za nazwą pliku conf

      • adminek

        super, że się udało rozwiązać problem 🙂

  • Benjamin Vison

    Have you encountered any performance issues using Docker with Symfony2?

    • Bartłomiej Kiełbasa

      Not realy, because Docker is not a virtual but adds an extra layer between app and the host. Some one measured it and it slowed down less than 1 pecent

      • Benjamin Vison

        Yeah but for example when adding a volume to store the application code, let’s say that for example you are running docker on windows, and you are coding your application in windows so you have your application files in let’s say C:/project… in docker you have to add that volume, and when nginx/php attempts to look for the application files it is way slow for me…how do you handle the development process, where do you store the application data?

        • Bartłomiej Kiełbasa

          It’s not Docker’s problem but how you run it 🙂 Docker uses Linux’s features so to run it on Windows or mac you have to…. Install a virtual machina and run Docker there. On production, you should avoid things like that because It’s not optimal from the begining.

          Ps. Thanks for your comments!

          • Benjamin Vison

            got it, that’s something that I haven’t tried… I thought that for Linux you also needed something like Virtual Box in order to run docker… you can run docker containers right on linux without virtualization?

          • Bartłomiej Kiełbasa

            Exactly! On Linux you can install Docker nativly without any additional virtualization. It Just works.