How to build a clean Docker Symfony 5.2 PHP8 PostgreSQL Nginx project
Tags: php8, symfony, docker, postgres
Published: 2021-02-09 08:50:49

---
title: How to build a clean Docker Symfony 5.2 PHP8 PostgreSQL Nginx project
published: true
description: Use docker-compose to build a clean Docker Symfony 5.2 PHP8 PostgreSQL Nginx boilerplate project
tags: php8,symfony,docker,postgresql
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/4s6iutf0pg4zy6qk1ea1.png
---

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:

```bash
$ docker -v && docker-compose -v
Docker version 19.03.8, build afacb8b7f0
docker-compose version 1.27.4, build 40524192
```

### PosgreSQL

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

./docker/docker-compose.yml
```yaml
version: '3.8'

services:
  db:
    container_name: db
    image: postgres:12
    restart: always
    environment:
        POSTGRES_PASSWORD: password
        POSTGRES_DB: testdb
    ports:
        - 15432:5432
```
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
```docker
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
```
Then update docker-compose to connect and add a dependency to db container and expose our ./src folder

./docker/docker-compose.yml
```yaml
  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
```

### Nginx

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

./docker/nginx/Dockerfile
```docker
FROM nginx:alpine

WORKDIR /var/www

CMD ["nginx"]

EXPOSE 80 443
```
Add nginx configurations

./docker/nginx/Dockerfile
```nginx
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;
}

```
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
```nginx
upstream php-upstream {
    server php-fpm:9000;
}
```

./docker/nginx/sites/default.conf
```nginx
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;
    }
}

```

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

./docker/docker-compose.yml
```yaml
  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"
```
### 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.

```bash
composer create-project symfony/skeleton ./src
```

### How to use 

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

```
docker-compose up --build
```

### 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