Using Docker for Slim 4 application development environment
Tags: slim, php, routing, docker
Published: 2021-08-22 16:59:59

In the first part of the series we write a small Slim 4 application to know how the framework works, however in real world applications we need to know how to deal with more complicated problems instead of printing a message on a web page.

I believe, as software developers we need to prepare the work environment first and because we have a number of environments where the code we wrote will be running we need to be sure that those environment characteristics are common to minimize the number of surprises.

Also, as team members, having the same development environment could be helpful to ensure we are all having the same results without any impact from the local environment.

Fortunately, [Docker](https://www.docker.com/) can help to achieve those goals.

## Create docker directory

Create a new directory named `docker`, this directory will contain Docker containers definitions and doesn’t have to be named `docker`:
```shell
$ mkdir docker
```

## Define a PHP 8 container
1- Inside the `docker` directory, add a new subdirectory named `php`:

```shell
$ mkdir -p docker/php
```
2- Create a new `Dockerfile` (yes without extension) file 

```shell
touch docker/php/Dockerfile
```

Open the php Dockerfile and add the following instructions:

```docker
FROM php:8.1-fpm

RUN apt update \
    && apt install -y zlib1g-dev g++ git libicu-dev zip libzip-dev zip libpq-dev \
    && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \
    && docker-php-ext-install intl opcache pdo pdo_pgsql \
    && pecl install apcu \
    && docker-php-ext-enable apcu \
    && docker-php-ext-configure zip \
    && docker-php-ext-install zip

WORKDIR /var/www/slim_app

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

RUN git config --global user.email "you@example.com" \
    && git config --global user.name "Your Name"
```

> Note: Make sure to replace git credentials in the last two lines with your git credentials

The instructions above will scaffold a PHP container from a `PHP 7.4 FPM` image and:
- Install PHP extension that our Slim application depends on
- Sets the working directory of the container to  `/var/www/slim_app`
- Install composer

## Define a NGINX web server container
Unlike the PHP image, only NGINX default configuration is needed inside a subdirectory in `docker` directory:

### Add new `nginx` directory:
```shell
$ mkdir -p docker/nginx
```

### Add the default configuration file:
```shell
$ touch docker/nginx/default.conf
```

Edit ` docker/nginx/default.conf` with the following:

```
server {

    listen 80;
    index index.php;
    server_name localhost;
    root /var/www/slim_app/public;
    error_log /var/log/nginx/project_error.log;
    access_log /var/log/nginx/project_access.log;

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

    location ~ ^/index\\.php(/|$) {
        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;

        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
        fastcgi_busy_buffers_size 256k;

        internal;
    }

    location ~ \\.php$ {
        return 404;
    }

}
```
This is the simplest NGINX required configuration  to run a PHP application, note that it maps `fastcgi_pass` to port 9000 in the PHP container we defined previously.

## Let’s compose the containers images

To use the PHP and NGINX defined containers we need to create `docker-compose.yml` in the root folder of the application:

```yaml
version: "3.8"

services:
  php:
    container_name: slim_php
    build:
      context: ./docker/php
    ports:
      - '9000:9000'
    volumes:
      - .:/var/www/slim_app

  nginx:
    container_name: slim_nginx
    image: nginx:stable-alpine
    ports:
      - '8080:80'
    volumes:
      - .:/var/www/slim_app
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - php
```

Let see what we have here for the __PHP container__:
- Unlike the NGINX container configuration, PHP container doesn’t have an image key but a build context in order to use the `docker/php/Dockerfile` to build the container.
- Port 9000 of the computer is mapped to 9000 of the container
- Volumes is declared to store the data generated by the container, in the case of this example it will store the Slim application code in the project.


__For NGINX__
- nginx:stable-alpine will be pulled from the [docker-hub](https://hub.docker.com/) to build the container.
- The port 8080 of the computer is mapped to port 80 of the container.
- Declare the required volumes to persist the NGINX default configuration file and the PHP code for the application.

## Build the containers

Run the following command to build the containers:
```
$ docker-compose up -d --build
```

Once containers are successfully built the terminal should print message like the following screenshot:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hxbmngbm47eqtpb6ximi.png)

To make sure that the containers are up and running open the Docker Desktop app, it should shows that the containers are running like in the screenshot below:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l6aqwlt7ob89u8rsg39q.png)

It is possible to use the command line to know the status of the containers:

```shell
$ docker ps
```

Should print something like:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bsfyvi2ufdcpc1oidwma.png)

Now if you visit the URL `localhost:8080`, put the port you configured for NGINX, should run the Slim application we built in the first part.

GitHub repository has the code in this part in [development-environment-part-2](https://github.com/cherifGsoul/slim-from-scratch/tree/development-environment-part-2).