Symfony 6 with docker
Published: 2022-11-19 16:53:42

In this project the intention is to create a project in symfony 6, with docker, mariadb, phpmyadmin.

To begin with, we will create a page structure similar to the image:
![folder struct](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xaota2x9z9nqu6ncyul8.png)

Make the folders, and some files:

```bash
mkdir symfony-6-docker && touch .env && touch .gitignore 
&& touch docker-compose.yml && touch README.md 
&& mkdir docker && cd docker && mkdir database 
&& mkdir logs && mkdir nginx && mkdir php-fpm 
&& cd database && mkdir data && touch Dockerfile  
&& touch init.sql && cd ../logs && mkdir nginx 
&& cd nginx && touch access.log && touch error.log 
&& touch .gitignore && cd ../../nginx && touch Dockerfile 
&& touch nginx.conf && mkdir conf.d && mkdir sites 
&& cd  conf.d && touch default.conf && cd ../sites 
&& touch default.conf && cd ../../php-fpm 
&& touch wait-for-it.sh && touch Dockerfile && cd ../..
```


After that, it is necessary to verify that we have everything necessary to create a symfony 6 project.
For this we run the command.
```symfony
symfony check:requirements
```
When you get the same answer as the picture, it means that everything is fine.

![approve requirements](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7n4ygq4lutbycqj2n2xd.png)

Having everything ok, we create the project in the project root.
```symfony
 symfony new symfony --version="6.1.*"
```
With your preferred IDE, open the project in the root, and copy the contents of the files.

- docker-composer.yml
```yaml
# docker-composer.yml
version: '3'

services:
  database:
    build:
      context: ./docker/database
    environment:
      - MYSQL_DATABASE=${DATABASE_NAME}
      - MYSQL_USER=${DATABASE_USER}
      - MYSQL_PASSWORD=${DATABASE_PASSWORD}
      - MYSQL_ROOT_PASSWORD=${DATABASE_ROOT_PASSWORD}
    ports:
      - "3309:3306"
    volumes:
      - ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
      - ./docker/database/data:/var/lib/mysql

  phpmyadmin:
        depends_on:
            - database
        image: phpmyadmin
        links:
          - database
        restart: always
        ports:
            - 8080:80
        environment:
            PMA_HOST: database
            PMA_PORT: 3306
            PMA_ARBITRARY: 1

  php-fpm:
    build:
      context: ./docker/php-fpm
    depends_on:
      - database
    environment:
      - APP_ENV=${APP_ENV}
      - APP_SECRET=${APP_SECRET}
      - DATABASE_URL=mysql://${DATABASE_USER}:${DATABASE_PASSWORD}@database:3306/${DATABASE_NAME}?serverVersion=5.7
    volumes:
      - ./symfony:/var/www

  nginx:
    build:
      context: ./docker/nginx
    volumes:
      - ./symfony:/var/www
      - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./docker/nginx/sites/:/etc/nginx/sites-available
      - ./docker/nginx/conf.d/:/etc/nginx/conf.d
      - ./docker/logs:/var/log
    depends_on:
      - php-fpm
    ports:
      - "80:80"
      - "443:443"
```

- .env

```env
DATABASE_NAME=symfony
DATABASE_USER=appuser
DATABASE_PASSWORD=apppassword
DATABASE_ROOT_PASSWORD=secret

APP_ENV=dev
APP_SECRET=change-to-your-secret-value
```
- docker/database/Dockerfile

```docker
FROM mariadb:latest

CMD ["mysqld"]

EXPOSE 3306
```

- docker/database/init.sql

```sql
CREATE DATABASE IF NOT EXISTS symfony;
USE symfony;
```

- docker/nginx/Dockerfile

```docker
FROM nginx:alpine

WORKDIR /var/www

CMD ["nginx"]

EXPOSE 80 443
```

- docker/nginx/nginx.conf

```conf
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;
}
```

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

```conf
upstream php-upstream {
    server php-fpm:9000;
}
```

- docker/nginx/sites/default.conf

```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;
    }
}
```

- docker/php-fpm/Dockerfile

```docker
FROM php:fpm-alpine

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

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

RUN apk --update --no-cache add git

RUN apk add bash

RUN docker-php-ext-install pdo_mysql

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

WORKDIR /var/www

CMD composer install ; wait-for-it database:3306 -- bin/console doctrine:migrations:migrate ;  php-fpm 

EXPOSE 9000
```

- docker/php-fpm/wait-for-it.sh

```bash
#!/bin/sh

TIMEOUT=15
QUIET=0

echoerr() {
  if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi
}

usage() {
  exitcode="$1"
  cat << USAGE >&2
Usage:
  $cmdname host:port [-t timeout] [-- command args]
  -q | --quiet                        Do not output any status messages
  -t TIMEOUT | --timeout=timeout      Timeout in seconds, zero for no timeout
  -- COMMAND ARGS                     Execute command with args after the test finishes
USAGE
  exit "$exitcode"
}

wait_for() {
  for i in `seq $TIMEOUT` ; do
    nc -z "$HOST" "$PORT" > /dev/null 2>&1
    
    result=$?
    if [ $result -eq 0 ] ; then
      if [ $# -gt 0 ] ; then
        exec "$@"
      fi
      exit 0
    fi
    sleep 1
  done
  echo "Operation timed out" >&2
  exit 1
}

while [ $# -gt 0 ]
do
  case "$1" in
    *:* )
    HOST=$(printf "%s\n" "$1"| cut -d : -f 1)
    PORT=$(printf "%s\n" "$1"| cut -d : -f 2)
    shift 1
    ;;
    -q | --quiet)
    QUIET=1
    shift 1
    ;;
    -t)
    TIMEOUT="$2"
    if [ "$TIMEOUT" = "" ]; then break; fi
    shift 2
    ;;
    --timeout=*)
    TIMEOUT="${1#*=}"
    shift 1
    ;;
    --)
    shift
    break
    ;;
    --help)
    usage 0
    ;;
    *)
    echoerr "Unknown argument: $1"
    usage 1
    ;;
  esac
done

if [ "$HOST" = "" -o "$PORT" = "" ]; then
  echoerr "Error: you need to provide a host and port to test."
  usage 2
fi

wait_for "$@"
```
After copying all the files, go to the root of the project, and run:
`
docker-compose up -d
`
Link to the project:
[symfony project](http://localhost)

![show symfony](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4gwhdfbbhmlccrphd0od.png)

Link to the phpmyadmin:
[phpmyadmin](http://localhost:8080)

![image phpmyadmin](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9lx4ehu7rvcd0338b15e.png)


The project link on GitHub is:
[symfony-6-docker](https://github.com/slns/symfony-6-docker)