What Is a Dockerfile?
When you run the Docker run command and specify WordPress, Docker uses this file to build the image itself. The Dockerfile is essentially the build instructions to build the image.
The advantage of a Dockerfile over just storing the binary image (or a snapshot/template in other virtualization systems) is that the automatic builds will ensure you have the latest version available. This is a good thing from a security perspective, as you want to ensure you’re not installing any vulnerable software.
Let’s pull this apart piece by piece.
FROM
The first part is the FROM command, which tells us what image to base this off of. This is the multi-layered approach that makes Docker so efficient and powerful. In this instance, it’s using the php:5.6-apache Docker image, which again references a Dockerfile to automate the build process.
If you look at the PHP Dockerfile, you’ll see that it does all of the work of building the PHP environment with Apache for you. You can use this to start any PHP-based project too, so you’ll see it referenced by other systems like Joomla, Magento, and similar.
RUN
The next set of calls are the RUN commands. This is what runs within the container at build time. From the calls, you can see that ModRewrite is enabled (RUN a2enmod rewrite), and it then installs the php-gd and libraries required to run it. This isn’t standard in the default PHP 5.6 build, as it’s designed to be as small as possible. There’s also the mysqli PHP extension, which again is another dependency for WordPress.
VOLUME
This is the default volume we overrode in the last article. Specifying it in the Dockerfile allows it to be externally mounted via the host itself or a Docker data container. If it’s not defined here, then it’s not possible to access outside of the container.
ENV
This sets the environment variables, which can be used in the Dockerfile and any scripts that it calls. These are persistent with the container too, so they can be referenced at any time. In the case of the WordPress Dockerfile, we can see that it sets the version number, the upstream version number, and then the SHA1 hash of the download.
Then, with the environment variables set, there’s another RUN command to download the corresponding WordPress tarball, check it against the hash (to ensure it correctly downloaded), untar the files to /usr/src, and set the ownership of the files so that Apache can access them.
COPY
The COPY command is simply as it sounds. It can copy a file (in the same directory as the Dockerfile) to the container. You can do this for things like custom configuration files or like in this instance, a file to run commands after the container has been set up.
ENTRYPOINT
ENTRYPOINT and CMD are probably the two which will confuse you the most, especially if you’re not a heavy Linux user. In fact, with a casual read of the documentation, they very much seem like the same thing! However, there are some subtle differences, and they can both be used at the same time.
If the ENTRYPOINT isn’t specified, Docker will use /bin/sh -c as the default. However, if you want to override some of the system defaults, you can specify your own entrypoint and therefore manipulate the environment. The ENTRYPOINT command also allows arguments to be set from the Docker run command as well, whereas CMD can’t.
CMD
Hopefully, if the ENTRYPOINT part makes sense CMD will now fall into place. CMD is the default argument passed to the ENTRYPOINT. In the case of the WordPress Dockerfile, it seems a bit counter-intuitive. If you look at the bottom of the entrypoint.sh file, you’ll see exec ”$@“. This means that after the BASH script has run, the final command is to execute the arguments passed to the script. In this case, CMD is set to apache2-foreground, which therefore starts WordPress.
Don’t worry too much if ENTRYPOINT and CMD still seem very confusing. In most instances, you can simply use the existing configurations (as you’ll see below). If you’re at the point where you need to write your own CMD and ENTRYPOINT commands, CenturyLink Labs has a great blog article which covers the two commands in depth. I highly recommend reading it if you’re after more information.
Further commands
As this was a specific example, not all of the commands available were used. Have a read through the Dockerfile reference in the official Docker documentation to go over all of the available commands.
Modifying a Dockerfile
Now that you have a basic understanding, we can now modify the files to suit our own needs. Let’s get a copy of the official WordPress Dockerfile and make a few modifications. If you’ve got Git installed, clone the existing repo so that we can modify it:
In the “apache” directory, you’ll see the Dockerfile for WordPress. Since WP-CLI is a popular plugin which makes manipulating WordPress from the command line easy, let’s add it to the Dockerfile. Here’s what we need to add:
The wrapper around the wp-cli is to ensure it runs as the www-data user. Otherwise it will run as the root user. For this, we also need to install the sudo command available as well. Here’s the code for this:
We also want to quickly delete any of the files regarding apt in order to keep the container as lean as possible, which can be done with the following:
We now need to build the image. This can be done from the command line, and it will create a local Docker image for us. Since it’s not from a repo, we tag the build so that we can easily reference it. Here’s the build command we’ll use:
docker build -t wordpress-with-cli .
The period at the end of the command specifies the directory to build, which in this case is the directory we’re in. With the freshly built image, we can now fire up an instance of this and give our WP-CLI a go. All we need to do is reference the tag name we used (wordpress-with-cli) when creating the container. Here’s the command:
Note: This assumes you have the database container configured as per our previous article. If you’re copying the command verbosely, you’ll need to ensure the database container has been created and started. We can now call this from the command line just as if it were a local install. Here’s an example to install a new theme and activate it:
The output from the WP-CLI should be displayed, and you should see it going through the process of downloading the theme and then activating it. If you point your browser at the site (http://:8080), you should see the lovely quark theme installed and running for you.
Creating a New Dockerfile
While modifying an existing Dockerfile works, it also means you need to keep updating it every time the original changes. Because of the layered nature, we can do this quite easily. The changes we put in the file above can now be converted into a standalone Dockerfile and simply reference the parent WordPress layer. Here’s what the Dockerfile would look like:
As you can see, we simply referenced the WordPress image with the FROM command and then added our modifications. Anytime we build a new container, it’ll always use the latest version of WordPress. You could create builds tied to the latest subversion (e.g., 4.2) as well, so that you can still have version stability.
I’ve also uploaded the Dockerfile for the wp-cli to GitHub and to the Docker Hub Repository with the package name wordpress-with-wp-cli. This means that anyone can now use this image without having to first create the Dockerfile, just like you would with any of the other images available. You can also upload images to the public repository for free, or Docker allows private repos if you buy a subscription through them.
Docker also provides the source code to run your own private repository. It comes as the core system only, meaning that there’s no authentication or web interface available by default. These items need to be added on, since you would be customising them for your own environment. We’ll be covering this in a future article as well, so that you have all the pieces to the Docker ecosystem.