In the last post we set up a docker environment on an EC2 instance, but we didn’t really explain what docker is all about or why we were doing this. In this one, we are going to dive deeper into Docker and Docker Compose and we’ll set up a local environment that works nearly identically to the one we’ve set up in AWS. With our environment set up, we will build a website with WordPress to deploy to the EC2 instance.
At Forty4Digital we use Docker as part of our continuous integration process because docker containers perform consistently when they are running on a developer’s laptop, our CI servers, and production servers.
Docker is software for running Linux containers, there are open source and enterprise editions. Containers are somewhat like virtual machines, except that they use the same kernel as the host operating system. Containers are much more efficient and portable than virtual machines, which has helped them become a key driver in the rise of micro-services, and DevOps.
If you need a way to quickly spin up local development environments, and/or deploy projects to the cloud Docker is a good choice. Docker can help streamline your workflows and enable more automation in your development and operational processes.
Docker Compose is a tool for managing multi-container deployments, which can be pretty handy since it is common to use multiple containers when architecting an application with Docker. Docker Compose uses YAML files to define the container architecture, you can specify which images to launch, and provide volumes and port mappings that connect the containers together and with the outside world via the host machine that Docker is running on. This means that when a new developer comes on to the project, or it comes time to deploy to a remote host you only need to set up Docker, pull down the project’s code and run one command
docker-compose up to get the application up and running, this can save hours if not days of trial-and-error setup because no two machines are ever the same, Docker makes them the same.
WordPress is the world’s most popular open-source Content Management System (CMS). We use WordPress here at Forty4Digital to build client sites and as the backbone of rich web-apps and mobile applications. We like WordPress because it is easily extended with thousands of plugins and themes available, and if you can’t find a plugin you like you can write your own. We also like the clean and customizable admin dashboard that makes it easy for team members of varying technical ability to help manage a website or app.
WordPress is so easy that the hardest part about working with it used to be just getting an environment set up to run it, but Docker makes that easy too. If you haven’t looked into WordPress before I suggest you do, a couple of Google searches should pull up plenty of WP fans (and a few detractors), here are some articles that showcase many WP pluses:
Business websites, blogs, and eCommerce sites are the WordPress bread-and-butter, but there honestly isn’t much that WordPress can’t do. That said there are certain use cases that are less of a fit. If you don’t need a backend admin panel for your site or app, and there will not be frequent updates to your content, then you probably don’t need WordPress. In these instances, a statically hosted single-page app might provide a better user experience and lower the maintenance burden
In the last post, we set up Docker on an Amazon EC2 instance, now we are going to show you how to use Docker in your local development environment.
Install Docker, Docker-Compose
You can download an installer for your operating system here: https://www.docker.com/community-edition, There is also a great getting started guide here: https://docs.docker.com/get-started/. Check out these resources to get your Docker application up and running, then come back.
Now you should be able to execute docker commands in your terminal application of choice (I use iTerm2 for Mac).
$ docker --version and
$ docker ps
For a list of commands just type
$ docker you should have Docker Compose installed as well
The Docker run command is used to start a container specified by name
$ docker run [container-name] it could be a container from a registry like Docker Hub, or one that you built locally.
Run a container
Try running this hello-world container:
$ docker run hello-world
This will pull the hello-world image from Docker Hub and start a container with it, this container prints out a message to the console and then exits.
If you execute the
$ docker ps command again there should still be no running containers, there is a stopped hello-world container now though. You can see that container by using
$ docker ps -aYou can see some details about the container including the container id, image, start command, and name. You can specify a container name with the run command, if not Docker will generate a random (and often weirdly interesting) name for you.
You can use the container id or name with other docker commands to get information about or perform actions on the containers.
$ docker logs f240e95dfd18 displays log entries for the applications running in a container.
$ docker start f240e95dfd18 starts a stopped container
$ docker stop f240e95dfd18 stops a running container (hello-world stops itself)
$ docker rm f240e95dfd18 deletes a container
WordPress Docker Image
This is the official WordPress Docker image, when you start this image with
$ docker run it starts a web-server with a fresh copy of WordPress waiting to be installed. However WordPress needs a MySQL database to function and so you need to provide a path to a database server when starting a WordPress container. This is where Docker Compose comes into play.
Getting Started with Docker Compose
With Docker compose you use a YAML file to configure the services for your application and bring them all up at once with a single command. For our WordPress site, we will define a WordPress service that is linked to a non-standard port on the host machine (wp port 80 -> host port 8000) this way you can visit the WordPress site in your browser by going to http://localhost:8000. Our WordPress service will depend on a MySQL service that we also need to define.
Create the WordPress Compose file
Create a new directory on your computer for this project and then navigate to that directory:
$ mkdir wp-site && cd wp-site
Add a file named
version: "3" services: db: image: mysql:5.7 ports: - "3306:3306" volumes: - db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: somepassword MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: password wp: depends_on: - db image: wordpress:latest ports: - "8000:80" restart: always volumes: - "./wp-data:/var/www/html" environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: password volumes: db_data:
Let’s take a minute to understand what we are saying with this file.
The first line is saying which version of the compose file syntax we are using, next are the services. Services are where we specify which containers we want to start, with docker compose you can scale and load-balance the containers for a given service.
db service is for the database, it specifies a MySQL container, this compose file has port 3306 on the container linked to port 3306 on your host machine, this is so you can easily connect to the database run queries. If you are already running a MySQL service on port 3306 you will need to modify the host port something like:
ports: - "3336:3306"
Next we specify a volume named db_data, this volume stores the database information on your computer so that it is persisted even if the database container is deleted and recreated.
restart:always line is pretty self-explanatory, this means that if the container(s) in this service crash docker will try to restart it(them).
The environment section is used to inject environment variables into the containers when they are started, these varibles are used durring container start up, in this case they specify the root user password and a database and user to be created for WordPress.
Next is the WordPress service named
wp, this service depends on the
db service, which means that docker will wait for a succesful response from the database server before starting the WordPress container. This service is using the latest version of the official WordPress image, and has the host machines port 8000 linked to port 80 on the WordPress container. The WordPress container has an Apache web server listening on port 80. This service is also set to restart always.
For the wp service, we are using a relative path for the volume, a volume is not necessary for the containers to run but doing this will give us easy access to the WordPress files. When the service starts you will see a
wp-data/ directory created alongside this compose file.
Finally, the wp service has some environment variables, these are used to configure the database settings to match the vaules that we provided for the MySQL container(s).
Below services we have the creation of the
db_data named volume that is linked from the
Start the services with docker-compose
Now that we have a compose file we are only one command away from a fully-functional local WordPress installation.
Run this command in the same directory as the docker-compose.yml file to start the services:
$ docker-compose up -d
Now you can visit http://localhost:8000 to walk through the WordPress installation process:
If you look inside the project directory you can see the
wp-data/ directory with all of the WordPress files and folders. This is conveinent if you need to make a change to one of the files, or if you want to write your own themes or plugins. You can open this folder with your favorite text-editor or IDE, this folder is synced with the WP container, so you do not need to stop and start docker-compose when you update these files.
Hopefully, you found this infformation helpful, in our next post we are going to build a website with WordPress to deploy to cloud using Docker Compose.