How to Deploy PHP FPM, NGINX, and MySQL with Docker Compose
Posted October 22, 2023
Setting up a PHP local development environment using PHP FPM, NGINX, and MySQL is complex. Yet, leveraging the prowess of Docker and Docker Compose, this process is easier and flawless. In this comprehensive guide, we’ll go through the step-by-step process of deploying PHP FPM, NGINX, and MySQL with Docker Compose all in one container.
You will learn:
- How to run PHP apps using FPM (FastCGI Process Manager) alongside Docker Compose.
- The right way to set an NGINX server with a Docker container to run PHP FPM code.
- To make this setup deeper, you will learn how to combine MySQL database and PHPMyAdmin to run PHP FPM code alongside NGINX with Docker Compose.
Letβs Dive into this comprehensive guide and learn How to Deploy PHP FPM, NGINX, and MySQL with Docker Compose.
Prerequisites
Creating a PHP FPM app container with Docker Compose NGINX and MySQL is a step-by-step process. Before diving in, ensure:
- Docker and Docker Compose are installed your computer. Check the Docker website (https://www.docker.com/) and Docker Compose from the Docker Compose documentation (https://docs.docker.com/compose/install/)
- Ensure you have the following application structure ready:
nginx-php-app/
βββ Dockerfile
βββ docker-compose.yml
βββ nginx/
β β βββ nginx.conf
β β βββ Dockerfile
βββ app/
βββ index.php
This will represent the following:
Dockerfile
contains configurations to set up PHP with FPM on Docker and install necessary PHP extensions.docker-compose.yml
creates services to run PHP FPM, NGINX, and other services like a database or cache.nginx/nginx.conf
is the NGINX main configuration file and your application-specific NGINX settings.nginx/Dockerfile
will show you the Docker configurations needed to package the NGINX server.app/index.php
contains the source code for your PHP application.
If files are ready, jump in and get the PHP FPM, NGINX, and MySQL containers up and running.
For related setups, check the following:
- Easy Apache PHP Guide with Docker Compose, MySQL and PhpMyAdmin
- Running PHP, Apache, and PostgreSQL with Docker Compose
- Deploy PHP FPM, Apache httpd, and MySQL with Docker Compose
Step 1: Creating PHP FPM Image using Dockerfile
Dockerfile will tell Docker how you need to package PHP and FPM. This is good when selecting the Version of PHP you want to run. Update your Dockerfile as follows:
# Add PHP-FPM base image
FROM php:8.2-fpm
# Install your extensions
# To connect to MySQL, add mysqli
RUN docker-php-ext-install mysqli pdo pdo_mysql
php:8.2-fpm
is the base image and will run PHP version 8.2. You can update it with the right version.docker-php-ext-install
is a command for installing PHP extensions on Docker. Because you need to connect to MySQLmysqli
, its extensions must be installed.
Step 2: Creating NGINX Image using Dockerfile
In your nginx/Dockerfile
file, you’ll create the Docker configurations needed to package the NGINX server.
# Use the official NGINX image
FROM nginx:latest
# Remove default NGINX configuration
RUN rm /etc/nginx/conf.d/default.conf
# Copy your custom NGINX configuration
COPY ./nginx/nginx.conf /etc/nginx/conf.d/
You use the COPY command to add the nginx/nginx.conf
file to Docker. This file contains all NGINX custom configurations you need to run and server PHP-FPM on docker.
Now open nginx/nginx.conf
and add the following NGINX configurations:
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html index.htm;
# Redirects requests to index.php if the file is not found
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# Passes PHP requests to PHP-FPM container
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass php-fpm:9000; # Replace with your PHP-FPM container name
fastcgi_index index.php;
}
# Logs for Nginx access and errors
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
}
By default, NGINX uses port 80. The server will run on localhost
. We will use Docker Compose to add your app code to /var/www/html
so Nginx can access it. The main file here is index.php
. If you are using a different file name, update your configuration.
The location
block adds routing for incoming requests.
The main part you need to understand is the location ~ \.php$
block. You need it to process PHP files. It forwards PHP requests to a php-fpm
container and server your index.php
file.
Based on that, PHP must be created with the php-fpm
container name. You will create that in the next step.
Step 3: Creating PHP FPM and NGINX Containers with Docker Compose
Use the docker-compose.yml
file to build the PHP FPM and NGINX images using the Dockerfiles you created. This way, Nginx will expose your app to the web so you can access it.
But first, ensure your app/index.php
file has some static PHP-related code as follows:
<?php
echo "Testing PHP-FPM on Docker."
?>
<?php
phpinfo();
?>
Go to your docker-compose.yml
file and create PHP-FPM and Nginx services as follows:
version: '3.9'
services:
# PHP-FPM Service
php-fpm:
build:
context: .
dockerfile: Dockerfile
volumes:
# Mounts the local 'app' directory to the container's Nginx root
- ./app:/var/www/html
# NGINX Service
nginx:
build:
context: .
dockerfile: ./nginx/Dockerfile
volumes:
# Mountlocal 'app' directory to the Nginx root
- ./app:/var/www/html
ports:
- "8080:80"
depends_on:
- php-fpm # Depends on the PHP-FPM service
Run the following command to build and run your container:
docker-compose up --build -d
Open http://localhost:8080/
on the browser of your choice, and PHP-FPM is ready and running with Docker alongside NGINX as follows:
And PHP, FPM, and NGINX are working with Docker Compose. Now, letβs add MySQL to run dynamic PHP code.
Step 4: Deploying PHP FPM, NGINX, and MySQL with Docker Compose
To Run PHP-FPM will MySQL, you need to create a MySQL service with Docker Compose. Update your docker-compose.yml
file with MySQL as follows:
version: '3.9'
services:
# PHP-FPM Service
php-fpm:
build:
context: .
dockerfile: Dockerfile
volumes:
# Mounts the local 'app' directory to the container's Nginx root
- ./app:/var/www/html
depends_on:
# Depends on the MySQL database service
- mysql-db
# NGINX Service
nginx:
build:
context: .
dockerfile: ./nginx/Dockerfile
volumes:
# Mountlocal 'app' directory to the Nginx root
- ./app:/var/www/html
ports:
- "8080:80"
depends_on:
- php-fpm # Depends on the PHP-FPM service
- mysql-db # Depends on the MySQL database service
# MySQL Database Service
mysql-db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: test_database
MYSQL_USER: db_user
MYSQL_PASSWORD: password
ports:
# Maps port 3306 on the host to port 3306 on the MySQL container
- "3306:3306"
Now, update the app/index.php
file with MySQL-related dynamic PHP script as follows:
<?php
// Database connection parameters
$host = 'mysql-db'; // MySQL server hostname within the same Docker network
$user = 'db_user'; // MySQL username
$pass = 'password'; // MySQL password
$db = 'test_database';// MySQL database name
// Create a new MySQLi object to establish a database connection
$conn = new mysqli($host, $user, $pass, $db);
// Check if the connection was successful
if ($conn->connect_error) {
// Display an error message and terminate the script if the connection fails
die("Connection failed: " . $conn->connect_error);
}
// If the connection is successful, print a success message
echo "PHP Connected to MySQL successfully";
// Close the database connection
$conn->close();
?>
This script will create a connection. If the connection fails, it will display an error message indicating the failure reason. If the connection succeeds, it will print “PHP Connected to MySQL successfully” and then close the database connection using $conn->close()
.
That will be enough to test a PHP FPM, NGINX, and MySQL setup.
Run the Docker Compose command to rebuild your container:
docker-compose up --build -d
If your PHP FPM, NGINX, and MySQL setup work, http://localhost:8080/
should display a success message:
Step 5: Deploying PhpMyAdmin to MySQL PHP-FPM NGINX Container
Now, how do you access, your database? PhpMyAdmin is great at doing that. Update the docker-compose.yml
file with a PhpMyAdmin service as follows:
version: '3.9'
services:
# PHP-FPM Service
php-fpm:
build:
context: .
dockerfile: Dockerfile
volumes:
# Mounts the local 'app' directory to the container's Nginx root
- ./app:/var/www/html
depends_on:
# Depends on the MySQL database service
- mysql-db
# NGINX Service
nginx:
build:
context: .
dockerfile: ./nginx/Dockerfile
volumes:
# Mountlocal 'app' directory to the Nginx root
- ./app:/var/www/html
ports:
- "8080:80"
depends_on:
- php-fpm # Depends on the PHP-FPM service
- mysql-db # Depends on the MySQL database service
# MySQL Database Service
mysql-db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: test_database
MYSQL_USER: db_user
MYSQL_PASSWORD: password
ports:
# Maps port 3306 on the host to port 3306 on the MySQL container
- "3306:3306"
# PHPMyAdmin Service
phpmyadmin:
image: phpmyadmin/phpmyadmin
links:
# Links the PHPMyAdmin service to the MySQL database service
- mysql-db
ports:
- "8081:80"
environment:
PMA_HOST: mysql-db
# Use MySQL root password for PHPMyAdmin
MYSQL_ROOT_PASSWORD: password
- Run the docker-compose command to rebuild and add the new service:
docker-compose up --build -d
PhpMyAdmin is exposed on 8081. Open http://localhost:8081/
to access it.
- Use
root
as the user andpassword
as the password as set onMYSQL_ROOT_PASSWORD: password
and login to phpMyAdmin:
Conclusion
Congratulations! The PHP FPM, NGINX, and MySQL with Docker Compose setup work. You have learned how to deploy PHP FPM, NGINX, and MySQL using Docker Compose.
You have a working PHP FPM, NGINX, and MySQL environment. You can now effortlessly deploy your PHP code to Docker using Docker Compose.