How to setup docker-compose for Symfony projects
Tags: docker, symfony, php
Published: 2022-06-18 10:54:40

## [OPTIONAL] Create symfony project
For this example, we create a simple symfony project using composer `create-project` command using package `symfony/skeleton`:

```bash
composer create-project symfony/skeleton example
```

If you don't have composer installed, you can find how to do it in [it's official website](https://getcomposer.org/doc/00-intro.md)

## Create PHP-FPM Dockerfile
Create a file named `Dockerfile` in your project root and write the following content:

```
FROM php:8.1-fpm

COPY --from=composer /usr/bin/composer /usr/bin/composer
```
In this example we are using `php:8.1-fpm` image from [php official images](https://hub.docker.com/_/php?tab=description&page=1) but other FPM images are valid too if its PHP version satisfies symfony project requirements.

In order to manage composer dependencies, we copy composer binary from composer official image using [multi-stage builds](https://docs.docker.com/develop/develop-images/multistage-build/#use-an-external-image-as-a-stage)

## Create nginx configuration
Create `nginx.conf` file in your project root and write the following content:

```
events {
    worker_connections 1024;
}

http {
    server {
        server_name  example.app;
        root /var/www/app/public;

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

        location ~ ^/index\.php(/|$) {
            fastcgi_pass example_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 /var/log/nginx/api_error.log;
        access_log /var/log/nginx/api_access.log;
    }
}

```

The important things here are:

- `root /var/www/app/public` defines the directory where de index file is located.
- `fastcgi_pass example_php:9000` instructs nginx to execute PHP scripts using server `example_php` and port `9000`.


## Puting all together
To comunicate nginx with php, we create `docker-compose.yaml` file in project root with the following content:

```
services:
  example_nginx:
    container_name: example_nginx
    image: nginx:1.21.3-alpine
    restart: on-failure
    volumes:
      - './:/var/www/app:ro'
      - './nginx.conf:/etc/nginx/nginx.conf:ro'
    ports:
      - "9081:80"
    depends_on:
      - example_php

  example_php:
    container_name: example_php
    build:
      context: .
    working_dir: /var/www/app/
    volumes:
      - './:/var/www/app/'
```

### example_nginx

#### image
Indicates docker-compose the image that should be used to create the container. You can find more official images [here](https://hub.docker.com/_/nginx)

#### restart
Indicates when should the container be restarted. You can find more info in [compose specification](https://docs.docker.com/compose/compose-file/#restart)

#### volumes
Makes files available for the service container. In this case, we are using two volumes:

- `'./:/var/www/app:ro'` that binds project files to `/var/www/app` directory in readonly mode
- `'./nginx.conf:/etc/nginx/nginx.conf:ro'` that binds nginx configuration file to `/etc/nginx/nginx.conf` in readonly mode

You can find more info about volumes [here](https://docs.docker.com/compose/compose-file/#volumes).

#### ports
Binds container port `80` to localhost `9081`. This allows us to access out symfony application using URL `http://localhost:9081`.

You can find more info about ports [here](https://docs.docker.com/compose/compose-file/#ports)

#### depends_on
Expresses that this service dependens on service `example_php`. Remember that we configured nginx to use `example_php` as `fastcgi_pass` server.

You can find more info about `depends_on` [here](https://docs.docker.com/compose/compose-file/#depends_on)

### example_php

#### context
Defines the path to the directory where the Dockerfile is located. In this case, we have both Dockerfile and docker-compose.yml in the same directory and that's why we simple use `.`.

You can find more info about build configuration [here](https://docs.docker.com/compose/compose-file/build/#context-required)

#### working_dir
Sets the application root directory as working directory to simplificate running application commands using `docker exec`

#### volumes
In this service, we make all application files available in read and write mode in order to allow write operations like cache generation and install dependencies.

## Runing the app
To run the app, we just need to run `docker-compose up` and access our app using the URL `http://localhost:9081`.