Understanding Docker and Docker Compose
This blog post gives clear explanations of Docker, Docker volumes, and Docker Compose. We won’t be using a reverse proxy server. You can skip to the “Dockerize WP” section if you already know about these things.
Quick Guide to Linux Updates:
It’s important to keep your Linux system up to date! Just keep in mind that the way you update will depend on the version of Linux you have. If you want to know what Linux distribution you’re using, type cat /etc/os-release into your terminal.
- For Ubuntu and other Debian-based systems: First, you should check to see if there are any new updates. This is like looking at what new things are in a store. You can do this by running
sudo apt update. But to really get those new things (install the updates), you’ll need to runsudo apt upgrade -y. - For AlmaLinux and other systems based on RHEL: This is a little easier. The command
sudo dnf update -ydoes both steps for you: it looks for updates and then installs them.
Important: Both sudo apt upgrade and sudo dnf update will install new versions of packages, but they won’t automatically remove packages that aren’t being used anymore.
Put docker engine on Ubuntu
You need to set up the Docker apt repository before you can install Docker Engine for the first time on a new host machine. After that, you can use the repository to install and update Docker. Look in the documentation for the last steps. You will install both Docker and Docker Compose if you follow the installation instructions. You can learn more about docker compose later in this blog.
After installing docker, check its status.
sudo systemctl status docker
To add your user account to the docker group, use the command:
sudo usermod -aG docker USER
Run the command docker info to see containers, images, the docker root directory, and a lot of other useful information.
Getting images and running containers
The command docker run -d -p 8080:80 --name myNewWebsite nginx will pull the image and start the container. You should see the nginx default page when you go to serverIP:8080.
To see the GET HTTP requests, run the command:
docker logs dockerID
To see how much each container is using of server resources in real time:
docker stats
OR
docker stats dockerID
Check that the disk usage isn’t included in the stats. Use docker ps -s to see how much space the container takes up on the server disk.
Keeping your container’s data
If you stop the docker, you will lose all the data that was saved in it by default. There are two ways to keep the data safe: bind mount and volumes. Docker volumes are better for use in production. These commands are helpful for Docker volumes.
docker volume create VOLNAME
docker volume ls
docker volume inspect VOLNAME
We use docker volume rm VOLNAME to get rid of a volume. We use docker volume prune to get rid of all the volumes that aren’t being used.
Now let’s make a nginx container with a volume for the main sites in the container (not on the local machine or server) and run it.
docker run -d --name nginx -p 80:80 -v wp_nginx_vol:/usr/share/nginx/html nginx
This path on the server will save all the container data: /var/lib/docker/volumes/wp_nginx_vol/_data
You can now use the cp command to copy files from any server volume to a docker volume. Use the ls command to check the container volume after you stop it!
Learning about Docker Compose for Web Apps
You can use docker-compose to create and run multi-container Docker apps. Docker-compose lets you manage all of your containers as a single service instead of having to do it one at a time. This makes development, testing, and deployment a lot easier.
What is a file called docker-compose.yml?
Docker-compose uses a YAML file, usually called docker-compose.yml, to set up the services for your app. This file lists all the parts of your app, like a web server, a database, and any other services, as well as their dependencies, networks, and volumes.
This is how a docker-compose.yml file is set up:
services:
web:
build: .
ports:
- "8000:8000"
volumes:
- .:/code
depends_on:
- db
db:
image: postgres:13
environment:
POSTGRES_DB: mydb
POSTGRES_USER: user
POSTGRES_PASSWORD: password
Let’s look at the most important parts:
- services: This is the most important part of your
docker-compose.ymlfile. Each service entry describes a different container that is part of your app. - web: This is a service called “web.”
- build: .: This tells Docker Compose to use the Dockerfile in the current directory (
.) to make an image for this service. This is perfect for the code for your custom app. - ports: – “8000:8000”: This connects port 8000 on your host machine to port 8000 inside the web container. This lets you use your host machine to get to your web app.
- volumes: – .:/code: This mounts the current directory (
.) on your host machine into the/codedirectory inside the web container. This is very helpful for development because any changes you make to your code on the host will show up right away in the container without having to rebuild the image. - depends_on: – db: This tells the web service that it needs the db service to work. Before the web service starts, Docker Compose will make sure that the db service does. This helps control the order in which services that depend on each other start up.
- db: This is a service called “db.”
- image: postgres:13: This service doesn’t build an image; it uses a pre-existing
postgres:13image from Docker Hub. This is normal for databases and other standard services. - environment: This part lets you set environment variables inside the container. Here, we’re setting up the PostgreSQL database with a name, a user, and a password.
Common docker-compose commands and when to use them
Important: You must run all docker-compose commands, like docker-compose up, docker-compose down, docker-compose ps, etc., from the folder where your docker-compose.yml file is.
You can use a few simple commands to manage your application once you have your docker-compose.yml file set up:
docker compose up: This is the main command you use to start your app.docker-compose up -d: Starts all services in detached mode (in the background), so you can keep using your terminal. This is often the best choice for both development and production.docker compose up --build: Forces Docker Compose rebuilds images before starting containers to make sure you’re running the most recent code. This is very important after you change your Dockerfile or application code.docker-compose down: This command stops and deletes the networks, volumes, and containers thatdocker-compose upmade.docker compose down --volumes: This also deletes named volumes that you set up in thevolumessection of yourdocker-compose.ymlfile. Be careful with this, because it will delete your database data if it is stored in a named volume.docker compose ps: This command shows the services that are running and what their status is.docker compose logs [service_name]: Shows the logs for one service or all services.docker compose logs -f: This command follows the logs in real time, just liketail -f.docker compose exec [service_name] [command]: This command lets you run a command inside a service container that is already running.
Dockerize WP
You should have done the steps before and run the commands. Let’s start over with dockerization. Please stop all dockers that are currently running, and then run docker system prune -a.
Step 1: Get the ground ready
Make a new folder called “wordpress-dockerized”
mkdir wordpress-dockerized
cd wordpress-dockerized
touch docker-compose.yml
nano docker-compose.yml
In docker-compose.yml, paste the following:
services:
wordpress:
image: wordpress:latest
ports:
- "80:80"
volumes:
- wp_app:/var/www/html
- ../files/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
environment:
WORDPRESS_DB_HOST: wp_db
WORDPRESS_DB_NAME: $DB_NAME
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: $DB_PASSWORD
WORDPRESS_DEBUG: ${WORDPRESS_DEBUG:-0}
WORDPRESS_CONFIG_EXTRA: |
define('WP_MEMORY_LIMIT', '256M');
define('DISALLOW_FILE_EDIT', true);
depends_on:
wp_db:
condition: service_healthy
restart: unless-stopped
wp_db:
image: mysql:8.4
restart: unless-stopped
volumes:
- wp_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: $DB_PASSWORD
MYSQL_DATABASE: $DB_NAME
healthcheck:
test: ["CMD-SHELL", "exit | mysql -h localhost -P 3306 -u root -p$$MYSQL_ROOT_PASSWORD"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
volumes:
wp_app:
wp_data:
This WordPress image uses an Apache server behind the scenes, so keep that in mind. You should use wordpress:fpm if you want to use a reverse proxy server like Nginx.
Make the .env file. We put our environment variables ($DB_NAME and $DB_PASSWORD) in our docker-compose.yml. To set these variables, we need to make a .env file in the same folder as your docker-compose.yml file.
touch .env
To add the values you want, open .env in a text editor (like nano .env) and type them in.
DB_NAME=wordpress_db
DB_PASSWORD=your_strong_password
Make the uploads.ini file. Our docker-compose.yml file points to ../files/uploads.ini. You need a files folder one level up from your wordpress-dockerized folder, and inside that folder, you need an uploads.ini file.
mkdir ../files
touch ../files/uploads.ini
Open files/uploads.ini in a text editor (like nano ../files/uploads.ini) and add the settings for PHP uploads. For example:
file_uploads = On
memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 600
You can change these numbers if you need to.
Now, go back to the directory where you set up wordpress-dockerized:
cd ../wordpress-dockerized
Step 2: Open the WordPress app
You can now start your WordPress app with Docker Compose since you have all the files in the right place:
docker compose up -d
docker compose up: This command builds, sets up, and starts the services that are listed in yourdocker-compose.ymlfile.-d: This starts the services in detached mode, which means they will run in the background.
You can get to your WordPress site as soon as the services are up and running. It may take a few minutes for the database and WordPress to start up.
The time has come 🙂
To begin the wp installation, type your server’s IP address into the browser. You should see the WordPress installation screen. To finish the setup, enter your site title, admin username, password, and email.
We made two volumes in the composer file, so all the wp files and the wp db will be on the server at the following path. To be sure, run the command ls /var/lib/docker/volumes/.
Step 3: The Last Step: Adding Your Domain and SSL Certificate
We will use a Cloudflare SSL certificate for this one simple WordPress site. We don’t need a reverse proxy server like Nginx or Traefik.
First, add a new A record to your Cloudflare DNS settings that points to the IP address of your server. Second, under SSL/TLS, pick “Flexible” as the certificate mode.
Next, you need to put these two lines in your wp-config.php file. You can use nano in your server terminal to open the file at /var/lib/docker/volumes/wordpress-dockerized_wp_app/_data/wp-config.php:
define('WP_HOME','https://wp.corefortify.com');
define('WP_SITEURL','https://wp.corefortify.com');
Don’t forget to use your real domain name instead of wp.corefortify.com. Have fun with your WP in a container.


