Deploy PHP FPM, Apache httpd, and MySQL with Docker Compose

Posted November 1, 2023
Docker Apache httpd and PHP FPM Setup with Docker Compose and MySQL

Dive in and learn how to use Docker with Apache httpd and PHP FPM containers to run PHP on Docker Compose alongside MySQL. FPM (FastCGI Process Manager) easily creates pools, runs PHP processes, handles incoming requests, and dispatches them to these pools. It gives PHP-based web applications improved performance and scalability.

Now, you need web servers like Apache httpd server to serve PHP-driven content on the web. Docker and Docker Compose are great to do so.

In this guide, you will package your PHP app and run it with FPM. You will then use Docker to spin up the Apache httpd server and MySQL database using Docker Compose. You will learn:

  • The right way to run any PHP version (5.3, 5.4, 5.6, 7.0, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2) with FPM httpd and Docker Compose.
  • How to package your PHP FPM app using Dockerfile and bundle a single PHP Docker image.
  • Use httpd as the httpd HTTP server to expose a PHP FPM app running on Docker and serve PHP-driven content on the web.
  • How to add MySQL container and run PHP FPM scripts with SQL queries. You will also add PhpMyAdmin to access your MySQL databases.

Now, delve into this comprehensive guide and learn how to get Docker Apache PHP FPM running with Docker Compose and MySQL.

Prerequisites

Creating a PHP FPM app container with Docker Compose httpd Apache and MySQL is a step-by-step process. Ensure you have:

  • Docker installed on your computer.
  • Basic knowledge of working with PHP and MySQL will be great.
  • Ensure you have the following application structure ready:
apache-php-fpm-app/
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ docker-compose.yml
β”œβ”€β”€ apache/
β”‚ β”‚ β”œβ”€β”€ apache.vhost.conf
β”‚ β”‚ └── Dockerfile
└── app/
    └── index.php

This will represent the following:

Docker Apache httpd and PHP FPM Setup with Docker Compose and MySQL

  • Dockerfile contains the configuration needed to spin up PHP with FPM and install required PHP extensions.
  • docker-compose.yml creates all the services needed to spin up PHP FPM, Apache httpd, and MySQL containers.
  • apache/apache.vhost.conf will host all Apache configurations you need so Apache httpd can server PHP on the web.
  • apache/Dockerfile will have all the Docker configurations you need to spin up the Apache httpd server.
  • app/index.php hosts your PHP app source code.

Once you confirm you have this ready, let’s get the Docker httpd PHP FPM container up and running.

Creating PHP FPM Image using Dockerfile

Dockerfile writes all the instructions you need to build your custom image. This way, you will be able to add adding configurations your container needs. An example is adding the mysqli extension so PHP can communicate with the MySQL database. This is what the Dockerfile file does. Add the following code for PHP FPM Docker setup:

# 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_mysq

Here:

  • Docker will pull php:8.2-fpm from Docker Hub and create your image.
  • Note that php:php:8.2-fpm-fpm specifies the PHP version you want to use. This means Docker will use PHP version 8.2. You can change this version based on what PHP you want to run. Just replace 8.2 with other versions such as 5.3, 5.4, 5.6, 7.0, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2, etc.
  • If you want to install any PHP extension with Docker, use the command docker-php-ext-install with RUN.

Creating Apache httpd Image using Dockerfile

Like you create your PHP FPM Dockerfile, you need one to run Apache httpd on Docker.

First, you need the right configuration to run PHP FPM on Apache. This will help you create an Apache Virtual Host configuration to handle PHP files via FPM and serve them to the web.

Go to the apache/apache.vhost.conf file and add the following VirtualHost configuration:

# Set the ServerName to localhost
ServerName localhost

# Configure a VirtualHost to handle requests on port 80
<VirtualHost *:80>
    # Proxy PHP requests to port 9000 PHP-FPM container
    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://php-fpm:9000/var/www/html/$1
    
    # Set the DocumentRoot for the virtual host
    DocumentRoot /var/www/html/
    
    # Directory configuration for the DocumentRoot
    <Directory /var/www/html/>
        DirectoryIndex index.php
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    # Define the CustomLog and ErrorLog destinations
    CustomLog /proc/self/fd/1 common
    ErrorLog /proc/self/fd/2
</VirtualHost>
  • Your application is running on localhost. ServerName should be localhost and handle incoming requests on port 80.
  • Apache will forward requests for PHP files in your container. Note that the container is set as php-fpm. This tells you PHP FPM container must be named ‘php-fpm’. Remember that you will use the name in docker-compose.yml.
  • /var/www/html/ will be your application’s default directory on Apache. This way, the virtual host will for files to serve to start from /var/www/html/.
  • on the Directory, DirectoryIndex is set to index.php. index.php hosts your PHP code and the application entry point. If you used a different file, update your config file correctly.
  • If you want to debug your app, create CustomLog and ErrorLog destinations to manage application logs and those of Docker.

Head over to your apache/Dockerfile and create your Apache HTTP server using httpd as follows:

# httpd base image
FROM httpd:2.4
# Copy the Apache virtual host configuration file to the container
COPY ./apache/apache.vhost.conf /usr/local/apache2/conf/extra/apache.vhost.conf

# Enable Apache modules to ensure proper functionality
RUN sed -i \
   # Uncomment the configuration for mod_deflate to enable compression
    -e '/#LoadModule deflate_module/s/^#//g' \
    # Uncomment the configuration for mod_proxy to enable proxying capabilities
    -e '/#LoadModule proxy_module/s/^#//g' \
    # Uncomment the configuration for mod_proxy_fcgi to enable FastCGI proxy module
    -e '/#LoadModule proxy_fcgi_module/s/^#//g' \
    /usr/local/apache2/conf/httpd.conf

# Include the virtual host configuration file in the main Apache configuration
RUN echo "Include /usr/local/apache2/conf/extra/apache.vhost.conf" >> /usr/local/apache2/conf/httpd.conf

Creating PHP Apache Container with Docker Compose and Serve PHP App

With the Dockerfile ready, Docker will now use Docker Compose to create PHP-FPM and Apache httpd services to spin your app.

You will use the docker-compose.yml file to:

  • Build the PHP and Apache httpd image using the Dockerfile.
  • Expose your PHP app container to access it on the web.

First, go to app/index.php and create a PHP test script. Make sure it is static and not database-related. For example:


<?php
echo "Hello, Docker! PHP is Now Up and Running PHP version: " . phpversion();
?>

<?php
phpinfo();
?>

Now you can create PHP-FPM and Apache httpd services in your docker-compose.yml file as follows:

version: '3.9'
services:
  php-fpm:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./app:/var/www/html
  
  apache-httpd:
    build:
      context: .
      dockerfile: ./apache/Dockerfile
    volumes:
      - ./app:/var/www/html
    ports:
      - "8080:80"
    depends_on:
      - php-fpm

In your root directory, run the following command to start the container:

docker-compose up --build -d

Docker Apache httpd and PHP FPM Setup with Docker Compose and MySQL

Confirm if these services were created in your Docker Demon:

Docker Apache httpd and PHP FPM Setup with Docker Compose and MySQL

You can now access your app on http://localhost:8080/ as follows:

Docker Apache httpd and PHP FPM Setup with Docker Compose and MySQL

phpinfo() will log the information of the app, its server, and so on:

Docker Apache httpd and PHP FPM Setup with Docker Compose and MySQL

How to Add MySQL Docker Container to PHP- FPM using Docker Compose

You can now run simple static PHP code. But you need one running on Docker to create a dynamic that uses a database.

Update the docker-compose.yml file and MySQL as follows:

version: '3.9'
services:
  php-fpm:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./app:/var/www/html
    depends_on:
      - mysql-db 
  
  apache-httpd:
    build:
      context: .
      dockerfile: ./apache/Dockerfile
    volumes:
      - ./app:/var/www/html
    ports:
      - "8080:80"
    depends_on:
      - php-fpm
      - mysql-db 
  mysql-db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: test_database
      MYSQL_USER: db_user
      MYSQL_PASSWORD: password
    ports:
      - "3306:3306"

In your app/index.php file, add the following script for database Connection testing:

<?php
$host = 'mysql-db';
$user = 'db_user';
$pass = 'password';
$db = 'test_database';

$conn = new mysqli($host, $user, $pass, $db);

if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

echo "Connected to MySQL successfully";

$conn->close();
?>
  • The Database connection variables must match that of your Docker MySQL container. Note that the host is not localhost. Your host will change to MySQL container service, mysql-db.
  • Docker will use the mysqli you previously installed in your Dockerfile (docker-php-ext-install mysqli) to create a connection to MySQL.
  • You will get the respective message if the database connection is working.

Run the docker-compose command to rebuild your containers:

docker-compose up --build -d

And PHP can now communicate with MySQL within Docker successfully.

Docker Apache httpd and PHP FPM Setup with Docker Compose and MySQL

This shows how to run PHP with MySQL, and you update your scripts to perfect different database operations.

Using phpMyAdmin to MySQL PHP-FPM Apache Httpd Server

Even though your database works, you don’t have a GUI to access it. Here is how you will use phpMyAdmin to access it:

  • Update the docker-compose.yml file with a phpMyAdmin service:
version: '3.9'
services:
  php-fpm:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./app:/var/www/html
    depends_on:
      - mysql-db 
  
  apache-httpd:
    build:
      context: .
      dockerfile: ./apache/Dockerfile
    volumes:
      - ./app:/var/www/html
    ports:
      - "8080:80"
    depends_on:
      - php-fpm
      - mysql-db 
  mysql-db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: test_database
      MYSQL_USER: db_user
      MYSQL_PASSWORD: password
    ports:
      - "3306:3306"

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    links:
      - mysql-db
    ports:
      - "8081:80"
    environment:
      PMA_HOST: mysql-db
      MYSQL_ROOT_PASSWORD: password
  • Run the docker-compose command to rebuild your containers:
docker-compose up --build -d
  • Open http://localhost:8081/ to access phpMyAdmin:

Docker Apache httpd and PHP FPM Setup with Docker Compose and MySQL

  • Use root as the user and password as the password as set on MYSQL_ROOT_PASSWORD: password and login to phpMyAdmin:

Docker Apache httpd and PHP FPM Setup with Docker Compose and MySQL

Conclusion

You have learned how to use Docker Compose and create an Apache httpd server to run PHP-FPM apps with MySQL.

I hope this guide was helpful!

Deploy PHP FPM, Apache httpd, and MySQL with Docker Compose

Written By:

Joseph Chege