For my blog I wanted to create my own WordPress Docker image for it. In this article we will walk through creating a Dockerfile for building a WordPress image. We’ll break down each step, explaining the purpose and significance, so you can understand how to create your own WordPress Docker image. Whether you’re a seasoned developer or just getting started with Docker and WordPress, this guide will provide a clear roadmap.
In today’s software development landscape, Docker has become an indispensable tool for creating, deploying, and managing applications. Its containerization technology ensures consistency across different environments, simplifies deployments, and enhances scalability. For popular platforms like WordPress, Docker offers a fantastic way to streamline setup and management.
Let’s get started with creating our docker image for running WordPress.
Step 1. Choosing the Base Image
Choosing the right base image is crucial for creating an efficient and secure Docker image. For our WordPress image, we’ll start with Debian. Debian is a popular choice for servers because it’s renowned for its stability and security, meaning fewer unexpected issues and a more reliable foundation for your WordPress site.
We’ll be using the bookworm-slim
variant of the official Debian image. “Bookworm” is the codename for the current stable release of Debian (version 12 at the time of writing). The -slim
suffix indicates a minimized version of the image, containing only the essential packages to run Debian. This is a best practice in Docker: smaller images mean faster downloads, faster deployments, and a reduced attack surface.
So, the first line of our Dockerfile
is:
FROM debian:bookworm-slim
Step 2. Updating the Packages
Next we want to make sure that our Docker image is up to date and that we are using the latest packages to ensure that we have the latest security patches and bug fixes. This minimizes vulnerabilities in your WordPress environment.
To achieve this, we’ll use the RUN
instruction in our Dockerfile
to execute commands within the image. Specifically, we’ll use apt
, the package manager for Debian.
First we’ll run the command apt update
refreshes the local package index. Think of it like updating the list of available software and their versions. It doesn’t actually install or upgrade anything; it just gets the latest information.
Next, we’ll run the command apt -y upgrade
which installs the newest versions of all packages currently installed on the system. The -y
flag automatically answers “yes” to any prompts during the upgrade process, allowing the build to proceed unattended, which is essential for automated image builds.
So we now add the following two lines to the Dockerfile.
RUN apt update
RUN apt -y upgrade
Step 3. Installing Supervisord: Managing Multiple Processes
WordPress, when served with NGINX, requires at least two main processes to be running: the NGINX web server itself and PHP-FPM (FastCGI Process Manager) to handle PHP requests. Docker containers are generally designed to run a single main process. To manage multiple processes effectively within a container, we will setup Supervisord.
Creating the Supervisord Configuration File
The first thing that we need to do is create a configuration file for it called supervisord.conf. Below is the contents of the supervisord.conf file to start the Nginx and Php-FPM processes.
[supervisord]
nodaemon=true
logfile=/dev/null
logfile_maxbytes=0
[program:php-fpm]
command = /usr/sbin/php-fpm8.2 --force-stderr --nodaemonize
autostart=true
autorestart=true
priority=10
stdout_events_enabled=true
stderr_events_enabled=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
stopsignal=QUIT
[program:nginx]
command=/usr/sbin/nginx -g "daemon off; error_log /dev/stderr info;"
autostart=true
autorestart=true
priority=20
stdout_events_enabled=true
stderr_events_enabled=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
stopsignal=QUIT
[include]
files = /etc/supervisor/conf.d/*.conf
This supervisord.conf
file is used to manage and run Nginx and PHP-FPM within a Docker container, ensuring both services start automatically and keep running. The [supervisord]
section configures Supervisord, a process manager, to run in the foreground (nodaemon=true
) and disables logging to files by directing logs to /dev/null
. The [program:php-fpm]
section defines the PHP-FPM process, specifying the command to run it, enabling automatic restarts, and directing logs to standard output and error streams for easier debugging in a containerized environment. Similarly, the [program:nginx]
section configures Nginx to run in the foreground (daemon off
), ensuring it stays active under Supervisord’s control. Both programs use stopsignal=QUIT
, allowing them to shut down gracefully. Finally, the [include]
section allows additional configuration files to be loaded dynamically from /etc/supervisor/conf.d/
. This setup ensures Nginx and PHP-FPM are properly managed, automatically restarted if they fail, and their logs are accessible in Docker’s logging system.
Adding Supervisord to Your Docker Image
Next we’ll install Supervisord in the Docker Image using the following commands. The commands below install Supervisord using apt -y install supervisor
, ensuring that it is available to manage multiple services within the container. A dedicated log directory (/var/log/supervisor
) is created to store process logs, although in this setup, logging is redirected to standard output for better integration with Docker logs. Finally, the Supervisord configuration file (supervisord.conf
) is copied into /etc/supervisor/conf.d/
, defining how Nginx and PHP-FPM will be monitored and managed. This approach ensures both services start automatically, restart if they fail, and remain operational under Supervisord’s control, making the container more robust and reliable.
# Install Supervisord so that we can run multiple processes in the docker container
RUN apt -y install supervisor
RUN mkdir -p /var/log/supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
Step 4. Installing NGIX, PHP-FPM and PHP Extensions
Next, we’ll install Nginx, PHP-FPM, and the necessary PHP extensions required for WordPress in the Docker image. As we are using a Debian base image we’ll use the apt command to install nginx php-fpm and the required php extensions.
We’ll add the lines below to the Dockerfile to install these components. The RUN apt -y install
command is used to automate the installation of packages inside the container. The apt
package manager is responsible for retrieving and installing software on Debian-based systems, and the -y
flag automatically confirms the installation, preventing the need for manual user input. This ensures that Nginx, PHP 8.2-FPM, and the required PHP extensions are installed seamlessly during the image build process.
# Install NGINX
RUN apt -y install nginx
# Install PHP and the php-mysql package
RUN apt -y install php8.2-fpm php-mysql
# Install Additional PHP Extensions for wordpress
RUN apt -y install php-curl php-gd php-intl php-mbstring php-soap php-xml php-xmlrpc php-zip php-imagick php-dom php-exif php-igbinary php-mbstring
Step 5. Removing Default NGINX Site Configurations
By default, NGINX comes with a default site configuration. We want to use our own configuration specifically tailored for WordPress. Next we’ll add the following statements to the Dockerfile to remove the default configurations to prevent conflicts and ensure our custom configuration is the only one active.
# Remove the default site configuration files for nginx
RUN unlink /etc/nginx/sites-enabled/default
RUN rm -f /etc/nginx/sites-available/default
Step 6. Copying Custom NGINX Site Configuration
Next we need to setup the NGINX configuration in the Docker Image.
Creating a Configuration File for Nginx
In this step we need to configure Nginx. Create a file called nginx-site.conf in a folder called conf with the following contents. Replace your_domain with the domain for your website.
server {
listen 80;
server_name your_domain www.your_domain;
root /var/www/wordpress;
index index.html index.htm index.php;
location / {
#try_files $uri $uri/ =404;
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ .php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
}
location ~ /.ht {
deny all;
}
location =https://alleria.karunsblog.com/favicon.ico { log_not_found off; access_log off; }
location = /robots.txt { log_not_found off; access_log off; allow all; }
location ~* .(css|gif|ico|jpeg|jpg|js|png)$ {
expires max;
log_not_found off;
}
}
This Nginx configuration file sets up a web server to serve a WordPress site. It listens on port 80 and defines the domain name while setting the root directory to /var/www/wordpress
, where WordPress files are stored. The index
directive ensures that index.php or HTML files are loaded as default pages. The main location /
block routes requests, using try_files
to ensure requests are properly handled by WordPress. The PHP processing block (location ~ .php$
) configures Nginx to forward PHP requests to PHP-FPM via a Unix socket. Security rules are included to block access to hidden files (like .htaccess
), and optimizations disable logs for certain static assets and files like favicon.ico
and robots.txt
. Additionally, caching rules are set for static content like images, CSS, and JavaScript, improving performance. This configuration ensures Nginx properly serves the WordPress site while optimizing speed and security.
Copying the Nginx Configuration File into the Docker Image
For the next step, we need to copy the configuration file into the Docker Image. To do this we add the following commands to the Dockerfile.
# Copy our NGINX Site Configuration File into the image
COPY --chown=www-data:www-data conf/nginx-site.conf /etc/nginx/sites-available/wordpress
RUN ln -s /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/wordpress
The COPY
command transfers the custom Nginx site configuration file (nginx-site.conf
) from the local conf
directory into the container’s Nginx configuration directory (/etc/nginx/sites-available/wordpress
). The --chown=www-data:www-data
flag ensures that the file is owned by www-data, the user under which Nginx operates, preventing potential permission issues. The RUN ln -s
command creates a symbolic link in /etc/nginx/sites-enabled/
, enabling the WordPress site configuration. This approach follows standard Nginx best practices, allowing multiple site configurations while ensuring the correct one is activated. With this setup, Nginx knows how to serve the WordPress site when the container starts.
Step 7. Downloading and Installing WordPress
Next we’ll download and install WordPress in the Dockerfile.
# Download WordPress
RUN mkdir -p /var/www/wordpress
RUN apt install wget
RUN wget https://wordpress.org/wordpress-6.7.2.tar.gz -O /tmp/wordpress.tar.gz
RUN tar -zxvf /tmp/wordpress.tar.gz -C /var/www
# WordPress Setup
RUN chown -R www-data:www-data /var/www/wordpress
In this section of the Dockerfile, we are downloading and setting up WordPress inside the container. First, we create the necessary directory (/var/www/wordpress
) to store the WordPress files. We then install wget, a command-line tool for downloading files, and use it to fetch the latest WordPress package (wordpress-6.7.2.tar.gz
) from the official WordPress website. The downloaded archive is extracted into /var/www
, making the WordPress files accessible. Finally, we change the ownership of the WordPress directory to www-data, the user that Nginx and PHP-FPM run as, ensuring proper file permissions. This setup ensures WordPress is correctly installed and ready to run inside the container.
Step 8. Making the Blog Accessible: Exposing Port 80
Now that we have our WordPress installation running with Nginx, we need to make it accessible from outside the container. Web servers, like Nginx, typically listen for connections on port 80 (the standard port for HTTP traffic).
To inform Docker that our container listens on port 80, we use the EXPOSE
instruction in our Dockerfile
and add the following statement to the Dockerfile:
EXPOSE 80
Step 9. Creating a Docker Volume for WordPress
In this step we want to make sure that the owner of the wordpress folder is set correctly and we also want to create a persistent docker volume for WordPress to use.
RUN chown -R www-data:www-data /var/www/wordpress
# Set up a volume for wordpress
VOLUME /var/www/wordpress
These commands ensure proper file permissions and enable persistent storage for the WordPress site inside the Docker container. The RUN chown -R www-data:www-data /var/www/html
command recursively changes the ownership of the WordPress files to the www-data
user, which is the default user for Nginx and PHP-FPM. This prevents permission issues when the web server tries to read or modify files. The VOLUME /var/www/wordpress
directive creates a Docker volume, allowing the WordPress files to persist even if the container is stopped or removed. This setup ensures that any changes made to WordPress, such as theme updates or uploaded media, are not lost when the container restarts, improving the reliability and flexibility of the deployment.
Step 10. Specifying the Startup Command for the Docker Image
We’ll be using supervisord in the docker image. As we discussed earlier, Supervisord is managing NGINX and PHP-FPM. By making Supervisord the CMD
, we ensure that when the container starts, Supervisord starts, and Supervisord in turn starts and manages NGINX and PHP-FPM, creating a fully functional WordPress environment.
We’ll add the command below to the Dockerfile. The CMD
instruction specifies the default command to run when the Docker container starts. Here, it’s set to ["/usr/bin/supervisord"]
.
CMD ["/usr/bin/supervisord"]
Step 11. Final Dockerfile
After completing all the steps we have the following Dockerfile for our WordPress Docker image.
FROM debian:bookworm-slim
# Update the list of packages
RUN apt update
# Upgrade the packages
RUN apt -y upgrade
# Install Supervisord so that we can run multiple processes in the docker container
RUN apt -y install supervisor
RUN mkdir -p /var/log/supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Install NGINX
RUN apt -y install nginx
# Install PHP and the php-mysql package
RUN apt -y install php8.2-fpm php-mysql
# Install Additional PHP Extensions for wordpress
RUN apt -y install php-curl php-gd php-intl php-mbstring php-soap php-xml php-xmlrpc php-zip php-imagick php-dom php-exif php-igbinary php-mbstring
# Remove the default site configuration files for nginx
RUN unlink /etc/nginx/sites-enabled/default
RUN rm -f /etc/nginx/sites-available/default
# Copy our NGINX Site Configuration File into the image
COPY --chown=www-data:www-data conf/nginx-site.conf /etc/nginx/sites-available/wordpress
RUN ln -s /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/wordpress
# Download WordPress
RUN mkdir -p /var/www/wordpress
RUN apt install wget
RUN wget https://wordpress.org/wordpress-6.7.2.tar.gz -O /tmp/wordpress.tar.gz
RUN tar -zxvf /tmp/wordpress.tar.gz -C /var/www
# Expose port 80 for NGINX
EXPOSE 80
# WordPress Setup
RUN chown -R www-data:www-data /var/www/wordpress
# Set up a volume for wordpress
VOLUME /var/www/wordpress
CMD ["/usr/bin/supervisord"]
Step 12. Building the Docker Image
To build a docker image with the docker image name mywordpress-image run the following command:
docker build -t mywordpress-image .
Github Repository
All the files that were created as a part of this article are available in the following Github Repository: https://github.com/kdambiec/public-wordpress-docker-image
Leave a reply