Learn how to quickly deploy a LAMP (Apache, MariaDB, PHP) stack using Docker Compose with our easy-to-follow guide.
If you’re looking to streamline the process of setting up an Apache, MariaDB, and PHP environment for your web development projects, you’re in the right place.
Docker Compose provides a convenient way to define and manage multi-container applications, allowing you to create, configure, and deploy your LAMP stack in minutes.
However, suppose you still prefer to take the traditional approach and install the LAMP stack from the native packages for the distro you are using. In that case, our tutorials for Ubuntu, Debian, Rocky Linux, and AlmaLinux will help you do it effortlessly.
By the end of this guide, you’ll have a fully functional LAMP stack running in a Docker environment, ready to power your web applications.
You’ll also gain a solid understanding of Docker Compose and its capabilities, empowering you to manage your containerized applications in the future efficiently. So let’s dive in!
Of course, having Docker and Docker Compose installed is required to deploy a containerized LAMP stack. So, if you don’t already have Docker installed, any of the following guides may be helpful:
- How to Install Docker on Ubuntu 22.04
- How to Install Docker on Debian 11 (Bullseye)
- How to Install Docker on AlmaLinux / Rocky Linux
- How to Install Docker on Fedora
- How to Install Docker on Raspberry Pi
The other essential component is Docker Compose. Remember, it is provided separately from Docker. Therefore, you must Install Docker before adding Docker Compose; otherwise, Compose will not function.
Installing it is pretty simple, even if it is not already on your Linux system. Type the following two commands:
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose
Create Project’s Structure
Docker Compose allows you to build and run stacks of multiple containers. In other words, it is a tool for defining and running multi-container Docker applications.
To use it, you must first create a “docker-compose.yml” file that configures the containers for your application. Then, you can use a single command such as “
docker-compose up -d” to start all the containers and link them together.
Let’s create the directory structure to house the files required to set up Apache, MariaDB, PHP, and phpMyAdmin with Docker Compose. The final version should look like the one shown below, and below we’ll explain what each file and directory represents.
We use an arbitrary name for the main directory, such as “lamp.” It will store all the files required for the setup, so let’s create it.
Then we make three subdirectories inside it: “apache_docker,” “php_docker,” and “www.”
- The “apache_docker” directory contains the file (Dockerfile) which builds the Apache container, as well as the additional configuration for the Apache server (“apache-vhost.conf“), providing the integration of the web server with PHP and adding a virtual host.
- The “php_docker” directory contains the file “Dockerfile,” which builds the PHP container and adds additional modules.
- Finally, the “www” directory is intended to store the PHP scripts that the application we are developing is expected to execute.
It is important to note that we chose all these directory names arbitrarily. But, of course, you are free to use different ones.
Set Up Apache, MariaDB, PHP, and phpMyAdmin with Docker Compose
It’s time to create our deployment file describing all the services in our containerized LAMP stack. First, create a file named “docker-compose.yaml” inside the “lamp” directory with your preferred text editor:
cd lamp vim docker-compose.yaml
Add the following content to it:
version: "3.8" services: # PHP Service php: build: './php_docker/' volumes: - ./www/:/var/www/html/ # Apache Service apache: build: './apache_docker/' depends_on: - php ports: - "80:80" volumes: - ./www/:/var/www/html/ # MariaDB Service mariadb: image: mariadb:10.11 environment: MYSQL_ROOT_PASSWORD: your_password volumes: - mysqldata:/var/lib/mysql # phpMyAdmin Service phpmyadmin: image: phpmyadmin/phpmyadmin:latest ports: - 8080:80 environment: PMA_HOST: mariadb depends_on: - mariadb # Volumes volumes: mysqldata:
Save and close the file. Don’t be worried if something in its contents is unclear to you. We’ll go through it in more detail below.
We’ll begin with PHP, the first service in our “docker-compose.yaml” file. The key point here is the “build” directive, which points to the “php_docker” directory, where the default “Dockerfile” is located.
As you can see, there is no path to a Docker image here. This is because we will be building our own, the instructions for which can be found in the “Dockerfile” file.
You may be asking why we need to build our own Docker image for PHP instead of using one already available on Docker Hub. The answer is simple: the official image includes limited preinstalled PHP extensions. Unfortunately, they are, in most cases, insufficient for the applications we aim to develop.
Therefore, we will create a new Docker image based on the official PHP 8.2 one, but additionally, we will compile and include some of the most often-used PHP extensions, such as MySQL, GD, ZIP, XML, and so on.
So, create a file named “Dockerfile” inside the “php_docker” directory with your preferred text editor and add the following content to it:
FROM php:8.2-fpm # Installing dependencies for building the PHP modules RUN apt update && \ apt install -y zip libzip-dev libpng-dev libicu-dev libxml2-dev # Installing additional PHP modules RUN docker-php-ext-install mysqli pdo pdo_mysql gd zip intl xml # Cleaning APT cache RUN apt clean
Save and close the file. Of course, as you guessed, if you need more PHP extensions, you can include them in the file.
The “volumes” directive from the “php” service part in “docker-compose.yaml” specifies where the app’s PHP files are. As you know, Docker containers are temporary, and any data are expected to be lost when the container is deleted. Fortunately, the Docker volumes provide a mechanism to persist data created inside a container.
So, our local “www” directory points to “/var/www/html” inside the PHP container, where PHP will look for executable PHP scripts. In other words, we map a folder on the host filesystem (outside of the container context) to within the running container.
Next, let’s create an “index.php” file into it, which will just be used for testing.
Add the single line shown below, then save and exit the file.
<?php phpinfo(); ?>
The “depends_on” directive instructs our PHP container to wait until the MariaDB service has been started. We do this because we expect PHP to try to connect to the database; thus, it must first be operational.
Things are similar here. We use the most recent Docker image and expose the container’s port 80 to port 80 of our local Linux system.
Let’s first create our “apache-vhost.conf” file, which sets the root directory containing the PHP files for our application to be the container “/var/www/html,” which, as we already know, we have mapped to our local one “www.”
In addition, we load the modules we need in Apache so that the web server can proxy the requests, in this case, to the PHP container.
So, inside the “apache_docker” directory, create a file named “apache-vhost.conf” and paste the following content into it:
ServerName localhost LoadModule deflate_module /usr/local/apache2/modules/mod_deflate.so LoadModule proxy_module /usr/local/apache2/modules/mod_proxy.so LoadModule proxy_fcgi_module /usr/local/apache2/modules/mod_proxy_fcgi.so <VirtualHost *:80> # Proxy .php requests to port 9000 of the PHP container ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://php:9000/var/www/html/$1 DocumentRoot /var/www/html/ <Directory /var/www/html/> DirectoryIndex index.php Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> # Send Apache logs to stdout and stderr CustomLog /proc/self/fd/1 common ErrorLog /proc/self/fd/2 </VirtualHost>
Save and exit the file.
Now, again inside the “apache_docker” directory, let’s create the “Docker” file that will build our Apache image and import into it the “apache-vhost.conf” file we just created.
FROM httpd:2.4-alpine RUN apk update; apk upgrade; # Copy Apache virtual host file to proxy .php requests to PHP container COPY apache-vhost.conf /usr/local/apache2/conf/apache-vhost.conf RUN echo "Include /usr/local/apache2/conf/apache-vhost.conf" \ >> /usr/local/apache2/conf/httpd.conf
Again, save and exit the file.
Our MariaDB server’s Docker Compose configuration is simple. All that needs to be done is replace the “MYSQL_ROOT_PASSWORD” directive, “your_password,” with the one you choose. As the name implies, this is the password for the MariaDB root account.
The “volumes” directive ensures that we will not lose the data in our database during container restarts. That’s all we need for our MariaDB container.
The final container in our Docker Compose deployment is phpMyAdmin. Since it is not required for the LAMP stack to function, it dramatically simplifies MariaDB administration, which is why we include it in our deployment.
We specify phpMyAdmin to be accessible on port 8080 because we have already exposed port 80 to the Apache container on our local Linux system.
The “PMA_HOST: mariadb” directive tells the phpMyAdmin container which database to connect to, in this case, our MariaDB container.
Start and Run the LAMP Stack with Docker Compose
Finally, we can run Apache, MariaDB, PHP, and phpMyAdmin using Docker Compose. To do this, execute the below-given command from the “lamp” directory where our “docker-compose.yaml” file is located.
Start and run the containers in the background:
docker-compose up -d
The images will start downloading, and the PHP and Apache Docker images will be built during the process.
The entire procedure will take a few minutes, depending on your internet connection speed. In the end, you should see a screen similar to the one below, informing you that all containers have been successfully started.
The initial delay of the containers’ start will only be the first time because Docker must download images from the Internet and then build some of them. After that, all subsequent runs will take seconds since they will be already available locally on your Linux system.
Finally, you can open your browser and navigate to “http://localhost.” The “index.php” file we prepared in the “www” directory will greet you.
You can also reach your containerized phpMyAdmin instance at “http://localhost:8080” and use the username “root” and password that you set in the “docker-compose.yaml” file to connect to and manage the MariaDB server.
It’s time to congratulate yourself on a well-done job! So let’s quickly walk through the essential Docker Compose commands for managing your containerized LAMP stack.
Basic Docker Compose Commands
The basic Docker Compose commands you can use in practice are shown below with examples. Remember to execute them from the directory containing the “docker-compose.yaml” file.
To view a list of all the containers that are currently running in your LAMP deployment, type:
To stop all docker containers that are running in the background, use the command as shown below:
Of course, you can stop just one of the containers in your LAMP stack rather than all of them. Run “docker-compose stop” followed by the service name to do so. Notice not the container name but the service name!
For example, to stop the Apache container, execute the following:
docker-compose stop apache
Similarly, you can rerun it later by executing “docker-compose start apache.”
Similarly, from your project directory (“lamp”), type the command below to start up your application:
The “docker-compose logs” command displays log output from services. For example, to view the Apache container logs:
docker-compose logs apache
Additionally, if you want to aggregate the logs of every container in your LAMP stack and track what’s happening in them in real-time, type:
docker-compose logs -f
The following command stops and removes containers and networks created by the “docker-compose up -d” command:
Additionally, if you want to stop and remove containers as well as their associated Docker images, use the following command:
docker-compose down --rmi all
In addition, if you want an in-depth introduction to Docker Compose, check out our comprehensive guide.
Congratulations! You have mastered quickly deploying Apache, MariaDB, and PHP using Docker Compose. With the knowledge and skills you have gained from our guide, you are well-equipped to streamline your web development workflow and accelerate your project deployment process.
The benefits of using Docker Compose for your LAMP stack deployment are numerous. First, it provides isolation and portability, ensuring your applications run consistently across different environments.
It also enables scalability and easy scaling of individual services within your stack, allowing you to handle increased traffic and demand seamlessly. Furthermore, the modular nature of Docker Compose makes it effortless to add or remove services from your stack as your application evolves.
We hope our guide has been valuable in demystifying deploying a LAMP stack using Docker Compose. Now, armed with this knowledge, you can confidently embark on your projects and easily deploy your applications.
Happy coding and happy deploying!