How to dockerize a Laravel App

⚠️ Caution: This post assumes Docker cli has been installed to your environment.

If you have a working Laravel project and you want to dockerize the app, you are in the right place. To dockerize your app we will need three files:

  1. Dockerfile
  2. .dockerignore
  3. nginx.conf

Dockerfile will be used to generate the Docker image and .dockerignore file will be used for excluding files from the image. We will use nginx HTTP server for the image so we will need an nginx configuration file which is named nginx.conf. Let’s get started by creating a Dockerfile in the project root directory. I have added comments to explain the directives line by line.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
FROM php:fpm-buster

USER root

# Install php related packages
RUN apt update
RUN apt install -y git curl libpng-dev libonig-dev libxml2-dev zip unzip

RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd

RUN pecl install -o -f redis \
    &&  rm -rf /tmp/pear \
    &&  docker-php-ext-enable redis

# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Install NGINX
RUN apt install -y nginx

# Copy NGINX configuration file
COPY conf/nginx.conf /etc/nginx/sites-enabled/default

# Copy project files
WORKDIR /srv
RUN chown -R www-data:www-data /srv
COPY --chown=www-data:www-data . .

# Change User
USER www-data

# Install Project dependencies
RUN composer require

# Execution Command and exposed port
USER root
CMD nginx && php-fpm
EXPOSE 80

Also we need .dockerignore file. Let’s create it in the project root. Therefore, we will create an image and that image will not contain the Dockerfile and the vendor folder. Also excluding .env file is also critical for security reasons.

1
2
3
vendor/
.env
Dockerfile

The last step will be creating a folder named conf and create a file nginx.conf.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
server {
    listen 80;
    listen [::]:80;
    root /srv/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico {
        access_log off; log_not_found off;
    }
    location = /robots.txt {
        access_log off; log_not_found off;
    }

    error_page 404 /index.php;

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass localhost:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

If you want, you can build and test your docker image with these commands:

1
2
docker build -t project-name .
docker run -p 3000:80 --env-file .env project-name