The easy way to install Symfony with Docker
Welcome to my first article !
I’m Oumaima, a software engineer with a passion for sharing knowledge, always eager to learn more .. until now I don’t know much but I’ll be sharing anyway :)
The picture might make it seem like we’re about to feed Symfony to our friendly dolphin, but don’t worry it’s not the case :)
I’m just sharing with you my super method to install Symfony 6.x with Docker.
Just so you know, this isn’t the only way, it’s one approach among many. While I’ll be using Composer and Nginx, Symfony provides other methods such as using the Symfony console and the internal Symfony server mentioned in the documentation.
Let’s dive in!
1/ Create your docker-compose.yml setup
To begin our Symfony adventure, we’ll start by creating a docker-compose.yml
file. This file will orchestrate the deployment of our Symfony 6.x application. All we need are three essential components: PHP 8.x, a web server (Nginx in our case but you can use Apache as well), and a database MYSQL (which we'll simply call 'db' in our Docker setup).
#docker-compose.yml
version: "3.8"
services:
php:
build: ./docker/php
volumes:
- ./app:/var/www/html
networks:
- symfony
nginx:
build: ./docker/nginx
ports:
- "80:80"
volumes:
- ./app:/var/www/html
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
networks:
- symfony
db:
image: mysql:8.0.33
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: symfony
MYSQL_USER: symfony
MYSQL_PASSWORD: secret
networks:
- symfony
networks:
symfony:
In this docker-compose.yml file, we define three crucial services: php, nginx, and db. Let’s break down their roles:
php: Well, of course, we won’t be building a Symfony project without PHP! ;)
We’ll be using the php:8.x-fpm image, for Symfony 6.3 you can use 8.1 or higher.
nginx: We employ the official Nginx image, exposing port 80.
db: For the database, we use the mysql:8.x image and configure it by setting environment variables for the MySQL root password, database name, user, and password which will be defined in our .env file
The networks section introduces a custom network named symfony. This network enables seamless communication between our services.
With our Docker composition in place, we’re ready to move on to the next step.
2/ Create your PHP Dockerfile
For organization purposes, we’ll start by creating a directory structure. Inside a directory called “docker,” create another directory named “php.” In this “php” directory, we’ll define our Dockerfile for PHP. This Dockerfile, located at /docker/php, is where we'll handle PHP extension installation.
Here’s the content of the Dockerfile:
#docker/php
FROM php:8.2-fpm-buster
RUN apt-get update && apt-get install -y \
gnupg \
g++ \
procps \
openssl \
git \
unzip \
zlib1g-dev \
libzip-dev \
libfreetype6-dev \
libpng-dev \
libjpeg-dev \
libicu-dev \
libonig-dev \
libxslt1-dev \
acl \
&& echo 'alias sf="php bin/console"' >> ~/.bashrc
RUN docker-php-ext-configure gd --with-jpeg --with-freetype
RUN docker-php-ext-install \
pdo pdo_mysql zip xsl gd intl opcache exif mbstring
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
WORKDIR /var/www/symfony
In this Dockerfile, we:
- Use the
php:8.2-fpm-buster
as our base image. - Update the package list and install various dependencies required for Symfony and PHP extensions.
- Configure and install PHP extensions necessary for Symfony, such as pdo, pdo_mysql, zip, xsl, gd, intl, opcache, exif, and mbstring.
- Set up an alias for Symfony’s console command, making it more convenient to run Symfony console commands.
- Install Composer to manage PHP dependencies.
We can also add an instruction to change the configuration of php.ini as well by adding :
COPY php.ini /usr/local/etc/php/conf.d/docker-php-config.ini
in the Dockerfile and to create in the php directory a php.ini with your custom configuration.
With these Dockerfile instructions, we’re ready to build our PHP is ready to run !
3/ Create your Nginx configuration
Inside the docker
directory, create a nginx
directory. In this nginx
directory, create an nginx.conf
file with the following content:
#docker/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
client_max_body_size 0;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
gzip on;
include /etc/nginx/conf.d/*.conf;
}
This nginx.conf
file sets up Nginx configurations, including user, worker processes, error logging, event handling, HTTP configurations, and more.
Still inside the docker/nginx
directory, create a Dockerfile
with the following content:
#docker/nginx/Dockerfile
FROM nginx:1.21-alpine
COPY nginx.conf /etc/nginx/
COPY templates /etc/nginx/templates/
RUN echo "upstream php-upstream { server php:9000; }" > /etc/nginx/conf.d/upstream.conf
EXPOSE 80
EXPOSE 443
Don’t worry, you’re not the only one who thinks Dockerfiles are written in an alien language at first!
So, let me break down what I’ve learned from this Dockerfile:
we’re using the official Nginx Alpine image as our base. We copy our custom nginx.conf
to Nginx's configuration directory and create an upstream configuration to point to the PHP-FPM service, ensuring our services are in sync.
Than, Create a directory named templates
inside the docker/nginx
directory. I choose to name it templates, if you’re feeling adventurous, go ahead and name it “toto,” but be sure to adjust your Dockerfile accordingly otherwise nothing will work :( .
Inside the templates
directory, create a default.conf.template
file with the following content:
#docker/nginx/templates/default.conf.template
server {
listen 80;
server_name localhost;
root /var/www/symfony/public;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ ^/index\.php(/|$) {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Max-Age' 1728000 always;
add_header 'Content-Type' 'text/plain; charset=utf-8' always;
add_header 'Content-Length' 0 always;
return 204;
}
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
fastcgi_pass php:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
internal;
}
location ~ \.php$ {
return 404;
}
error_log /dev/stdout info;
access_log /var/log/nginx/project_access.log;
}
This default.conf.template
file configures Nginx to serve your Symfony application. It sets up the routes and handles PHP requests via FastCGI.
Your Docker directory structure should now look like this :
4/ Create your .env file
At the same level of your docker-compose.yml create .env
#.env
COMPOSE_PROJECT_NAME=symfony
MYSQL_ROOT_PASSWORD=root
MYSQL_DATABASE=symfony
MYSQL_USER=user
MYSQL_PASSWORD=root
You see I used a very strong password for my project :D but please, don’t follow my lead and use these credentials in a production environment..
5/ Start your Docker
Now that everything is set up, navigate to the root directory (where your docker-compose.yml
is located) in your terminal, and execute the following command to start your Docker containers. This command will also rebuild the containers if necessary:
docker-compose up --build
6/ Install the Symfony project
To install the Symfony project within your Docker environment, access the PHP container using the following command:
docker-compose exec php bash
Inside the container PHP, use Composer to create a new Symfony project. Here, we’ll create a Symfony project named symfony
composer create-project symfony/skeleton:"6.3.*" symfony
Ensure that your docker
directory and docker-compose.yml
are located within your project directory. Your project structure should resemble this:
With these steps completed, your Symfony project is now up and running within a Dockerized environment.
Now go to http://localhost:80 and voilà enjoy !!