Only a few days ago I was looking into different solutions in order to migrate this coding blog to a different host provider. There are some changes I would like to make but instead of messing around with the live version I would very much prefer to have a local WordPress instance to play with.
The last time I set up a local environment for CMS like Joomla or Drupal was more than a decade ago. From what I recall it was just painful and woefully boring. I also hated the mess of dependencies and services that have to be installed and setup specifically for the target OS. On top of that, if the dev machine had a different OS than the production machine, which was common, configuration might not match and thus leading to a series of painful yet necessary debugging steps in order to bring the applications up and running. In fact, a common trick was to create a VM matching the OS used in the production server and then installing the necessary programs.
Before diving into the “good old-fun” of messing around with Apache and Mysql I asked a good friend of mine, which is a professional DevOps engineer, if he knew an stress-free or automated way to setup a WordPress environment.
“Use Docker you fool!” he said. “Docker is a container platform that hosts containers, which are standardised unit of software. Most likely you will find Docker images for WordPress and a Db that are ready to go for your OS“.
Amazed and completely confused I started doing my background research. I found out that Docker is a background daemon, a service, that runs applications in their own user-space, called containers. As such, an application within a container is isolated and cannot access other resources on the OS. The concept of containers have been around for decades in the UNIX world. The word jail was used to describe a modified runtime environment for a program that prevents that program from accessing protected resources. Building such containers was no easy task, prone to error and often it mislead to a false sense of security if it wasn’t configured properly. Docker simplifies the process of creating, building, running, distributing and also removing containers. Docker uses existing container engines to get the jail feature a containerised application requires.
The following picture, taken from the Docker website, shows an example of the Docker infrastructure.
Before Docker, applications were likely installed within a virtual machine (which is in fact what I used to do) in order to achieve the same level of containment and isolation, or to simply re-use a specific environment for development and testing. A VM provides virtual hardware on which an OS and other programs can be installed. However a VM takes up resources from the host machine as an entire OS (comprised of user and kernel-space) is to be run. Containers instead are not virtualised, Docker doesn’t use hardware virtualisation, and programs running inside the Docker interface directly using the kernel of the host OS. Removing a layer of complexity no resources are wasted by running redundant software or simulating virtual hardware.
Going back to the original topic…how then a containerised application run in isolation, in a jail, by a background service helps in speeding up the process of installing and configuring WordPress and MySql?
The good news is: there are a lot of images available from the Docker Hub, which is the place where open Docker images are stored and that are ready to be pulled, installed and run in a container.
First thing first let’s install Docker on the target machine, for Windows or Mac (I haven’t tried Linux though). Once that’s done the Docker command will be available in the terminal or in the command prompt.
To pull WordPress and Mysql in their own containers use these two commands:
docker pull wordpress docker pull mysql
Hang in there we are halfway there. Now that the images are available locally they need to be run and configured in order to work. Let’s start and configure mysql first:
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=somewordpress MYSQL_DATABASE wordpress MYSQL_USER wordpress MYSQL_PASSWORD wordpress
docker run --name some-wordpress -p 8080:80 -d wordpress -e WORDPRESS_DB_HOST db:3306 WORDPRESS_DB_USER wordpress WORDPRESS_DB_PASSWORD wordpress WORDPRESS_DB_NAME: wordpress
WordPress is now available on the 8080 port and configured to connect to Mysql.
The entire process of downloading and configuring Docker images can be also sped up by using the docker-compose tool. Compose is a tool for defining and running multi-container Docker applications using a YAML file to configure the application’s services. With a single command is then possible to pull, run and configure one or multiple applications.
Let’s have a look at the yml file needed:
version: '3.3' services: db: image: mysql:5.7 # the mysql image to pull from docker hub # after the semicolon a specific version # can be targeted or the latest using :latest volumes: - db_data:/var/lib/mysql # where to put the files in the container filesystem restart: always environment: MYSQL_ROOT_PASSWORD: somewordpress MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress wordpress: depends_on: - db # puts a dependency on the mysql container defined above image: wordpress:latest ports: - "8080:80" restart: always environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_NAME: wordpress volumes: - ./wp:/var/www/html #bind mount a folder on the host within the container volumes: db_data:
Create a folder, create a file called docker-compose.yml in it and past the content from the snippet above. Create a sub-folder called wp (give it read-write privileges for non-sudo users). The above command will bind mount the directory wp (on the host machine) into the WordPress container, so you will be available to access the content of /var/www/html (which contains all of the WordPress files).
Finally run this command from the folder that contains the yml file:
docker-compose up -d
and that’s a wrap! In a matter of minutes both the WordPress and Mysql image are downloaded, run and configured in isolation to be ready to use. This didn’t mess up with my local machine as the images can be removed at any time by using a docker command like:
docker stop containerId docker rm containerId
All the dependencies needed are confined within the container and don’t pollute the dev machine.
Docker has many more benefits, which are beyond the scope of this article but If you’re interested in reading more I’d suggest to check out the Docker blog. There are also tons of resources out there, in the form of books and articles made by members of the community.
I had fun learning Docker and found it’s a great solution for what I was looking for. I hope you will find this article useful! Let me know what you think in the comments below!