When operating a website, server settings and database management can be a headache. Doing everything manually often leads to mistakes and can be very time-consuming. However, using Docker and a docker-compose.yml
file, you can automate the entire setup process and simplify management.
With this single file, you can build and maintain a WordPress and MySQL environment, and even automate regular backups. There’s no need for complex command inputs or configuration changes for backups. This docker-compose.yml
file is a powerful tool that ensures your site is built and maintained with just a few commands while keeping your data secure.
Here’s a summary of the convenient features offered by this WordPress environment:
- Backup function for migration: Automatically backs up the database, allowing you to migrate or restore at any time.
- Automatic WordPress core updates: Updates the core WordPress files to the latest version automatically when the container is restarted.
- Data persistence: The
wp-content
directory and database are persisted on the host side, ensuring that customizations and content are retained even when the container is restarted or updated. - Automatic setup of Japanese WordPress: Automatically downloads and sets up the Japanese version of WordPress, making it easy to build a Japanese environment. The system also supports multiple languages, allowing users to automatically install and configure the desired language version based on their needs.
- Easy-to-manage log function: The Apache logs are stored on the host, allowing you to easily access error logs and other information from outside the container.
- Scheduled automatic backups: Automatically backs up the MySQL database daily, reducing the risk of losing important data. These backups are scheduled and saved regularly without the need for manual intervention.
- Smooth container update process: Easily update WordPress and MySQL images, with the rebuilding process automated. The process from building to restarting the container is seamless, making it easy for beginners to keep their environment up to date.
- Simple management of environment variables: The environment variables are straightforward to configure, allowing centralized management of WordPress and MySQL connection settings, with the flexibility to adjust the environment as needed.
The docker-compose.yml
file we’ll introduce next is designed to deploy WordPress easily and automate database backups. It provides a reliable system that allows for simple recovery of your site and data during server migration.
Role and Placement of Four Files and php.ini
The four files and the php.ini
file used in this project each play an important role. Placing them in the correct directories will enable you to efficiently build a WordPress environment. Below is the purpose of each file and how to arrange them. I created an appropriate directory in my home directory and placed them there.
The following is an ASCII art example illustrating the structure where there’s a youtube
directory under the home directory, containing five files.
/home/username/
└── youtube/
├── docker-compose.yml
├── Dockerfile
├── .env
├── php.ini
└── entrypoint.sh
File Descriptions:
- docker-compose.yml: A file that defines multiple containers, such as WordPress and MySQL.
- Dockerfile: A file that defines the configuration and necessary packages inside the container.
- .env: A file used to define environment variables (e.g., database username and password).
- php.ini: The PHP configuration file (used to set upload limits, timezone, etc.).
- entrypoint.sh: A script that runs when the container starts.
docker-compose.yml
- Purpose: This file is used to manage multiple Docker containers (e.g., WordPress and MySQL) at once. It defines container settings, networks, volumes, and more.
- Main Role: It automates the setup of the WordPress web server, database, and backup services, efficiently managing the entire environment.
- Placement: Place this file in the root directory of the project, and start the environment using the command
docker-compose up -d
.
.env
- Purpose: This file manages environment variables. It externalizes important settings, such as the database username, password, and name, making it easy to change settings while maintaining security.
- Main Role: It simplifies environment settings and facilitates migration between different environments. By modifying the
.env
file, you can dynamically change the settings for each service. - Placement: Place this file in the same directory as
docker-compose.yml
.
Dockerfile
- Purpose: This file is used to create a custom WordPress environment. It customizes the foundation for running WordPress, such as specific PHP settings and installing additional packages.
- Main Role: It automatically builds a customized WordPress environment, simplifying the build process.
- Placement: Place this file in the same directory as
docker-compose.yml
.
entrypoint.sh
- Purpose: This script runs automatically when the container starts. It handles initial setup for WordPress, file copying, and database connection settings.
- Main Role: It automates the initialization of the WordPress environment, ensuring the container starts properly. It also streamlines the process of configuring the database and copying files.
- Placement: Place this file in the location referenced in the
Dockerfile
(e.g.,/usr/local/sbin/entrypoint.sh
). However, it can be placed in the same directory as the other three files without any issues. The reasoning is explained below.
1. Reference in the Dockerfile
In the Dockerfile
, if you use the COPY
or ADD
command to copy entrypoint.sh
into the container, as long as the file path on the host is specified correctly, it can be copied to the container regardless of its location.
For example, if the following is written in the Dockerfile
, entrypoint.sh
located in the host directory is copied to /usr/local/sbin/entrypoint.sh
inside the container.
COPY entrypoint.sh /usr/local/sbin/entrypoint.sh
RUN chmod +x /usr/local/sbin/entrypoint.sh
With this setup, entrypoint.sh
will be executed correctly when the container starts.
2. Specifying in docker-compose.yml
In docker-compose.yml
, when building the Dockerfile
, the build
option specifies the context. This context refers to the directory where the Dockerfile
exists (which is the same directory as docker-compose.yml
). Because of this, files specified in the Dockerfile
(such as entrypoint.sh
) will be referenced from the same directory, ensuring they function correctly.
If the following configuration is set in docker-compose.yml
, files specified in the Dockerfile
will be handled properly.
services:
wordpress:
build:
context: .
dockerfile: Dockerfile
container_name: wordpress
restart: unless-stopped
volumes:
- ./wordpress:/var/www/html
Here, context: .
indicates that the directory where docker-compose.yml
exists is specified as the build context.
3. File Placement and Reference Mechanism
Docker copies or mounts files from the host machine into the container. As long as entrypoint.sh
is properly placed on the host and correctly referenced in both the Dockerfile
and docker-compose.yml
, it will work without any issues, regardless of which directory the file is in on the host.
By placing these files in an appropriate directory and executing the commands, you can easily set up a WordPress environment, with data management and backups automated.
Below is the content of docker-compose.yml
, followed by a step-by-step explanation of each setting and configuration.
version: '3.7'
services:
wordpress:
build:
context: .
dockerfile: Dockerfile
container_name: wordpress
restart: unless-stopped
ports:
- "8888:80"
environment:
- WORDPRESS_DB_HOST
- WORDPRESS_DB_USER
- WORDPRESS_DB_PASSWORD
- WORDPRESS_DB_NAME
volumes:
- ./php.ini:/usr/local/etc/php/conf.d/php.ini
- ./wordpress:/var/www/html # Persist WordPress files on the host
- ./logs/apache2:/var/log/apache2 # Mount log files externally
db:
image: mysql:latest
container_name: wordpress-db
restart: always
environment:
- MYSQL_DATABASE
- MYSQL_USER
- MYSQL_PASSWORD
- MYSQL_ROOT_PASSWORD
volumes:
- ./db_data:/var/lib/mysql # Persist MySQL data
wpsql:
image: mysql:latest
container_name: wpsql
depends_on:
- db
environment:
MYSQL_HOST: db
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- ./backup:/backup # Directory for backups
command: >
/bin/bash -c "
while ! mysqladmin ping -h \"$$MYSQL_HOST\" --silent; do
sleep 1;
done;
while true; do
echo 'Starting backup...';
MYSQL_PWD=$$MYSQL_PASSWORD mysqldump -h $$MYSQL_HOST -u $$MYSQL_USER ${MYSQL_DATABASE} > /backup/${MYSQL_DATABASE}_backup.sql;
echo 'Backup complete.';
sleep 86400;
done"
restart: on-failure
volumes:
db_data: {}
backup: {} # Added volume for backups
1. WordPress Service
- build: context: . indicates that a custom WordPress image will be built using the
Dockerfile
. - container_name: The container is named “wordpress” for easy identification.
- ports: Maps host port 8888 to container port 80, allowing external web access.
- environment: The database hostname, username, password, and database name are set as environment variables.
- volumes:
- Mounts
./php/php.ini
to the PHP configuration file in the container, allowing you to customize PHP settings. - Mounts
./wordpress
to/var/www/html
, persisting WordPress files on the host. - Saves Apache logs externally by mounting
./logs/apache2
.
- Mounts
2. Database Service (db)
- image: Uses the latest MySQL image to provide the database service.
- container_name: The database container is named “wordpress-db”.
- volumes: Mounts
./db_data
to the MySQL data directory, ensuring data persistence.
3. Backup Service (wpsql)
- container_name: This container is named “wpsql” and is responsible for automatically backing up the MySQL database.
- volumes: Saves database backups as
.sql
files in the./backup
directory. - command: The backup process runs daily, dumping the database every 86,400 seconds (24 hours) and storing the backup.
4. Volume Persistence
- db_data: Persists the database data.
- backup: Stores the database backups.
This docker-compose.yml
file automatically sets up WordPress and MySQL and also takes care of backing up the database. By backing up the database in .sql
format, migrations become much easier.
Contents and Explanation of the .env
File:
# WordPress Configuration
WORDPRESS_DB_HOST=db
WORDPRESS_DB_USER=exampleuser
WORDPRESS_DB_PASSWORD=examplepass
WORDPRESS_DB_NAME=exampledb
# MySQL Configuration
MYSQL_DATABASE=exampledb
MYSQL_USER=exampleuser
MYSQL_PASSWORD=examplepass
MYSQL_ROOT_PASSWORD=rootpassword
The .env
file is a crucial file used to externalize and manage the settings of the Docker environment. The information set in this file is referenced within docker-compose.yml
, allowing the configuration of each service (WordPress, MySQL) to be handled dynamically.
1. WordPress Configuration
- WORDPRESS_DB_HOST=db
- Explanation: Specifies the hostname of the database that WordPress will connect to. Here, the database service name
db
is used as the hostname.
- Explanation: Specifies the hostname of the database that WordPress will connect to. Here, the database service name
- WORDPRESS_DB_USER=exampleuser
- Explanation: The username that WordPress will use to access the database. In this case, the user is set as
exampleuser
.
- Explanation: The username that WordPress will use to access the database. In this case, the user is set as
- WORDPRESS_DB_PASSWORD=examplepass
- Explanation: The password that WordPress will use to access the database. Here, the password is set as
examplepass
.
- Explanation: The password that WordPress will use to access the database. Here, the password is set as
- WORDPRESS_DB_NAME=exampledb
- Explanation: Specifies the name of the database that WordPress will use. Here, the database is named
exampledb
.
- Explanation: Specifies the name of the database that WordPress will use. Here, the database is named
2. MySQL Configuration
- MYSQL_DATABASE=exampledb
- Explanation: The name of the MySQL database that will be created. WordPress will store its data in this database.
- MYSQL_USER=exampleuser
- Explanation: The MySQL username that will access the database. It is set as
exampleuser
.
- Explanation: The MySQL username that will access the database. It is set as
- MYSQL_PASSWORD=examplepass
- Explanation: The password for the MySQL user. This password secures access to the database.
- MYSQL_ROOT_PASSWORD=rootpassword
- Explanation: The password for the MySQL root (administrator) user, used for overall database management.
Role of the .env
File:
By using this .env
file, you can manage important information such as the database name, username, and password in a single place, making it easy to modify settings depending on different environments.
Next, I’ll provide the translation and explanation for the contents of the Dockerfile
.
FROM wordpress:latest
# Set UID and GID to match the host environment
ARG UID=1000
ARG GID=1000
RUN usermod -u ${UID} www-data && groupmod -g ${GID} www-data
# Create /var/log/apache2 and set permissions
RUN mkdir -p /var/log/apache2 && chown -R www-data:www-data /var/log/apache2
# Create html directory and set ownership
RUN mkdir -p /var/www/html && chown -R www-data:www-data /var/www/html
# Install necessary packages
RUN apt-get update && apt-get install -y \
mariadb-client \
wget \
unzip \
rsync \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Set entrypoint.sh
COPY entrypoint.sh /usr/local/sbin/entrypoint.sh
RUN chmod +x /usr/local/sbin/entrypoint.sh
# Add ServerName
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
ENTRYPOINT ["/usr/local/sbin/entrypoint.sh"]
Dockerfile is a configuration file used to create a custom WordPress environment. It contains commands, packages, and settings necessary to properly run WordPress. Below is an explanation of each part.
FROM wordpress
- Explanation: This specifies the base Docker image. It uses
wordpress:latest
to build the environment based on the latest WordPress image.
# Set UID and GID to match the host environment
ARG UID=1000
ARG GID=1000
RUN usermod -u ${UID} www-data && groupmod -g ${GID} www-data
- Explanation: This section sets the user ID (UID) and group ID (GID) of the
www-data
user and group inside the container to match the host environment. This prevents issues with file permissions and ownership by aligning the IDs with those of the host system. This means you don’t need to manually change ownership on the host.
# Create /var/log/apache2 and set permissions
RUN mkdir -p /var/log/apache2 && chown -R www-data:www-data /var/log/apache2
- Explanation: This creates the directory
/var/log/apache2
where Apache logs will be saved and sets its ownership to thewww-data
user. This ensures that Apache can correctly output its logs.
# Create the html directory and set ownership
RUN mkdir -p /var/www/html && chown -R www-data:www-data /var/www/html
- Explanation: This creates the directory
/var/www/html
, where WordPress HTML files will be stored, and sets its ownership to thewww-data
user. This ensures that WordPress can operate on these files without permission issues.
Installing and Optimizing Necessary Packages
RUN apt-get update && apt-get install -y \
mariadb-client \
wget \
unzip \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
1. Package Installation
- Explanation: Installs necessary packages such as the MariaDB client,
wget
, andunzip
. These packages are required for proper operation, including the ability to connect WordPress to MySQL, download files, and unzip them.
2. apt-get clean
- Explanation: Clears out the package manager’s cached files to avoid leaving unnecessary package files on the disk.
- Purpose: Reduces the size of the Docker image, helping to maintain a lightweight and efficient setup. This is a key step for ensuring efficient operation.
3. rm -rf /var/lib/apt/lists/*
- Explanation: Deletes the package lists (index files) maintained by
apt-get
after installation. - Purpose: Since these lists are no longer needed after the installation, deleting them further reduces the image size for more efficient operation.
Why This is Important
A smaller Docker image is more efficient for deployment and transfer. Removing unnecessary files provides the following benefits:
- Reduced image size: By removing caches and lists, the image becomes smaller, reducing disk usage and improving transfer times during deployment.
- Improved performance: A smaller image results in faster container startup and downloads, ensuring smoother operation.
This command is crucial for cleaning up the system and enhancing efficiency.
# Set entrypoint.sh
COPY entrypoint.sh /usr/local/sbin/entrypoint.sh
RUN chmod +x /usr/local/sbin/entrypoint.sh
- Explanation: Copies the
entrypoint.sh
script from the host to the container’s/usr/local/sbin/entrypoint.sh
and grants execute permissions. This script plays a key role in automatically setting up WordPress during container startup.
# Add ServerName
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
- Explanation: Adds
ServerName localhost
to Apache’s configuration file to avoid warnings related to the server name.
ENTRYPOINT [“/usr/local/sbin/entrypoint.sh”]
- Explanation: Specifies the script that will run when the container starts. In this case,
entrypoint.sh
is executed, which handles WordPress setup and initialization.
This Dockerfile correctly builds a WordPress and MySQL environment and installs the necessary packages and permissions. It is particularly notable for using entrypoint.sh
to automatically perform initial setup when the container starts.
Next, I’ll provide the translation and explanation for the contents of entrypoint.sh
.
#!/bin/bash
set -e
echo "Starting entrypoint.sh script..."
# Set permissions for the HTML directory
echo "Setting permissions for the html directory..."
chown -R www-data:www-data /var/www/html || { echo "Failed to set permissions"; exit 1; }
chmod -R 755 /var/www/html || { echo "Failed to change permissions"; exit 1; }
# If wp-config.php does not exist, copy the WordPress files
if [ ! -f /var/www/html/wp-config.php ]; then
echo "wp-config.php does not exist. Copying WordPress files for the first time."
cp -rv /usr/src/wordpress/* /var/www/html/ || { echo "Failed to copy files"; exit 1; }
# Rename wp-config-sample.php to wp-config.php
if [ -f /var/www/html/wp-config-sample.php ]; then
echo "Renaming wp-config-sample.php to wp-config.php."
mv /var/www/html/wp-config-sample.php /var/www/html/wp-config.php || { echo "Failed to rename file"; exit 1; }
fi
fi
# Download and extract Japanese version of WordPress
if [ ! -d /var/www/html/wp-content/languages ]; then
echo "Downloading Japanese version of WordPress..."
if ! wget https://ja.wordpress.org/latest-ja.zip -O /tmp/latest-ja.zip; then
echo "Failed to download"
exit 1
fi
echo "Extracting Japanese version of WordPress..."
if ! unzip /tmp/latest-ja.zip -d /tmp/wordpress-ja; then
echo "Failed to extract"
exit 1
fi
echo "Copying Japanese WordPress files..."
cp -rv /tmp/wordpress-ja/wordpress/* /var/www/html/ || { echo "Failed to copy files"; exit 1; }
fi
# Update the WordPress core files to the latest version
echo "Updating WordPress core files..."
if ! wget https://ja.wordpress.org/latest-ja.zip -O /tmp/latest-ja.zip; then
echo "Failed to download WordPress core files"
exit 1
fi
if ! unzip -o /tmp/latest-ja.zip -d /tmp/wordpress-ja; then
echo "Failed to extract WordPress core files"
exit 1
fi
# Copy core files while excluding the wp-content directory
rsync -a --exclude 'wp-content' /tmp/wordpress-ja/wordpress/ /var/www/html/ || { echo "Failed to copy WordPress core files"; exit 1; }
# Apply environment variables to wp-config.php
if [ -f /var/www/html/wp-config.php ]; then
echo "Applying environment variables to wp-config.php."
sed -i "s/database_name_here/${WORDPRESS_DB_NAME}/" /var/www/html/wp-config.php
sed -i "s/username_here/${WORDPRESS_DB_USER}/" /var/www/html/wp-config.php
sed -i "s/password_here/${WORDPRESS_DB_PASSWORD}/" /var/www/html/wp-config.php
sed -i "s/localhost/${WORDPRESS_DB_HOST}/" /var/www/html/wp-config.php
fi
echo "Contents of /var/www/html:"
ls -la /var/www/html
echo "Exiting entrypoint.sh script."
exec apache2-foreground
entrypoint.sh
is a script that runs automatically when the container starts, and it simplifies the initial setup of WordPress and database connection. This script is mainly used to handle permission settings, file copying, and WordPress environment configuration automatically. Below is an explanation of each section. The update of WordPress core files will be explained later.
#!/bin/bash
set -e
- Explanation: At the beginning of the script,
set -e
is used. This ensures that if any error occurs in the script, execution stops immediately. This prevents errors from being overlooked and ensures the script runs safely.
echo "Starting entrypoint.sh script..."
- Explanation: A message indicating the start of the script. It is logged to help track the script’s execution status.
Setting Permissions for the HTML Directory
echo "Setting permissions for the html directory..."
chown -R www-data:www-data /var/www/html || { echo "Failed to set permissions"; exit 1; }
chmod -R 755 /var/www/html || { echo "Failed to change permissions"; exit 1; }
- Explanation: This sets the owner and group of the
/var/www/html
directory towww-data
and grants appropriate file permissions. This ensures that WordPress can operate correctly with the required file access permissions.
Copying WordPress Files if wp-config.php
Does Not Exist
if [ ! -f /var/www/html/wp-config.php ]; then
echo "wp-config.php does not exist. Copying WordPress files for the first time."
cp -rv /usr/src/wordpress/* /var/www/html/ || { echo "Failed to copy files"; exit 1; }
# Rename wp-config-sample.php to wp-config.php
if [ -f /var/www/html/wp-config-sample.php ]; then
echo "Renaming wp-config-sample.php to wp-config.php."
mv /var/www/html/wp-config-sample.php /var/www/html/wp-config.php || { echo "Failed to rename file"; exit 1; }
fi
fi
- Explanation: If
wp-config.php
does not exist, it copies the initial WordPress configuration files and renameswp-config-sample.php
towp-config.php
. This generates the configuration file required for WordPress to run for the first time.
Downloading and Extracting the Japanese Version of WordPress
if [ ! -d /var/www/html/wp-content/languages ]; then
echo "Downloading Japanese version of WordPress..."
if ! wget https://ja.wordpress.org/latest-ja.zip -O /tmp/latest-ja.zip; then
echo "Failed to download"
exit 1
fi
echo "Extracting Japanese version of WordPress..."
if ! unzip /tmp/latest-ja.zip -d /tmp/wordpress-ja; then
echo "Failed to extract"
exit 1
fi
echo "Copying Japanese WordPress files..."
cp -rv /tmp/wordpress-ja/wordpress/* /var/www/html/ || { echo "Failed to copy files"; exit 1; }
fi
- Explanation: If the Japanese version of WordPress is not yet installed, it downloads, extracts, and copies the files to
/var/www/html
. You can easily modify the URL to support multiple languages. For example, WordPress versions in different languages can be retrieved from the official WordPress website:- English (default): https://wordpress.org/latest.zip
- French: https://fr.wordpress.org/latest-fr.zip
- German: https://de.wordpress.org/latest-de_DE.zip
- Spanish: https://es.wordpress.org/latest-es_ES.zip
Applying Environment Variables to wp-config.php
if [ -f /var/www/html/wp-config.php ]; then
echo "Applying environment variables to wp-config.php."
sed -i "s/database_name_here/${WORDPRESS_DB_NAME}/" /var/www/html/wp-config.php
sed -i "s/username_here/${WORDPRESS_DB_USER}/" /var/www/html/wp-config.php
sed -i "s/password_here/${WORDPRESS_DB_PASSWORD}/" /var/www/html/wp-config.php
sed -i "s/localhost/${WORDPRESS_DB_HOST}/" /var/www/html/wp-config.php
fi
- Explanation: This applies environment variables, defined in
.env
or elsewhere, to thewp-config.php
file. This dynamically sets the database connection information, ensuring WordPress operates correctly.
echo "Contents of /var/www/html:"
ls -la /var/www/html
- Explanation: Displays a list of files and directories in
/var/www/html
to verify that the files have been copied correctly.
echo "Exiting entrypoint.sh script."
exec apache2-foreground
- Explanation: A message indicating the script has completed successfully. Then, Apache is started in the foreground, launching the web server.
entrypoint.sh
Script Summary
The entrypoint.sh
script automates the initial setup of WordPress, including copying files, configuring database connections, and setting up file permissions. This makes the initialization process fast and eliminates the need for manual setup.
PHP.ini Configuration and Placement
When setting up a WordPress environment, it is important to have a php.ini
file, which controls key PHP settings. The php.ini
file should be placed in the same directory as docker-compose.yml
and Dockerfile
, as mentioned earlier, making it easy to manage and reflect configuration changes immediately.
1. Example of php.ini
Below is a basic example of a php.ini
configuration. The settings for post_max_size
, upload_max_filesize
, and date.timezone
are particularly important as they affect file uploads and date/time handling. In this article’s example, the following values have been adjusted to handle larger themes:
; File upload limits
post_max_size = 64M
upload_max_filesize = 200M
; Timezone setting
date.timezone = "Asia/Tokyo"
- post_max_size: Specifies the maximum amount of data that can be sent in a POST request, such as file uploads. Here it is set to 64MB, but you can adjust this value as needed.
- upload_max_filesize: Defines the maximum size of a file that can be uploaded. If you need to handle large files, increase this value.
- date.timezone: Sets the timezone used by PHP. In this case, it is set to Asia/Tokyo, but you can change it to your region (e.g.,
America/New_York
for the US).
2. Customizing Settings for Your Environment
PHP settings vary depending on the environment. Adjust the values for post_max_size
, upload_max_filesize
, and date.timezone
to suit your working environment or project requirements.
- File upload limits: If large file uploads are required, increase
upload_max_filesize
. - Timezone: Ensure that the PHP timezone matches your server’s timezone for accurate date/time handling.
3. Mounting the php.ini
File in docker-compose.yml
To ensure that the php.ini
file is properly reflected in the container, it is mounted as shown in the previous docker-compose.yml
example:
services:
wordpress:
volumes:
- ./php.ini:/usr/local/etc/php/conf.d/php.ini # Mount the php.ini file
With this configuration, the settings from php.ini
are used inside the container and are immediately applied.
How to Start the Docker Container
Here is an easy-to-follow guide for beginners on how to set up a WordPress environment with Docker. By following these steps, you’ll be able to get WordPress running quickly.
1. What You’ll Need
- A computer with Docker and Docker Compose installed.
- The
docker-compose.yml
file (this defines the WordPress environment). - The
php.ini
file (PHP configuration file). Dockerfile
entrypoint.sh
.env
2. Step 1: Verify the Docker Compose Configuration File
First, check the docker-compose.yml
file. This file contains settings for WordPress, MySQL, and more. It will be used to start the containers. The content of docker-compose.yml
is the same as the one shown above and should work without any issues.
services:
wordpress:
image: wordpress:latest
ports:
- "8888:80"
volumes:
- ./php.ini:/usr/local/etc/php/conf.d/php.ini
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: rootpassword
Step 2: Starting the Containers
Using Docker Compose to start the containers is very simple. You only need to run two commands.
Building the Container Image
Open a terminal or command prompt and navigate to the directory where the docker-compose.yml
file is located. Then, execute the following command:
docker-compose build
What Happens?
When this command is executed, Docker will create the necessary containers (WordPress and MySQL). After waiting for a while, the containers will be ready.
The command docker compose build
builds the image based on the build section defined in the docker-compose.yml
file, using the specified Dockerfile. For example, if the following is specified:
services:
wordpress:
build:
context: .
dockerfile: Dockerfile
- context: .: Specifies the context directory for the build (usually the directory where the Dockerfile is located). Files and directories in the context are referenced during the image build process.
- dockerfile: Dockerfile: Specifies the Dockerfile used for the build. This Dockerfile defines how the container’s contents will be constructed.
The image is built step by step according to the instructions in the Dockerfile. Each instruction (e.g., FROM
, RUN
, COPY
) is built as a separate layer, and each layer is cached.
For example:
- FROM wordpress: Uses the latest WordPress image as the base.
- RUN apt-get update && apt-get install: Installs necessary packages.
- COPY entrypoint.sh: Copies a file from the host to the container.
Using Cache in the Build Process
During the build process, caching is used. If the same step was built previously, Docker uses the cached result instead of executing the step again, speeding up the build process. However, if you want to skip the cache and rebuild all steps, you can use the --no-cache
option:
docker compose build --no-cache
The build process applies to all services defined in the docker-compose.yml
file. For example, if the file includes both a WordPress service and a MySQL service, each will be built separately.
Once the Build is Complete
When the build finishes, a new Docker image is created locally. This image can be launched as a container using the docker compose up
command. In other words, the docker compose build
command constructs the image according to the Dockerfile’s instructions and saves it locally, preparing the image to be run later with the docker compose up
command.
Starting the Container
After the build is complete, run the following command:
docker-compose up -d
What Happens?
This command launches the WordPress and MySQL environments in the background. Once the environment is up and running, you can access the WordPress setup page by opening your browser and navigating to http://localhost:8888.
Step 3: Verifying the Containers
To check if the containers are running correctly, run the following command:
docker ps
This command displays a list of currently running containers, allowing you to verify that the WordPress and MySQL containers are operational.
Step 4: Stopping the Containers
To stop the containers, run the following command:
docker-compose down
- All containers will be stopped: All containers defined in the
docker-compose.yml
file will be stopped. - Containers will be removed: The stopped containers will be removed from the system.
- Network removal: Any custom networks created by
docker-compose.yml
will also be deleted (if the network was automatically created).
Optionally Removing Volumes
If you specify docker compose down --volumes
, the data volumes that have been persisted with the containers will also be deleted.
However, the image itself is not deleted, so the containers can be restarted with docker compose up
the next time.
Important Notes on Volume Removal
If you use docker compose down --volumes
, the volumes are deleted, which means the data in the mounted volumes will also be deleted.
Specifically:
1. If the Directory is Mounted on the Host
For example, if a directory like ./db_data:/var/lib/mysql
is mounted on the host side, running docker compose down --volumes
will not delete the data in the ./db_data
directory on the host.
While the volume itself is deleted, the data on the host remains, so it can be reused when the container is restarted.
2. If Only the Volume is Used
If the data is persisted purely in a Docker volume (without being mounted to a host directory), running docker compose down --volumes
will delete the volume, and the data in the database will also be deleted.
In this case, the data will not remain when the container is restarted, meaning the data will be lost.
Clarifying the Optional Volume Removal in Step 5
Running docker compose down --volumes
deletes the Docker-managed storage volumes. These “volumes” refer to Docker’s internal storage areas.
However, when a directory is mounted on the host, the data is directly stored on the host’s file system. In such cases, even if the container or volume is deleted, the data on the host is not deleted.
Example Comparison:
Here’s a clearer explanation of how the two scenarios differ:
1. When Mounting a Directory on the Host (./db_data:/var/lib/mysql
)
services:
db:
volumes:
- ./db_data:/var/lib/mysql
In this case, the ./db_data
directory on the host is mounted to /var/lib/mysql
inside the container. This means that the database data is saved in the host’s directory.
Since the data is saved on the host directory, even if the container or volume is deleted, the data remains on the host.
Even if you run docker compose down --volumes
, the data on the host (./db_data
directory) will not be deleted.
2. When Using Docker’s Internal Volume (db_data:/var/lib/mysql
)
services:
db:
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
In this case, the Docker-managed volume (db_data
) is mounted to /var/lib/mysql
inside the container. The database data is stored in the Docker-managed volume, not in the host directory.
Since the data is not stored on the host file system, it is only saved in Docker’s internal volume.
If you run docker compose down --volumes
, the volume is deleted, and the database data is completely erased.
Simple Summary:
./db_data:/var/lib/mysql
(Stored on the host):- The data is stored on the host’s
./db_data
directory, so even if the container or volume is deleted, the data remains. - Running
docker compose down --volumes
will not delete the data on the host.
- The data is stored on the host’s
db_data:/var/lib/mysql
(Stored in Docker’s volume):- The data is stored in Docker’s internal volume
db_data
, so runningdocker compose down --volumes
will delete both the volume and the data. - When the container is restarted, the data will be gone and cannot be recovered.
- The data is stored in Docker’s internal volume
Conclusion:
If you want to store the data on the host, you should use a setting like ./db_data:/var/lib/mysql
to mount the host directory.
Be cautious when managing data with only Docker volumes, as running docker compose down --volumes
will erase the data.
To summarize, docker compose down
stops and deletes the containers, removes the network, but does not delete the image.
With these steps, you can easily set up a WordPress environment using Docker. By simply running the commands, you can quickly try WordPress in your own environment.
Managing the containers is straightforward, as you can start them with docker-compose up
and stop them with docker-compose down
, making it easy and accessible even for beginners.
Will the Data Be Reset When the Container is Restarted?
1. Basic Understanding
Although Docker containers run as temporary environments, if properly configured, the data will not be lost when the container is restarted. For example, even if the container is stopped and then restarted, the posts and theme settings will remain intact.
2. Why Isn’t the Data Lost?
The reason the data isn’t reset is due to data persistence. In the docker-compose.yml
file, WordPress files and the database data are saved on the host, meaning the data is retained even when the container is restarted.
volumes:
- ./wordpress:/var/www/html # Persist WordPress files on the host
- ./db_data:/var/lib/mysql # Persist MySQL data on the host
./wordpress
: This directory stores WordPress themes and post data. Since it is saved on the host, it remains intact even if the container is restarted../db_data
: This directory stores the MySQL database data. Since it is also saved on the host, there is no risk of losing posts or other data. Even running thedocker compose down --volumes
command will not delete it.
3. Example: Behavior When Restarting the Container
Even if the container is stopped and restarted, the data remains as follows:
- Stopping the container:
docker-compose down
- Restarting the container:
docker-compose up -d
In this process, the data stored on the host is automatically remounted to the container, so the previous state is preserved. Any theme changes or posts will remain unchanged.
4. Cases Where Data May Be Reset
If the data is reset, the following issues might be the cause:
- Incorrect volume settings: If the volumes for saving data to the host are not properly set in
docker-compose.yml
, the data will not be retained, and it may be reset after a restart. - Host directory deleted: If the data stored on the host is deleted for any reason, the data may be reset when the container restarts.
By ensuring that data is saved on the host, there is no concern about data being reset when restarting Docker containers. With proper volume settings in the docker-compose.yml
file, changes to posts or themes will remain intact, allowing you to confidently restart the container.
How to Apply the Latest WordPress State on Subsequent Restarts
1. Automatic Updates with entrypoint.sh
By adding a script to entrypoint.sh
, WordPress core files are automatically updated to the latest version each time the container is restarted. This script updates everything except the wp-content
directory, ensuring that theme and plugin customizations are preserved while only the core files are updated automatically when the container is restarted.
# Update WordPress core files to the latest version
echo "Updating WordPress core files..."
wget https://ja.wordpress.org/latest-ja.zip -O /tmp/latest-ja.zip
unzip -o /tmp/latest-ja.zip -d /tmp/wordpress-ja
# Overwrite everything except the wp-content directory
rsync -a --exclude 'wp-content' /tmp/wordpress-ja/wordpress/ /var/www/html/
- Advantages: WordPress core files are automatically updated to the latest version simply by restarting the container, eliminating the need to manually download and copy files.
- Protection of the
wp-content
Directory: Customized themes and plugins are not affected, as they are excluded from the update process.
2. Using docker pull
and Rebuilding
By using docker pull
to get the latest WordPress image and then restarting the container with docker-compose up
, the new image will be applied. This allows you to use the latest version of WordPress, but files mounted on the host (such as /var/www/html
and wp-content
) are retained.
- Advantages: Not only WordPress but also other container services like MySQL may be updated to the latest versions, resulting in an overall system update.
- Important Note: Even after running
docker pull
, WordPress files, themes, and plugins mounted on the host will not be overwritten. You will still need to use a script likeentrypoint.sh
to update the core files.
Automatic Updates (Recommended)
Using entrypoint.sh
, you can automatically update the WordPress core files when the container restarts. Themes and plugins in the wp-content
directory are preserved and remain unaffected.
Manual Updates
If you choose not to use automatic updates, you can manually copy the latest version of WordPress files to the host to perform the update.
1. Updating the Docker Image
Using the docker pull
command, you can fetch the latest WordPress image from Docker Hub or a private repository. This updates the image stored locally to the latest version. However, there are a few points to keep in mind:
- New WordPress Version: The new image contains the latest WordPress core files, so when you restart the container with
docker-compose up
, this new image will be used.
2. Impact on Files Mounted on the Host
Files and directories mounted on the host through the docker-compose.yml
file are not overwritten when the image is updated. Here’s how it works:
/var/www/html
Directory: If this directory is mounted on the host, even after updating the image withdocker pull
, the files on the host are preserved. Therefore, the update to WordPress core files is not automatically reflected in the files on the host.wp-content
Directory: This directory, where themes, plugins, and uploaded images are stored, is persisted on the host. As a result, runningdocker pull
does not change it, and customizations and settings are retained.
3. Behavior of entrypoint.sh
(Automatic WordPress Core Updates)
The script added to entrypoint.sh
automatically updates the WordPress core files to the latest version every time the container is restarted. The key point is that the wp-content
directory is excluded from the update, so theme and plugin customizations are not lost.
# Update WordPress core files to the latest version
echo "Updating WordPress core files..."
wget https://ja.wordpress.org/latest-ja.zip -O /tmp/latest-ja.zip
unzip -o /tmp/latest-ja.zip -d /tmp/wordpress-ja
# Overwrite everything except the wp-content directory
rsync -a --exclude 'wp-content' /tmp/wordpress-ja/wordpress/ /var/www/html/
- Protection of the
wp-content
Directory: This script usesrsync
to overwrite everything except thewp-content
directory. The important thing is that customized files such as themes and plugins are safely retained.
4. How to Apply the Latest WordPress Core Files
There are two ways to apply the latest WordPress core files:
- Automatic Update (Recommended): The script added to
entrypoint.sh
automatically fetches and applies the latest WordPress core files when the container restarts. This removes the need to manually copy the files. - Manual Update: You can manually copy the latest WordPress files to the
./wordpress
directory on the host and overwrite them as needed. However, be careful to preserve thewp-content
directory.
Since the files mounted on the host are retained even after running docker pull
, the themes, posts, and plugin settings will not be lost.
To reflect the latest WordPress core files, it is recommended to use the script added to entrypoint.sh
for automatic updates.
The entrypoint.sh
script runs every time the container restarts, ensuring that WordPress core files are always up to date without affecting theme or plugin customizations.
Steps to Perform Regularly
1. Fetch the Latest Version of the Docker Images
To regularly update the WordPress and MySQL images to the latest versions, run the following commands:
docker pull wordpress
docker pull mysql
2. Stop the Containers
After updating the images, stop the containers:
docker compose down
3. When Rebuild is Necessary
A rebuild is necessary under the following conditions:
- If the Dockerfile is edited: For example, when adding new packages or changing settings within the Dockerfile.
- If
entrypoint.sh
or configuration files are edited: For instance, if you modify the WordPress auto-update script or change PHP settings.
In such cases, rebuild without using the cache by running the following command:
docker compose build --no-cache
4. Restart the Containers
After rebuilding the image or simply restarting the container, start the containers in the background with the following command:
docker compose up -d
Summary of Regular Steps:
- Use
docker pull
to get the latest images and then stop the containers withdocker compose down
. - If files or settings have been modified, rebuild the containers with
docker compose build --no-cache
. - If no changes were made, simply restart the containers with
docker compose up -d
.
Issues with File Mounting and Directory Creation in Docker
When trying to mount files in Docker, if the file does not exist on the host, a directory is created instead of the file. This is due to Docker’s default behavior, and appropriate countermeasures are needed. Below, I’ll explain the reasons and solutions for this issue.
1. Difference Between File and Directory Mounting
- Directory Mounting: When mounting a directory in Docker, if the directory does not exist on the host, Docker automatically creates the directory.
- File Mounting: On the other hand, when attempting to mount a file, if the file does not exist on the host, Docker creates a directory instead of a file. This behavior can lead to unexpected results.
2. Conditions Under Which the Problem Occurs
This issue occurs in the following scenarios:
- File Does Not Exist on the Host: For example, when there is a file mount setting in
docker-compose.yml
, and the file does not exist on the host, Docker creates a directory at that location instead of the file.yamlコードをコピーするvolumes: - ./php/php.ini:/usr/local/etc/php/conf.d/php.ini
If./php/php.ini
does not exist on the host, Docker creates a directory calledphp.ini
on the host. - File Expected in the Container: While the container expects
php.ini
to be a file, a directory is mounted instead, causing unexpected behavior in the container.
3. Cause of the Issue
The cause of this issue lies in Docker’s default behavior. When a file intended for mounting does not exist on the host, Docker automatically creates a directory. Therefore, it is crucial to create the file on the host beforehand.
4. Solutions
To avoid this issue, the following measures are effective:
- Create the File on the Host in Advance: By creating the file on the host beforehand, you can prevent Docker from mistakenly creating a directory. For example, you should prepare the
php.ini
file on the host from the beginning. - Check File Existence in
entrypoint.sh
: Another effective solution is to add a check in your script to see if the file exists on the host, and create a dummy file if necessary.
When mounting files in Docker, the mount might not behave as expected if the file doesn’t exist on the host, causing Docker to create a directory instead. To prevent this, it is important to prepare the files you intend to mount on the host beforehand. This is especially important for configuration files like php.ini
, as having them on the host from the start ensures stable behavior from Docker.
Why Default Language Settings May Differ with the Same WordPress Image
Even when using the same WordPress Docker image, the default language settings may vary. This can be due to the following factors:
Possible Causes
- Differences in Environment Variables: When using
docker run
, Japanese locale may be set automatically, but when usingdocker-compose
, the default language settings may differ if environment variables are not properly configured indocker-compose.yml
. - Impact of Themes or Plugins: The theme or plugins being used may influence language settings. Some themes or plugins may default to English.
- Internet Connection Differences: WordPress automatically downloads necessary translation files via the internet during the initial installation. If the internet connection is unstable or restricted, this download may fail, causing the default display to be in English.
Overwriting wp-includes
and wp-admin
Directories
Overwriting the wp-includes
and wp-admin
directories is generally safe. These directories contain files related to WordPress core functionality, and users rarely need to customize them directly.
Roles of Each Directory
wp-includes
: Contains libraries and scripts that provide the internal functionality of WordPress. These files support essential WordPress functions.wp-admin
: Contains files related to the WordPress admin dashboard, supporting the display and operation of administrative functions.
Reason for Overwriting
These directories contain core files that should be updated when WordPress is upgraded. Overwriting them during the installation of a new version of WordPress applies the latest features and security patches.
Directories to Be Cautious About
wp-content
: This directory contains themes, plugins, and user-uploaded files. Since it holds custom settings and content, care must be taken to avoid overwriting it.
Conclusion
Overwriting wp-includes
and wp-admin
, which contain WordPress core functionality, is safe and should be done when updating to the latest version. However, be careful not to overwrite the wp-content
directory, which contains themes, plugins, and user-uploaded files.
By distinguishing between files that should and should not be overwritten when updating or configuring WordPress, you can safely maintain an up-to-date WordPress environment.
Why Is a Separate Container Needed? (Regularly Saving the Database as a .sql File)
Simply using a mounted database can make data migration and restoration a bit complicated. Below, I’ll explain the specific reasons and the advantages of using a backup container.
Why Migrating a Mounted Database Is Difficult:
Complexity of Direct Data Handling:
While mounted data is saved in the host’s ./db_data
directory, simply copying this directory is not sufficient for migrating the database.
Since database binary files depend on the specific MySQL version and settings, migrating them to a different environment can be challenging.
MySQL Version and Configuration Compatibility:
When migrating between different servers or MySQL versions, there can be compatibility issues with the binary data.
Because of this, there is a risk that a simple file copy may not successfully migrate the data.
Ensuring Data Consistency Is Difficult:
When migrating the data of a running database, the database often needs to be temporarily stopped to ensure data consistency.
Especially for large databases, copying files while the database is running can result in incomplete data migration.
Advantages of Using a Backup Container:
Ease of Migration:
- .sql files are MySQL’s standard export format, making them highly compatible when importing into other MySQL instances. This allows for smooth migration to different environments or servers.
- Even when MySQL versions or configurations differ, migrating with a .sql file is highly reliable.
Simple Backup and Restoration:
- By regularly backing up the database as a .sql file, you can easily restore the data whenever necessary.
- Additionally, like a snapshot, you can maintain a specific point-in-time version of the data, making it easy to revert to a previous state if an issue arises.
Cross-Environment Flexibility:
- .sql files are text-based database dumps, making them easy to migrate to other servers or local environments.
- Even when migrating data between different server environments, .sql files offer flexibility and reliability.
Conclusion:
While a mounted database allows for real-time data storage, it is more convenient to regularly back up the database in .sql format to facilitate easy migration and restoration. Using a backup container increases data integrity and reduces risks during migration.
If You Want to Connect to the Database via Command Line
To connect to a MySQL container running in Docker from an external source, you typically use the following command. If the MySQL container’s port is correctly exposed in the docker-compose.yml
file, external connections will be allowed.
Connecting to the MySQL Container from the Host Machine
To connect to the MySQL container from the host machine, use the following command:
mysql -u root -p -h 127.0.0.1 -P 3306
-u root
: Specifies the MySQL username. Here, the default root user is used.-p
: Prompts you to enter the password.-h 127.0.0.1
: Specifies the host’s IP address. Normally, when connecting from the host machine to the container, 127.0.0.1 (the loopback address) is used.-P 3306
: Specifies the MySQL port number. By default, MySQL uses port 3306.
Why External Connections Are Enabled
In a MySQL container running in Docker, if the port is exposed in the docker-compose.yml
file, external connections are enabled by default. Unlike a regular MySQL server, there is no need to manually modify the bind-address
setting, making it easy to allow external connections. Use the password set in the environment variable MYSQL_ROOT_PASSWORD
.
For example, the following docker-compose.yml
configuration exposes MySQL’s port:
services:
db:
image: mysql:latest
ports:
- "3306:3306"
This configuration maps port 3306 on the host machine to port 3306 in the MySQL container, allowing external connections.
Accessing from Another PC
If you want to connect to the MySQL server on the Docker container from another PC, you need to specify the IP address of the host machine instead of 127.0.0.1 (localhost). For example, if the host machine’s IP address is 192.168.1.100, you would connect using the following command:
mysql -u root -p -h 192.168.1.100 -P 3306
In this case, 192.168.1.100 is the host machine’s IP address within the local network. Using this IP address, you can connect to the MySQL container on the host from another PC.
Important Notes
- When connecting from another PC, make sure that port 3306 is open in the host machine’s firewall settings.
- Additionally, if the ports are not properly exposed in
docker-compose.yml
, the connection from other PCs might be blocked. Ensure that port mapping is correctly set up as shown below:
ports:
- "3306:3306"