What are the steps to containerize a Laravel 10 application with PHP 8.2 and its MySQL database using Docker?

Andrei Cociug
5 min readFeb 25, 2023

--

Docker is a powerful tool for developers that allows them to create containerized applications. Containerization can help to simplify development and deployment processes, as well as make it easier to run applications consistently across multiple environments. In this article, we will walk through the process of dockerizing a Laravel 10 app with PHP 8.2, MySQL, and Redis.

Prerequisites

Before we begin, make sure you have Docker and Docker Compose installed on your system. To get started, follow the official Docker installation instructions for your operating system.
A Laravel 10 application is also required. If you don’t already have one, you can start one by following the official Laravel documentation.

Step 1: Create a Dockerfile

The first step is to create a Dockerfile for the Laravel app. Create a new directory called docker in the root directory of your Laravel app and then create a new file called Dockerfile and paste the following code:

FROM php:8.2.3-fpm-alpine3.17

# Install required packages
RUN apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
build-base \
libpng-dev \
libzip-dev \
unzip \
linux-headers \
zip \
&& pecl install redis \
&& docker-php-ext-enable redis

# Install PHP extensions
RUN docker-php-ext-install \
pdo_mysql \
gd \
zip

# Set working directory
WORKDIR /srv/app

RUN addgroup -g 1000 -S docker && \
adduser -u 1000 -S docker -G docker

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

RUN set -eux; \
composer clear-cache

COPY ./docker-entrypoint.sh /docker-entrypoint.sh

RUN chmod +x /docker-entrypoint.sh

RUN chown -R www-data:www-data /srv/app

USER docker

# Expose port 9000 for PHP-FPM
EXPOSE 9000

ENTRYPOINT ["/docker-entrypoint.sh"]

# Start PHP-FPM
CMD ["/bin/sh"]

This Dockerfile creates a base image of php:8.2-fpm and installs the Laravel dependencies, such as Zip, Unzip, and the required PHP extensions. It also installs Redis and makes the PHP Redis extension available.

The WORKDIR instruction directs the container’s working directory to /srv/app, where the Laravel app will be installed.

Before starting PHP-FPM, the Dockerfile installs Composer, the app’s dependencies, and the appropriate permissions, and exposes port 9000.

Step 2: Create a docker-compose.yml file

The next step is to create a docker-compose.yaml file that defines the Laravel app’s services and network. Create a new file called docker-compose.yaml in the root directory of your Laravel app and paste the following code:

version: '3.8'

services:
app:
container_name: dockerize-laravel-app
build: ./docker
volumes:
- '.:/srv/app'
command: ["webapp"]
depends_on:
- mysql
networks:
- dockerize-laravel

nginx:
container_name: dockerize-laravel-nginx
image: 'nginx:1.23.3-alpine'
depends_on:
- app
networks:
- dockerize-laravel
ports:
- '80:80'
- '443:443'
volumes:
- './docker/nginx/conf.d:/etc/nginx/conf.d:ro'
- './:/srv/app:ro'

mysql:
image: mysql:8.0.32
container_name: dockerize-laravel-mysql
ports:
- '3306:3306'
env_file:
- ./.env
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_USER: ${DB_USERNAME}
MYSQL_PASSWORD: ${DB_PASSWORD}
networks:
- dockerize-laravel
volumes:
- dockerize-laravel-db-data:/var/lib/postgresql/data

redis:
image: redis:7.0.8-alpine3.17
container_name: dockerize-laravel-redis
ports:
- '6379:6379'
volumes:
- dockerize-laravel-redis-data:/data
networks:
- dockerize-laravel
healthcheck:
test: [ "CMD", "redis-cli", "ping" ]

volumes:
dockerize-laravel-db-data: {}
dockerize-laravel-redis-data: {}

networks:
dockerize-laravel:
driver: bridge

The volumes section defines the two volumes that will be created for the MySQL and Redis data.

The networks section defines the dockerize-laravel network that will be used by all the services.

Step 3: Create a default Nginx configuration file

In the docker-compose.yml file, we have defined a volume to mount the default Nginx configuration file. Under the directory called docker in the root directory of your Laravel app create a new directory called nginx inside it. In the nginxdirectory, create a new file called default.conf and paste the following code:

server {
client_max_body_size 100M;

listen 80 default;
server_name localhost;

root /srv/app/public;
index index.php;

access_log /var/log/nginx/sandbox-access.log;
error_log /var/log/nginx/sandbox-error.log debug;

location / {
# try to serve file directly, fallback to index.php
try_files $uri /index.php?$query_string;
gzip_static on;
}

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

This Nginx configuration file defines a server block that listens on port 80, sets the server name to localhost, and sets the root directory to /srv/app/public . It also defines two location blocks: one for serving static files and one for processing PHP files using FastCGI. The fastcgi_pass directive points to the appservice on port 9000.

Step 4: Create a docker-entrypoint.sh file

The final step is to create a docker-entrypoint.sh file that will be used to start the app service. In the docker directory of your Laravel app, create a new file called docker-entrypoint.sh and paste the following code:

#!/bin/sh
set -e

# shellcheck disable=SC2120
webapp() {
echo "Starting PHP-FPM"
php-fpm
}

case "$1" in
"webapp")
webapp
;;
*)
exec "$@"
;;
esac

This shell script defines a webapp function that starts PHP-FPM and sets it as the default command for the app service.

Step 5: Build and run the containers

This command will run the Dockerfile to build the app service, create volumes for the MySQL and Redis data, and start all the containers. The output in the terminal should indicate that the containers are starting up.

Once the containers are running, you can access your Laravel app by visiting http://localhost in your web browser. If everything was set up correctly, you should see your Laravel app running!

Dockerizing your Laravel app allows you to easily deploy it to different environments while also ensuring that all dependencies are included and correctly configured. With this configuration, you can easily scale your app while managing your database and caching services independently of your app.

I hope this article helped you get your Laravel app running in a Docker container. Have fun coding!

Find boilerplate on GitHub

Find me on LinkedIn

--

--