DEV Community

Henri Sekeladi
Henri Sekeladi

Posted on

Dockerfile for PHP Laravel

In this article we will create an Image of Docker Container for Laravel application. In the main folder of laravel, we created a folder called docker. Inside that folder we created some file configuration. In this case we use postgreSQL as database server.
 
Let's begin..

Dockerfile

Dockerfile located on the main laravel project. We used debian bullseye as base image.

# basic container
FROM php:8.3-fpm-bullseye

# setup user as root
USER root

# set working directory
WORKDIR /var/www

# install postgresql client 15
RUN apt-get update \
    && apt-get -y install gnupg2 lsb-release wget curl \
    && sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' \
    && wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
    && apt-get update

# install supervisor, postgresql libs and other libs of php
RUN apt-get install -y net-tools supervisor nginx -y \
    && apt-get install -y libpq-dev libgmp-dev \
    && apt-get install -y --no-install-recommends postgresql-client \
    # gd
    && apt-get install -y libzip-dev zlib1g-dev libpng-dev \
    && docker-php-ext-configure gd  \
    && docker-php-ext-install gd \
    && docker-php-ext-install gmp \
    # Install Postgre PDO
    && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \
    && docker-php-ext-install pdo pdo_pgsql pgsql \
    # option for install mysql as database
    # && docker-php-ext-install mysqli \
    # && docker-php-ext-enable mysqli \
    # opcache
    && docker-php-ext-enable opcache \
    # exif
    && docker-php-ext-install exif \
    && docker-php-ext-install sockets \
    && docker-php-ext-install pcntl \
    && docker-php-ext-install bcmath \
    # zip
    && docker-php-ext-install zip \
    # clean repo
    && apt-get autoclean -y \
    && rm -rf /var/lib/apt/lists/* \
    && rm -rf /tmp/pear/

# copy files of laravel
COPY . /var/www

# copy configuration of php, nginx and php-fpm
COPY ./docker/local.ini /usr/local/etc/php/local.ini
COPY ./docker/nginx.conf /etc/nginx/nginx.conf
COPY ./docker/www.conf /usr/local/etc/php-fpm.d/www.conf

# create log files
RUN touch /var/www/storage/logs/schedule.log
RUN touch /var/www/storage/logs/queue.log

# copy supervisor configuration
COPY ./docker/supervisord.conf /etc/supervisor/conf.d/

# setup composer and laravel
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN composer install --working-dir="/var/www"

# change level security of openssl
RUN sed -i 's/SECLEVEL=2/SECLEVEL=1/g' /etc/ssl/openssl.cnf

# generate passport keys if needed
#RUN php artisan passport:keys

#export port of the application
EXPOSE 80

# set permission on laravel directory
RUN chmod +rwx /var/www
RUN chown -R www-data:www-data /var/www/storage
RUN chown -R www-data:www-data /var/www/bootstrap
RUN chmod -R 775 /var/www/storage
RUN chmod -R 775 /var/www/bootstrap

RUN ["chmod", "+x", "docker/post_deploy.sh"]
CMD [ "sh", "docker/post_deploy.sh" ]
Enter fullscreen mode Exit fullscreen mode

local.ini

located on docker folder. Reconfigure upload_max_filesize and some other value, included memory_limit.

upload_max_filesize=40M
post_max_size=40M
max_execution_time=180
memory_limit=-1
date.timezone = "Asia/Jakarta"
expose_php = off
Enter fullscreen mode Exit fullscreen mode

nginx.conf

located on docker folder. We setup one serverblock as default nginx virtualhost.

user root;
worker_processes  auto;

events {
    worker_connections  1024;
}

http {
    access_log    /dev/stdout;
    include       mime.types;
    default_type  application/octet-stream;

    server {
        # we use port 80 here to work with our docker config but you can configure it to any port you want, just remember to update the dockerfile accordingly
        listen 80;

        index index.php index.html;

        # your application here
        server_name app;

        error_log  /var/log/nginx/error.log;

        access_log /var/log/nginx/access.log;

        add_header X-Frame-Options "SAMEORIGIN" always;
        server_tokens off;
        add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
        add_header X-XSS-Protection "1; mode=block";
        add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;

        # this should be the path of your public folder in laravel which from our dockerfile it would be /var/www/public
        root /var/www/public;

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

        location / {
         try_files $uri $uri/ /index.php?$query_string;
               gzip_static on;
        }
  }
}
Enter fullscreen mode Exit fullscreen mode

supervisord.conf

located on docker folder. We included supervisor configuration to run our queue on laravel application.

[program:schedule-run]
process_name=%(program_name)s_%(process_num)02d
command=/bin/bash -c "while [ true ]; do (php /var/www/artisan schedule:run --verbose --no-interaction &); sleep 60; done"
autostart=true
autorestart=true
user=www-data
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/storage/logs/schedule.log
stopwaitsecs=60

[program:test-01-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/artisan queue:work --queue=listener,default --tries=10
autostart=true
autorestart=true
user=www-data
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/storage/logs/queue.log
Enter fullscreen mode Exit fullscreen mode

www.conf

located on docker folder. We also reconfigure php-fpm configuration.

[www]
user = www-data
group = www-data
listen = 127.0.0.1:9000

pm = static
pm.max_children = 300
pm.start_servers = 40
pm.min_spare_servers = 20
pm.max_spare_servers = 60
pm.max_requests = 500
Enter fullscreen mode Exit fullscreen mode

post_deploy.sh

located on docker folder. We run supervisor, php-fpm and nginx on this script.

#!/bin/sh

# update application cache
php artisan optimize

# start the application
supervisord -c  "/etc/supervisor/supervisord.conf" && php-fpm -D &&  nginx -g "daemon off;"
Enter fullscreen mode Exit fullscreen mode

Build the Image

docker build .

OR with tag

docker build -t sampleapp:v1 .
Enter fullscreen mode Exit fullscreen mode

Run a Container

docker container run -d -p 8080:80 [docker_image]
docker container run -d -p 8080:80 sampleapp:v1
Enter fullscreen mode Exit fullscreen mode

Hopefully this article helps you!

Top comments (0)