As you probably know, I am a big Symfony fan 🙂 In the last few years I used Vagrant to set up my Symfony development environment more or less as described here. But we now have Docker and it’s time to move forward with a new setup. Docker containers are generally more lightweight than Vagrant virtual machines, so starting and stopping them is extremely fast. They also take a lot less disk space.

To setup a Docker container you need a Dockerfile file and to combine several containers we use the docker-compose.yml file. For our environment we will need two containers, one with the latest Ubuntu LTS to host the web server and our project files and one for MySQL.

The first container is defined in the Dockerfile file as below:

FROM ubuntu:16.04
ADD . /app
RUN apt-get update
RUN apt-get install -y php apache2 libapache2-mod-php7.0 php-mysql php-intl git git-core curl php-curl php-xml composer zip unzip php-zip
# Configure Apache
RUN rm -rf /var/www/* \
    && a2enmod rewrite \
    && echo "ServerName localhost" >> /etc/apache2/apache2.conf
ADD vhost.conf /etc/apache2/sites-available/000-default.conf
# Install Symfony
RUN mkdir -p /usr/local/bin
RUN curl -LsS https://symfony.com/installer -o /usr/local/bin/symfony
RUN chmod a+x /usr/local/bin/symfony
# Add main start script for when image launches
ADD run.sh /run.sh
RUN chmod 0755 /run.sh
WORKDIR /app
EXPOSE 80
CMD ["/run.sh"]

Add this file in a new folder. We also need the vhost.conf and run.sh files used in the code from above.

The vhost.conf file is used to configure the apache virtual host:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot /app/my_project/web
    <Directory /app/my_project/web>
        Options -Indexes
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

The run.sh file runs when the container starts and just makes sure that the cache and logs folders are set up before launching the apache web server:

#!/bin/bash
mkdir -p my_project/app/cache my_project/app/logs
touch my_project/app/logs/prod.log
touch my_project/app/logs/dev.log
chgrp -R www-data .
chmod -R g+w my_project/app/cache my_project/app/logs
source /etc/apache2/envvars
tail -F /var/log/apache2/* my_project/app/logs/prod.log my_project/app/logs/dev.log &
exec apache2 -D FOREGROUND

That’s all for our main Ubuntu container, we now need to create the docker-compose.yml file:

version: "2"
services:
    mysql:
        image: mysql:5.7
        container_name: mysqldb
        ports:
            - "4000:3306"
        expose:
            - "3306"
        environment:
            MYSQL_ROOT_PASSWORD: yourrootpassword
    site:
        build: .
        container_name: myproject
        ports:
            - "8080:80"
        expose:
            - "80"
        depends_on:
            - mysql
        volumes:
          - .:/app

This will tell Docker to first start an MySQL 5.7 container, then our Ubuntu container that will be able to access the MySQL container using the mysql host name.

Start everything with the docker-compose up command.

When it’s done, open a new terminal (let the latest docker compose command run, do not stop it) and use the docker ps command to see the running containers:

Now, you can take the id of the Ubuntu container and ssh into it:

docker exec -t -i [ID] bash

Here you will start a new Symfony project as always (you will have to delete the my_project folder created by Docker first):

rm -rf my_project
symfony new my_project 2.8

If you name you project something else (yes, you will probably do that) just replace the all my_folder occurrences in the files and commands above with the actual name of your project.

After you created the new Symfony project, it is better to rebuild the Docker containers so the setup of the cache and logs folders will be as intended. In the terminal window where you launched Docker, press Ctrl+C to stop it then run docker-compose up again.

That’s it! You can now access your new Symfony project using the following URL: http://localhost:8080/. To connect to MySQL you will use the mysql host name:

parameters:
    database_host: mysql
    database_port: null
    database_name: symfony
    database_user: root
    database_password: yourrootpassword

 

Thank you! Please let me know in the comments if you have any suggestions to improve this setup or problems running it.