DEV Community

loading...
Cover image for How to build a clean Docker Symfony 5.2 PHP8 PostegreSQL Nginx project

How to build a clean Docker Symfony 5.2 PHP8 PostegreSQL Nginx project

nicolasbonnici profile image nicolasbonnici ・3 min read

Hey there today we gonna build a boilerplate project using Docker for symfony 5.2 with PHP8, PostgreSQL database engine and nginx as reverse-proxy.

Getting Started

First you need Docker and docker-compose, i am gonna use those versions:

$ docker -v && docker-compose -v
Docker version 19.03.8, build afacb8b7f0
docker-compose version 1.27.4, build 40524192
Enter fullscreen mode Exit fullscreen mode

PosgreSQL

Using docker-compose setup PostgreSQL is very easy we gonna use version 12 from postgres:12 Docker image.

./docker/docker-compose.yml

version: '3.8'

services:
  db:
    container_name: db
    image: postgres:12
    restart: always
    environment:
        POSTGRES_PASSWORD: password
        POSTGRES_DB: testdb
    ports:
        - 15432:5432
Enter fullscreen mode Exit fullscreen mode

And that's it, nothing more, here we just ensure the container will always restart and forward 15432 container port to 5432 local port.

PHP8

We gonna u_se and setup the "php:8.0-fpm" Docker image and setup the PostegreSQL PDO driver.

./docker/php-fpm/Dockerfile

FROM php:8.0-fpm

COPY wait-for-it.sh /usr/bin/wait-for-it

RUN chmod +x /usr/bin/wait-for-it

RUN apt-get update && \
    apt-get install -y --no-install-recommends libssl-dev zlib1g-dev curl git unzip netcat libxml2-dev libpq-dev libzip-dev && \
    pecl install apcu && \
    docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql && \
    docker-php-ext-install -j$(nproc) zip opcache intl pdo_pgsql pgsql && \
    docker-php-ext-enable apcu pdo_pgsql sodium && \
    apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

COPY --from=composer /usr/bin/composer /usr/bin/composer

WORKDIR /var/www

CMD composer i -o ; wait-for-it db:5432 -- bin/console doctrine:migrations:migrate ;  php-fpm 

EXPOSE 9000
Enter fullscreen mode Exit fullscreen mode

Then update docker-compose to connect and add a dependency to db container and expose our ./src folder

./docker/docker-compose.yml

  php-fpm:
    container_name: php-fpm
    build:
      context: ./php-fpm
    depends_on:
      - db
    environment:
      - APP_ENV=${APP_ENV}
      - APP_SECRET=${APP_SECRET}
      - DATABASE_URL=${DATABASE_URL}
    volumes:
      - ./../src/:/var/www
Enter fullscreen mode Exit fullscreen mode

Nginx

Then finally use nginx web server as reverse proxy to our php-fpm container.

./docker/nginx/Dockerfile

FROM nginx:alpine

WORKDIR /var/www

CMD ["nginx"]

EXPOSE 80 443
Enter fullscreen mode Exit fullscreen mode

Add nginx configurations

./docker/nginx/Dockerfile

user  nginx;
worker_processes  4;
daemon off;

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;

    access_log  /var/log/nginx/access.log;
    #access_log /dev/stdout;
    #error_log /dev/stderr;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-available/*.conf;
}

Enter fullscreen mode Exit fullscreen mode

And configure default blocks, one for our php-fpm upstream and an other for the global project respectively on ./docker/nginx/conf.d/default.conf and ./docker/nginx/sites/default.conf.

./docker/nginx/conf.d/default.conf

upstream php-upstream {
    server php-fpm:9000;
}
Enter fullscreen mode Exit fullscreen mode

./docker/nginx/sites/default.conf

server {

    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    server_name localhost;
    root /var/www/public;
    index index.php index.html index.htm;

    location / {
         try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        try_files $uri /index.php =404;
        fastcgi_pass php-upstream;
        fastcgi_index index.php;
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        #fixes timeouts
        fastcgi_read_timeout 600;
        include fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }

    location /.well-known/acme-challenge/ {
        root /var/www/letsencrypt/;
        log_not_found off;
    }
}

Enter fullscreen mode Exit fullscreen mode

The last step is to create a dependency on our php-fpm container in our docker-compose configuration.

./docker/docker-compose.yml

  nginx:
    container_name: nginx
    build:
      context: ./nginx
    volumes:
      - ./../src/:/var/www
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/sites/:/etc/nginx/sites-available
      - ./nginx/conf.d/:/etc/nginx/conf.d
      - ./logs:/var/log
    depends_on:
      - php-fpm
    ports:
      - "80:80"
      - "443:443"
Enter fullscreen mode Exit fullscreen mode

Symfony 5

With a very few configuration we built our stack, now to setup Symfony let create a "src" project root folder and use composer.

composer create-project symfony/skeleton ./src
Enter fullscreen mode Exit fullscreen mode

How to use

To use the stack simply go onto the ./docker folder and run

docker-compose up --build
Enter fullscreen mode Exit fullscreen mode

To go further

Use a CI such like Github Actions or Gitlab CI to build and deploy this project.

Conclusion

With a very few configuration, we built a solid Symfony5 project stack using Docker.

Thank you for reading, you can find this tutorial source code on github: https://github.com/nicolasbonnici/docker-php8-sf5-nginx-pqsql-boilerplate

Discussion (2)

pic
Editor guide
Collapse
mmarton profile image
mmarton

Hi!

Nice article, just a few notes/questions:

  1. you named the nginix config file Dockerfile
  2. it was a bit misleading that you called your working directory src. At first i thought you only mapped the symfony's src folder into the php container.
  3. You map the whole project with vendor and possible node_modules into 2 containers. Wouldn't it be enough just to map the public dir to the nginx?
  4. what is the performance of the config above,

M

Collapse
nicolasbonnici profile image
nicolasbonnici Author

Hey there,

Nope the actual ./docker/nginx/Dockerfile is a very simple docker container build conf from nginx:alpine image.

I totally agree with you, i should rename this folder something like symfony for instance, you can submit a pull request if you want to.

Nope actually no use of npm, and composer vendors directory his located under the folder the actual ./src folder.

These is a development stack, not optimized or production ready, but the build time is very honorable.