Easy Apache PHP Guide with Docker Compose, MySQL and PhpMyAdmin
Posted November 20, 2023
Have you thought of running PHP on Docker? This guide teaches everything you need from start to finish and gets PHP up and running within Docker using Docker Compose, Apache, and MySQL.
PHP requires you to have an Apache server to run its code. You will need a MySQL database installed on your computer. With a Docker container, you can use Docker Compose and spin up the Apache server and MySQL database to run your PHP apps.
You will learn how to set up a PHP Docker development environment based on the following:
- Spin up a PHP Apache server Docker Compose container that will run any PHP version of your choice, i.e. (PHP 5.3, 5.4, 5.6, 7.0, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2) just to name a few.
- You will create a PHP Dockerfile example to define all the PHP configurations you might need and bundle them in a single Docker image.
- Create MySQL Docker Compose container that will communicate with the PHP Apache server
- Create a simple PHP app that communicates with the Dockerfile Apache and MySQL to run SQL queries using PHP scripts.
- While on the same, you will see how to use the docker php ext install mysql command to install the MySQL extension for PHP within Docker. This way, you’ll have your PHP MySQL database connection within Docker.
- Use Docker Compose to create a PhpMyAdmin container and access your PHP-related MySQL database
Let’s Dive into this comprehensive guide and learn the easy Docker Apache PHP setup with Docker Compose and MySQL.
For related setups, check the following:
- How to Deploy PHP FPM, NGINX, and MySQL with Docker Compose
- Running PHP, Apache, and PostgreSQL with Docker Compose
- Deploy PHP FPM, Apache httpd, and MySQL with Docker Compose
Prerequisites
Setting up a Docker Compose Apache PHP MySQL container 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.
Before diving in, the following will be your application structure:
php-docker/
│ ├── Dockerfile
│ └── docker-compose.yml
└── www/
└── index.php
Let’s break it down:
This structure will contain all the Docker Apache PHP and MySQL settings you need as follows:
Dockerfile
contains all the instructions to package a PHP image.docker-compose.yml
defines your Docker Compose services for your app. These services will be phpMyAdmin, MySQL, PHP, and Apache.www/index.php
hosts your PHP app source code.
Spinng Up PHP Apache Server using PHP Dockerfile Example
Dockerfile defines all the configurations you need to package your application together. This involves the command you need in your application and the version of PHP Apache you want to run:
In your working directory, create a Dockerfile
and define the Docker image for your PHP and Apache environment as follows:
- Add the base image of the PHP version you want to use. This is key to ensuring you have consistency in the PHP version. Here, I used
php:8.2
as follows:
# Use an official PHP runtime
FROM php:8.2-apache
At the same time, note that you are using a php:8.2-apache
image. This will package PHP and Apache Server together, so you don’t need to create Apache configurations separately. You can choose any version that works for you (PHP 5.3, 5.4, 5.6, 7.0, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2), etc.
- Proceed and enable PHP Apache modules using
RUN
. At the same time, install any extensions you need, including docker-php-ext-install mysqli, for MySQL connections as follows:
# Enable Apache modules
RUN a2enmod rewrite
# Install any extensions you need
RUN docker-php-ext-install mysqli pdo pdo_mysql
- Within Docker, you need a PHP working directory. Because you are using Apache, make sure you set the working directory to the default Apache server path as follows:
# Set the working directory to /var/www/html
WORKDIR /var/www/html
Docker will need to execute your PHP code. I can’t do that out of the box. Use Docker COPY
command and copy your source files so Docker can be able to use them:
# Copy the source code in /www into the container at /var/www/html
COPY ../www .
Your Dockerfile
should be ready and complete as follows:
# Use an official PHP runtime
FROM php:8.2-apache
# Enable Apache modules
RUN a2enmod rewrite
# Install any extensions you need
RUN docker-php-ext-install mysqli pdo pdo_mysql
# Set the working directory to /var/www/html
WORKDIR /var/www/html
# Copy the source code in /www into the container at /var/www/html
COPY ../www .
Creating PHP Apache Container with Docker Compose and Serve PHP App
You have all you need to create to package your PHP app. Now, you need to use the docker-compose.yml
file and create a PHP Apache Docker Compose service for your app. This way, Docker will:
- Builds the PHP and Apache image using the Dockerfile.
- Expose your PHP app. For example, use maps port 8080 on the host to port 80 on the container and expose your app
First, head over to your www/index.php
and create a PHP test script as follows:
<?php
echo "Testing a PHP Apache Docker Container";
?>
In your docker-compose.yml
, create your PHP Apache service as follows:
version: '3.9'
services:
webserver:
container_name: PHP-webServer
build:
context: .
dockerfile: Dockerfile
volumes:
- ./www:/var/www/html
ports:
- 8000:80
In this case:
- Docker will create a new container named
PHP-webServer
. - Docker Compose will create your container based on
Dockerfile
. - Your PHP app will be exposed on port
8000
.
Now run the following command to test if your PHP app is working as expected:
docker-compose up -d
These changes should be reflected in Docker Demon as such. You should have a PHP image ready and a container running as follows:
To verify if the PHP Apache container is running, head over to http://localhost:8000/
. You should be served with your simple PHP app based on the index.php
file as follows:
How to Add MySQL Docker Container to PHP Apache using Docker Compose
You just created the most basic PHP Apache Docker container. Let’s now dive deeper and add MySQL to our app.
To do so, you need to spin up a MySQL docker container using Docker Compose. Navigate to your docker-compose.yml
and make the following changes:
version: "3.9"
services:
webserver:
container_name: PHP-webserver
build:
context: .
dockerfile: Dockerfile
volumes:
- ./www:/var/www/html
ports:
- 8000:80
depends_on:
- 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"
You will note that:
depends_on
was added to your previousPHP-webserver
container. This way, PHP Apache will know to depend on MySQL database (mysql-db
) service to create your connections.- MySQL environment defines your typical database password, users, and databases. In this example, you can update them according to your liking.
- Once the Docker Container fires up a MySQL container, a
test_database
database will be created.
Now, you will use these database environment variables like on a local computer. But because we are on Docker, now you will update the www/index.php
file and include MySQL as follows:
<?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();
?>
Here:
- 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 check your containers:
docker-compose up -d
Open http://localhost:8000/
. If you set up everything correctly, PHP Apache should be able to establish a connection to MySQL database as follows:
Adding phpMyAdmin to MySQL PHP Apache Server
Your database is running. However, up to now, you don’t a GUI access and check what’s happening with your database. In that regard, you will use phpMyAdmin to log in to MySQL and visually access your database. Go ahead and update your docker-compose.yml
file as follows:
version: "3.9"
services:
webserver:
container_name: PHP-webserver
build:
context: .
dockerfile: Dockerfile
volumes:
- ./www:/var/www/html
ports:
- 8000:80
depends_on:
- 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
Rerun Docker Compose to add phpMyAdmin service:
docker-compose up -d
You have three services running:
phpMyAdmin will be served on port 8081
. Open http://localhost:8081/
on your browser:
To access MySQL, use root
as username and the value of MYSQL_ROOT_PASSWORD
as password. In this example, it is password
:
This Is how your MySQL database looks like. You can confirm by making sure it was test_database
.
Creating a PHP CRUD API and Running it with MySQL and PHP Apache Docker Container
What if you now want to create a CRUD API using PHP and run it within Docker alongside PHP, Apache, and MySQL? That’s very possible. Your PHP Docker environment is working, and you can run any PHP code and still use your MySQL database.
Assume you want to run the following POST and GET requests with PHP in your index.php
file:
<?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";
// Handle POST request
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (isset($_POST['submit'])) {
$name = $_POST['name'];
$email = $_POST['email'];
// Insert data into the database
$sql = "INSERT INTO users (name, email) VALUES ('$name', '$email')";
if ($conn->query($sql) === TRUE) {
echo "<br>Data inserted successfully";
} else {
echo "<br>Error inserting data: " . $conn->error;
}
}
}
// Handle GET request
if ($_SERVER["REQUEST_METHOD"] == "GET") {
if (isset($_GET['action']) && $_GET['action'] == 'fetch') {
// Retrieve data from the database
$result = $conn->query("SELECT * FROM users");
if ($result->num_rows > 0) {
echo "<br><br>Users:<br>";
while ($row = $result->fetch_assoc()) {
echo "Name: " . $row["name"] . " - Email: " . $row["email"] . "<br>";
}
} else {
echo "<br>No users in the database";
}
}
}
$conn->close();
?>
<!DOCTYPE html>
<html>
<head>
<title>PHP Form</title>
</head>
<body>
<h2>Submit Form</h2>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
Name: <input type="text" name="name"><br>
Email: <input type="text" name="email"><br>
<input type="submit" name="submit" value="Submit">
</form>
<h2>Retrieve Data</h2>
<a href="?action=fetch">Fetch Data</a>
</body>
</html>
What you need to do is create your database table on phpMyAdmin using the following script:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL
);
The run Docker Compose to restart your containers:
docker-compose up -d
Open your server http://localhost:8000/,
and it should be ready:
Try adding new data and fetch them as such:
At the same time, the data you add should be added to MySQL, and you can verify that on phpMyAdmin:
Conclusion
You now have Pro Docker Apache PHP Setup with Docker Compose and MySQL. You can now spin up a PHP Apache server Docker Compose container to run any PHP version you choose, i.e. (PHP 5.3, 5.4, 5.6, 7.0, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2). You now have a working CRUD API on docker while using MySQL to run SQL queries using PHP scripts with docker php ext install MySQL command to create the connections.