Dockerize your PHP Laravel, MySQL Application
Recently I came across a gig on Upwork to dockerize a PHP Laravel and MySQL application. Upon finding no significant blog or video to dockerize the Laravel application, I did it myself and now I am documenting the same for others. This is not a guide to do it for high scale production level environments. It is just to get started with your setup.
TL;DR
If you already know everything about Docker, Nginx, PHP, and Laravel and just want the docker-compose, go to the GitHub repository give it a star, replace the code in the application folder and run docker-compose up — build now you can access your application on localhost:8080
We will need 3 different services for this setup
- Nginx Server
- PHP Server
- MySQL Server
Directory Structure
Let’s create a folder called dockerize_laravel that will have all the files related to this dockerized Laravel application. It will look something like this on the root level. The application folder will contain all the files related to Laravel, basically the Laravel application. For this tutorial, I have just created a blank application but you can just replace it with your application code. The Nginx and PHP folders will contain the configurations related to Nginx and PHP.
Nginx Service
We will be using Nginx as the reverse proxy, the role of Nginx will be to listen on port 80 and pass the request to the PHP server so that it can process that request.
In the root folder create a file called docker-compose.yml and add the following code to it.
version: "3"
services:
nginx:
build:
context: .
dockerfile: nginx/Dockerfile
ports:
- "8080:80"
networks:
- internal
volumes:
- ./application/:/var/www/html/
- ./logs/nginx:/var/log/nginx/
container_name: nginx
networks:
internal:
driver: bridge
Create a folder called Nginx in the dockerize_laravel folder and create a file called Dockerfile in it having the following code. This file creates a docker container from nginx:alpine image and copies the Nginx configuration files from the local disk to the docker container.
FROM nginx:alpine
ADD nginx/default.conf /etc/nginx/conf.d
ADD nginx/fastcgi-php.conf /etc/nginx
Create a file called fastcgi-php.conf in the Nginx folder and the following code in it. This file defines the FastCGI config for handing PHP requests in Nginx.
# regex to split $uri to $fastcgi_script_name and $fastcgi_path
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
# Check that the PHP script exists before passing it
try_files $fastcgi_script_name =404;
# Bypass the fact that try_files resets $fastcgi_path_info
# see: http://trac.nginx.org/nginx/ticket/321
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
fastcgi_index index.php;
include fastcgi.conf;
Create a file called default.conf in the nginx folder and the following code in it. This file defines the Nginx configuration for the reverse proxy which listens to the request on port 80 and passes it to the PHP service which is listening on port 9000.
server {
listen 80;
listen [::]:80;
root /var/www/html/public/;
index index.php index.html index.htm index.nginx-debian.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# location / {
# index index.php index.html;
# }
location ~ \.php$ {
include fastcgi_params;
include fastcgi-php.conf;
fastcgi_pass php:9000;
}
}
Now your Nginx container configuration is completed.
PHP Service
This one is simple. Just create a folder called PHP in the dockerize_laravel folder and create a file called Dockerfile in it with the following code.
FROM php:8.1-fpm
# Install system dependencies
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install PHP extensions
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
This will create a docker container from PHP fpm image (make sure to check the correct fpm version required for your Laravel version else you will end up with an error). This will also install composer and all the required PHP extensions in the container.
Now add the following code in the docker-compose.yml file
php:
build:
context: .
dockerfile: php/Dockerfile
networks:
- internal
volumes:
- ./application/:/var/www/html/
- ./logs/php.log:/var/log/fpm-php.www.log
container_name: php
expose:
- "9000"
MySQL Service
Now this one is the simplest of all. Add the following code in the docker-compose.yml file and your MySQL service is done.
Note: I am using Macbook AIR M1 so had to add platform: linux/x86_64 in it. If you are not using Macbook AIR M1 you might try removing it if you get any errors.
mysql:
container_name: db
restart: always
image: mysql:latest
platform: linux/x86_64
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: 'root'
MYSQL_USER: 'sushant'
MYSQL_PASS: 'password'
volumes:
- ./db-data:/var/lib/mysql
networks:
- internal
Final docker-compose.yml
This final docker-compose.yml will look something like this.
version: "3"
services:
nginx:
build:
context: .
dockerfile: nginx/Dockerfile
ports:
- "8080:80"
networks:
- internal
volumes:
- ./application/:/var/www/html/
- ./logs/nginx:/var/log/nginx/
container_name: nginx
php:
build:
context: .
dockerfile: php/Dockerfile
networks:
- internal
volumes:
- ./application/:/var/www/html/
- ./logs/php.log:/var/log/fpm-php.www.log
container_name: php
expose:
- "9000"
mysql:
container_name: db
restart: always
image: mysql:latest
platform: linux/x86_64
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: 'root'
MYSQL_USER: 'sushant'
MYSQL_PASS: 'password'
volumes:
- ./db-data:/var/lib/mysql
networks:
- internal
networks:
internal:
driver: bridge
Modify the MySQL configuration in the .env file as follows.
Now run the following command from the dockerize_laravel folder to start all the 3 servicesdocker-compose up --build
Now open up a new terminal tab and cd into the dockerize_laravel folder from there run the following commands to do a composer install in the containerdocker-compose exec php sh
cd /var/www/html
composer install
Run the following command to generate the application key in the .env file
php artisan key:generate
Your beautiful Laravel application is up and running on localhost:8080
Right now no database is present in the MySQL container so you might face some errors because of it. To resolve that you can run the following commands to create the database and run the migrations.
In a new terminal window go to the dockerize_laravel folder and run the following commands
Now your database named laravel as mentioned in the .env file is created and ready to be used.
You can now connect to the php container and run the migrations
If this helped you please share this with your friends.