Until now, we have been trying to keep up-to-date by using the apt update command in our containers. Such knowledge is very useful not only for updating Docker containers, but also for migration, scaling, backup strategies, and many other scenarios. However, methods such as the apt update command, shown below, are not recommended: while it is technically possible to perform apt update
and package installation within the Docker container, it is not recommended as a Docker best practice. The reasons for this include
Violation of the principle of immutability
There is a principle that Docker containers should be immutable. That is, a container should not change throughout its lifecycle and should start in the same state each time it is re-created. Performing apt update
or package installations within a container can change the state of the container, compromising reproducibility and predictability.
Security Risks
Updating or installing packages directly within a container may introduce security risks. In particular, there is a risk of introducing unexpected vulnerabilities or malware when installing packages from untrusted sources.
Size and Performance Impact
Installing packages within a container can increase the size of the image and increase the time it takes to distribute and boot. It may also increase security vulnerabilities due to the accumulation of unnecessary packages and dependencies.
Recommended approach
- Use Dockerfile: Define required packages and dependencies in the Dockerfile and install them when building the custom image. This ensures that containers are immutable and have the same environment no matter where they are run.
- Take advantage of multi-stage builds: By separating the build and execution environments, you can keep the image size small and include only the packages you need.
For example, if a certain package is needed, it can be described in the Dockerfile as follows
Example Dockerfile
FROM ubuntu:latest
RUN apt-get update && apt-get install -y \
[required package] \
&& rm -rf /var/lib/apt/lists/*
This approach allows you to build the environment you need while ensuring container reproducibility, security, and performance.
The location of the PHP configuration file php.ini
in the container will vary depending on the version of PHP in particular and the base image being used, but a general guideline is as follows
/usr/local/etc/php/
directory
- This directory is used to store PHP’s main configuration file
, php.ini
; the settings that are initially loaded when PHP is started are located here. - If you want to completely replace the default
php.ini,
or if you want to define PHP’s overall configuration from scratch, it is appropriate to place the files in this directory.
/usr/local/etc/php/conf.d/
directory
- This directory is for placing additional configuration files; PHP will also automatically read the files in this directory and add them to the
php.ini
configuration. - It is convenient to place
.ini
files in theconf.d/
directory if you want to customize only certain settings, or if you want to make it easier to manage several different configuration files. So you do not have to modify the originalphp.ini
file, and it is easier to add or update settings.
Which should I choose?
- If you want to customize the overall PHP settings or completely replace the default
php.ini
, place thephp.ini
in/usr/local/etc/php/
. - If you only want to change certain settings, or if you want more flexibility in managing your settings, you can place a customized
.ini
file (e.g.,custom.ini
) in the/usr/local/etc/php/conf.d/
directory.
In fact, in many cases, the conf.d/
directory is easier to manage, and it is easier to add or change settings. That said, you can keep the default PHP settings and apply only the necessary changes.
What if I don’t have a backup on my host?
We suggest the following method Copy the necessary files from the container to the host. Using the docker cp
command is a direct and easy way to copy files and directories from the container to the host. This command can be used to copy files and directories in a particular container to the host system.
Example usage
docker cp [container name or ID]: [destination path on host]
For an example in my environment, the usage example is as follows
docker cp wp:/var/www/html . /wp/html
docker cp wp:/usr/local/etc/php . /wp/php
This command copies the /var/www/html
directory in the wordpress
container (where the WordPress files are stored) to ./wp/html
copy the PHP related files as well to save you the trouble of reconfiguring them. This will back up the files in /var/www/html
to the host.
When copying files or directories from the container to the host using the docker cp
command, if the destination directory does not exist, it will be created automatically. However, this is only the case if the destination path is specified as a directory.
For example, to copy the /var/www/html
directory in a container to a new directory ./wp/html
, the ./wp/html
directory does not exist, the docker cp
command will create this directory and then copy the files. In the above operation, ./wp/html
is automatically created and the contents of /var/www/html
are copied there. However, if you are copying files as a single file path (e.g., copying a single file in a container to a new file path on the host), the parent directory of that path is not automatically created.
However, the following error may occur
invalid output path: directory “/home/mamu/wp” does not exist
The docker cp
command does not automatically create the final directory to which files and directories are copied. That is, the last segment of the destination path (in this case html
) may be created automatically, but its parent directory (in this case /home/mamu/wp
) must exist beforehand. It’s tricky, but I figured it out by actually trying it myself.
Solution.
To solve this problem, the destination directory (or at least its parent directory) must be created manually. Use the following command to create the necessary directories
mkdir -p /home/mamu/wp
Notes.
- Note that if the destination directory already exists and contains files, this operation may overwrite its contents.
- When making backups, dynamic data, especially databases, should also be considered; in the case of WordPress, not only the contents of the
wp-content/uploads
directory, but also the database export is important. It is also easier later if you copy any PHP-related customized configuration files.
After copying a file or directory from a container to a host with the docker cp
command, it is common that the owner (owner) or group of the file or directory is set to the user who performed the copy operation (often root
or the current user). In particular, some applications, such as web servers, require that the owner or group of a particular file or directory be set to a particular user or group (e.g., www-data
).
For example, if you are using the WordPress container, your web server (e.g. Apache or Nginx) will typically run as the www-data
user. Therefore, the wp-content
directory and any other directories that need to be accessed by the web server must be owned by the www-data
user and group. To ensure this, you will need to change the owner of the copied files and directories.
Changing Ownership
To change the owner of a file or directory to www-data
, use the chown
command. For example, to change the owner of the ./wp/html
directory and all files in it to the www-data
user and group, execute the following command
sudo chown -R www-data:www-data ./wp/html
This command works as follows
chown
: Command to change the owner of a file or directory.- –
R
: Recursive operation on all files and subdirectories in a directory. www-data:www-data
: Specifies the new owner and group. In this case, both user and group arewww-data
../wp/html
: The path to the file or directory whose owner is to be changed.
Note: sudo
is used because this operation may require superuser privileges. The directory creation command did not use superuser privileges. If the user has write permission to the directory, the mkdir
command can create the directory without using sudo
. For example, if it is the user’s home directory or a subdirectory thereof, the directory can usually be created without sudo
. On the other hand, if you want to operate on a directory that affects the entire system (e.g., /usr/local
) or a directory owned by another user, you must use sudo
and execute the command with superuser privileges. It is easy to forget to do this, so we have decided to describe it here.
This procedure will ensure that the web server can access files and directories properly and that your WordPress site will function properly. The change of ownership is important for security reasons, and it is recommended that only certain users (in this case, the web server) have access to important files and directories.
What if the OS system is different between the host and the container?
For example, if the host is CentOS-like and the container is Debian-like, it is important to ensure that the User ID (UID) and Group ID (GID) match and are properly configured. This is because the default user and group UID/GID differ between Linux distributions. For example, the UID for the www-data
user is often 33
in Debian, but may be different on CentOS. These differences can cause authorization problems. We have experienced this many times and describe how to deal with it.
Specific steps
- Verify UID/GID: Check the UID/GID.
- Run the
id www-data
command in the container to check the UID and GID of thewww-data
user and group. - Check for the existence of similar users on the host system and check their UID/GID as well.
- Run the
- Create a user on the host: 1.
- If the
www-data
user does not exist on the host system, or if the UID/GID is different, create awww-data
user on the host with the same UID/GID as the container.
sudo groupadd -g [GID] www-data
sudo useradd -u [UID] -g www-data -M -N -s /sbin/nologin www-data
where[UID]
and[GID]
are the values ofwww-data
as confirmed in the container. - If the
- File and directory permission settings:.
- Set the appropriate owner (
www-data
) for the files and directories copied from the container to the host.
sudo chown -R www-data:www-data /path/to/directory
- Set the appropriate owner (
- Security checks: Check the security of the
- When adding new users or groups to the system, reassess the security risks and take additional security measures as necessary.
Points to note
- Security and compatibility: When using different Linux distributions for hosts and containers, be aware of differences in security policies and file systems. In particular, if you are using a security-enhanced Linux (SELinux), additional configuration may be required.
What about PHP related files?
Use the docker cp
command to copy the contents of wp:/usr/local/etc/php
to . After copying to ./wp/php
, it is common for the ownership of PHP configuration files to be set to the current user or root
; for PHP configuration files, it is not necessarily necessary to change the ownership of these files.
Although PHP configuration files (e.g. php.ini
) contain configuration information that is read by the server, these files are not written by the server process (e.g. the www-data
user). Therefore, read access permissions are sufficient for ownership of these files. In practice, PHP configuration files are only read at server startup and are rarely modified at runtime.
However, the following points should be noted
- Permissions: In order for the PHP configuration file to be read by the server process, appropriate read permissions must be set. Usually, this is not a problem as long as read permissions are granted to the owner of the file, a group, or another user.
- Security: PHP configuration files may contain critical settings that affect the server’s operation. Therefore, it is recommended that these files be secured and that unnecessary write permissions be removed.
If the PHP configuration files are working correctly after copying and the server starts without problems, no ownership changes will be necessary. However, if you experience problems reading the configuration file when the server starts, recheck the file’s permissions and adjust as necessary.
We have actually prepared the following docker-compose.yml. start the update process in Oracle Cloud. based on the contents of docker-compose.yml
, create this file under the wp
directory directly under your home directory. (For clarity and control) However, you will need to adjust the volume mount path appropriately in that case.
If you place the docker-compose.yml
file under the wp
directory, Docker Compose will resolve relative paths based on the directory where the docker-compose.yml
file resides. So, if the docker-compose.yml
file is located in the wp
directory, use the prefix ./wp
as a prefix is not necessary.
For example, consider the following directory structure
wp/
├── docker-compose.yml
├── html/
│ └─ (WordPress files...)
└── php/
└── php.ini
In this case, docker-compose.yml
will look like this
version: "3.8"
services:
wordpress:
container_name: wp
image: wordpress:latest
ports:
- "8080:80"
environment:
- TZ=Asia/Tokyo
restart: always
volumes:
- /etc/localtime:/etc/localtime:ro
- ./html:/var/www/html # Specify relative paths from `wp` directory base.
- ./php/php.ini:/usr/local/etc/php/php.ini
Here, ./html
and ./php/php.ini
paths are based on the wp
directory where the docker-compose.yml
file resides. Therefore, if you create the docker-compose.yml
file under the wp
directory, the ./wp
prefix is not necessary and a direct relative path is used.
By adjusting the path in this way, you can place the docker-compose.yml
file under the wp
directory and mount the files and directories in the appropriate locations in the container.
The reason there is no database information is because the database is on another server. The same may be true if you already have a customized wp-config.php
. If wp-config.php
already contains the proper database connection information and you have it mounted as a volume, then setting environment variables in the docker-compose.yml
file There is no need to do this. wp-config.php
is the core file for managing WordPress configuration and holds many site-specific settings, including database connection information. This configuration mounts the entire WordPress html
directory, which means that wp-config.php
, customized php.ini
files, and other necessary files and directories (e.g., wp-content
) are also contained within the container The container will now contain the database connection information and other configuration settings. Database connection information and other settings will now be automatically applied when the container is started.
Also, if you want to set the container’s time zone to Japan Standard Time (JST), it is more efficient to put the settings in the docker-compose.yml
file instead of setting them manually each time the container is launched. This way, the timezone is automatically applied each time the container is launched, ensuring consistency.
How to set the time zone in docker-compose.yml
To set the time zone, add an environment variable in the environment
section that specifies the time zone. It is also common to mount the host’s /etc/localtime
to the container so that the container can use the host’s time zone settings.
In the absence of a Dockerfile
, using the official wordpress:latest
image directly is the appropriate method.
https://hub.docker.com/_/wordpress
Update with the following steps, where wp is the currently running WordPress container.
- Stop the container: Run the following command
docker stop wp
- Delete the container: docker rm wp
docker rm wp
- Fetch the latest WordPress image: docker pull wordpress:latest
docker pull wordpress:latest
- Start the service using
docker-compose.yml:
docker compose up -d
This command starts the WordPress service in the background based on thedocker-compose.yml
file. The container will be created according to the settings specified in this file (port, volume, container name, etc.).
When running a WordPress container, files and directories that need to be mounted other than the PHP configuration, wp-config.php
, and wp-content
directories are usually based on specific customization and operational requirements. Here are a few additional elements worth considering
1. .htaccess files
- If you are using Apache, you can easily manage server configuration, redirection rules, etc. by mounting
.htaccess
files. This is often placed in the root ofvar/www/html
, but depending on the site configuration, it may be placed in a subdirectory. In the case of this container, it resided in the root ofvar/www/html
. Note that this is a hidden file. 2.
2. SSL Certificate
- If you want to run your site using HTTPS, you will need to securely mount your SSL certificate and private key in the container. However, it is more common to configure these on a reverse proxy or load balancer than on the WordPress container itself.
If you have a database on an external server, this is not a problem.
The docker-compose.yml
above does not specifically describe networking. In that case, when you use Docker Compose to start the service, it will create its own network by default. On the same host, services (containers) can refer to each other by name in this network and can communicate inside the network. However, default communication between different Docker Compose projects (or with containers launched independently) is restricted. That is, they cannot communicate with the database because it is a separate network from the database.
The following is a record of a network created by the network on its own.
mamu@g570:~/wp$ docker compose up -d
WARN[0000] /home/mamu/wp/docker-compose.yml: version is obsolete
[+] Running 1/2
⠋ Network wp_default Created 3.0s
✔ Container wp Started
The recommended way to allow WordPress and existing database containers to communicate is to create a user-defined network and connect both containers to that network. To create a user-defined network, follow these steps It may not be recommended to match the database network. A solution will appear later.
Creating a user-defined network
docker network create my-custom-network
Using a user-defined network in docker-compose.yml
version: "3.8"
services:
wordpress:
container_name: wp
image: wordpress:latest
ports:
- "8080:80"
restart: always
volumes:
- ./html:/var/www/html
- ./php/php.ini:/usr/local/etc/php/php.ini
networks:
- my-custom-network
networks:
my-custom-network:
external: true
This configuration uses a user-defined network named my-custom-network
. This network must also be applied to the database container.
3. Connecting database containers
If the database container is already running, you can connect to the user-defined network with the following command
docker network connect my-custom-network name or ID of the database container
This step will allow the WordPress container and the database container to communicate within the same user-defined network. You can then check the IP address of the container and put it in wp-config.php. docker inspect
command can be used to find out the IP address of a particular container. This is especially useful if you want to know which network the container is connected to and its IP address within that network.
For example, if you know the name or ID of a container (e.g. wordpress_container
), you can run the following command to get more information about the container and find its IP address
docker inspect wordpress_container
The output is in JSON format and contains a lot of information, but the IP address is under the "NetworkSettings"
key. Because of the length of the output, you can filter only specific information by using the grep
command (available on Linux and Mac terminals) or the --format
option built into the docker inspect
command.
As an example, to get the IP address of a specific container, use the following
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' wordpress_container
This command prints out the IP address of the specified container (in this example, wordpress_container
).-The -f
or --format
option is used to format the output. In this case, only the IP address of the container is extracted using Go’s template language.
*Note
When a container is connected to an existing user-defined network using the docker network connect
command, the container will belong to multiple networks. The container will be able to communicate via all networks to which it is connected.
For example, if the database container is already connected to the default bridge
network and you then run docker network connect my-custom-network database_container
, the database_container
will be connected to the bridge
network and my-custom-network
.
This is especially useful in complex environments where certain applications need to access services on different networks. However, for security reasons, connections to non-essential networks should be avoided. Connections to unnecessary networks increase security risks because they may provide an opportunity for an attacker to traverse the network and probe for vulnerabilities.
To see which networks your containers are connected to, you can use the docker inspect
command mentioned earlier. Network connection information can be found in the "Networks"
section under "NetworkSettings"
.
If you need to disconnect a container from a particular network, you can use the docker network disconnect
command. For example, to disconnect database_container
from the default-network
, run: default-network
was actually named bridge.
docker network disconnect default-network database_container
This will disconnect database_container
from the
, leaving only the other network connections. In this way, you can take advantage of Docker’s networking capabilities to flexibly manage communication between containers.default-network
And let’s not forget. The IP address has changed because we have made the database container belong to a custom Docker network. Put this IP address in wp-config.php
. The IP address can be checked with the docker inspect
command described earlier. When you write both WordPress and database settings in docker-compose.yml
as follows, just write db for the host in wp-config.php
. With this configuration, the Docker network
is managed within Docker Compose, and the alias db
allows other services (in this case wordpress
) to access the MariaDB server under the name db
.
If both WordPress and the database are on the same server, the following is done. The reason I am describing the port number of the database is because I want to connect to it from the outside. For example, Workbench or python scripts.
version: "3.8"
services:
db:
container_name: maria
image: mariadb:latest
ports:
- "3306:3306"
volumes:
- db_data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=examplepass
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=wordpress
restart: always
wordpress:
container_name: wp
depends_on:
- db
image: wordpress:latest
ports:
- "8080:80"
environment:
- WORDPRESS_DB_HOST=db
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=wordpress
- TZ=Asia/Tokyo
restart: always
volumes:
- /etc/localtime:/etc/localtime:ro
- ./html:/var/www/html
- ./php/php.ini:/usr/local/etc/php/php.ini
volumes:
db_data:
To keep your Docker images up-to-date, you will need to update your images periodically. This docker-compose.yml
uses existing images but not the latest ones. docker pull
command downloads the latest version of a given image from Docker Hub or another registry. This allows you to get the latest changes, including security patches and feature updates.
How to get the latest WordPress images
Using the latest images is very important from a security perspective, especially for WordPress. You can use the following command to pull the latest WordPress images
docker pull wordpress:latest
This command will download the latest WordPress image with the latest
tag.
Usage considerations
- Specify the version: If you are using
- Although using the
latest
tag will automatically fetch the latest version, it is sometimes recommended to specify a specific version for production environments. This improves predictability and repeatability of the environment. For example, you can specify a specific version such aswordpress:5.7
.
- Although using the
- Updating the image and restarting the container:.
- After acquiring a new image, you will need to recreate the container in order to update an existing container to use that image. This usually involves the process of stopping the container, deleting it, and restarting it with the new image.
- Data Persistence:.
- WordPress requires proper volume setup to hold critical data, such as
wp-content
directories and databases. This ensures that the container’s data is retained even if the image is updated.
- WordPress requires proper volume setup to hold critical data, such as
- Automation considerations:.
- For more efficient management, you may want to consider automatic image updates. For example, a CI/CD pipeline can be set up to automatically deploy new images as they become available.
By using the latest images, you can enjoy both functional improvements and enhanced security. Keeping the environment up-to-date also makes future maintenance and troubleshooting easier. docker-compose pull
command is another good practice. This command is used to update the images of all services defined in the docker-compose.yml
file. In other words, this command will automatically update all the specified images to the latest version.
Finally, the
With the docker-compose.yml
file and the files properly backed up (or mounted) on the host, you can update your services (e.g., WordPress) to the latest version at any time. It can also be restored to a previous state if necessary. This process increases deployment flexibility and facilitates version control.
Update Process
- Image update: To update the image specified in
docker-compose.yml
(e.g.wordpress:latest
) to the latest version, run the following commanddocker-compose pull
All images described indocker-compose.yml
will be updated to the latest version. - Restart the container: Restart the container with the latest images.
docker-compose up -d
This command will stop and remove containers as needed, then recreate and start them using the latest images.
Data Persistence
- Use of volumes: You can mount important data and settings, such as
/var/www/html,
which contains WordPress core files, plugins, themes, etc., WordPress configuration fileswp-config.php
, PHP configuration files, etc., on the host’s file system or on a volume to mount the container so that the data will be retained even if the container is deleted. - Backups: Make regular backups of your database and important files to ensure that your data is safe to restore in case something goes wrong.
Just in case.
The docker commit
command can be used to save a new image of the currently running container state. This allows you to create a snapshot of the container at the moment and later launch a new container using that image. This is useful if you want to keep a particular working environment or configuration in case of “just in case” situations.
How to use docker commit
Here are the basic instructions for using the docker commit
command
docker commit [options] container_id new_image_name
For example, if your container ID is c3f279d17e0a
and you want to save its state as an image myapp:snapshot
, you can execute the following
docker commit c3f279d17e0a myapp:snapshot
This command saves the current state of the running container as a new image named myapp:snapshot
. This image can be used to recreate the container later. It will revert back to the original as soon as it fails.
Usage scenarios for docker commit
- Save your development state: This is useful if you are debugging a particular issue during development and want to save the state of your application.
- Backing up configuration and data: Keep a container containing your application configuration and specific data so that you can quickly restore your environment when needed.
- Replicating a test environment: If you want to share a particular test environment with other team members, you can create an image of that environment for easy distribution.
Notes
- Image size: The image created by
docker commit
can be larger than the original base image because it contains all of the container’s changes. Proper management and cleanup is required. - State persistence: committing saves changes to the container file system, but any data stored in external storage, such as databases or files, must be backed up to that storage itself.
- Deprecated usage: some users use
docker commit
frequently to “version control” their Docker images, but it is originally recommended thatDockerfile
be used to build images. This makes the environment more transparent and reproducible.
While docker commit
is a very useful tool in certain circumstances, in normal operation, building and versioning images using Dockerfile
should be the basis.