This article is Part 1 of my Serious WordPress Development series. All code can be found here. For more context please read the introduction.
Regardless what application is being developed, it all starts with setting up your local machine in a simple and automated fashion, so that a new team member can get on-boarded quickly. If each developer has the very same environment, then the “works on my machine” effect is avoided. Hence, we reduce the risk of wasting time on single and localised errors caused by environmental differences.
Setting up a new local environment must be done with the following goals in mind:
- Standard – the setup should use well-known and well-supported packages and infrastructure setup primitives.
- Speed – the process should take a few minutes, and not hours.
- Simple – the initial setup should be automated, done with a minimal set of simple commands (ideally one), without requiring the developer to know about its intricacies.
- Self-contained – once setup, the need for “external” dependencies – i.e. remote applications, servers, databases, cloud services – should be limited to package repositories (e.g. yum, docker, NPM, maven repos etc…)
My team initially decided to use the free MAMP local WordPress server environment. MAMP is downloadable as an OS native package, and can also be installed with Homebrew on MacOSX. MAMP comes installed with PHP, Apache, and MySQL, and provides a user interface that lets you manage your local WordPress sites.
I had several issues with MAMP. The initial installation is a multi-step process requiring installing MAMP and configuring it (e.g. what ports the site should run on). It is largely a manual process done through the MAMP graphical user interface. More importantly we were relying on a third party software for doing something pretty standard. So this setup definitely failed the Standard, Speed, and Simple test.
I therefore replaced MAMP with a Docker setup using Docker Compose. I often use Docker Compose for orchestrating multiple containers locally. I find it very easy to get started with, as it requires only one deployment descriptor (docker-compose.yml
) and a set of simple commands (up
, down
, stop
, start
). It is also relatively well documented, with an active community of users.
Below is an example I re-created for this article that is very similar to what we had:
version: '3.1' services: wordpress: image: wordpress:5.3.2-php7.3-apache container_name: wordpress restart: always ports: - 80:80 environment: WORDPRESS_DB_HOST: mysql WORDPRESS_DB_USER: wp_db_user WORDPRESS_DB_PASSWORD: wp_db_password WORDPRESS_DB_NAME: wp_db volumes: - ./wordpress:/var/www/html mysql: image: mariadb:10.3.22 restart: always container_name: mysql ports: - 3306:3306 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: wp_db MYSQL_USER: wp_db_user MYSQL_PASSWORD: wp_db_password volumes: - ./mysql/data:/var/lib/mysql phpmyadmin: image: phpmyadmin/phpmyadmin container_name: phpmyadmin depends_on: - mysql restart: always ports: - 8989:80 environment: PMA_HOST: mysql
This setup enables a few things that are really important to me:
1. The whole stack is orchestrated as one fleet of resources, composed of three integrated containers:
-
- the
wordpress
app - the
mysql
database - the
phpmyadmin
app
- the
Note: WORDPRESS_DB_HOST: mysql
and PMA_HOST: mysql
allow the WordPress and MyPhpAdmin apps to connect to the database using the mysql
service name on the Docker Compose virtual network.
2. All WordPress files are mounted to our host folder ./wordpress
. It means that, while the container runs, any change to a PHP file will be automatically picked up.
3. All MySQL database files are mounted to our host folder ./mysql/data
. It makes it easier to tear down if necessary and re-create the site from scratch (we will use that in a later part of my series about dB changes management).
If you want to try this stack you can do the following:
git clone https://github.com/jdamore/wordpress-blog.git git checkout 9662a4a5379840 docker-compose up -d
The initial creation of the three containers on my machine with a pruned docker system (i.e. cleaned of any image, volume, or network) takes under a minute. Once finished you should have something like that:
➜ wordpress-blog git:(master)docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cb2aec9b914e phpmyadmin/phpmyadmin "/docker-entrypoint.…" 30 minutes ago Up 30 minutes 0.0.0.0:8989->80/tcp phpmyadmin e1e95cfb1a95 wordpress:5.3.2-php7.3-apache "docker-entrypoint.s…" 30 minutes ago Up 30 minutes 0.0.0.0:80->80/tcp wordpress 0a963bda3776 mariadb:10.3.22 "docker-entrypoint.s…" 30 minutes ago Up 30 minutes 0.0.0.0:3306->3306/tcp mysql
Then all you have left to do is:
- Setup your WordPress site, username, and password by visiting
http://localhost
, and after a few clicks you should be able to access the WordPress admin athttp://localhost/wp-admin
. - Visit the MyPhpAdmin at
http://localhost:8989
using theroot/root
orwp_db_user/wp_db_password
credentials, where you will see that thewp_db
schema has been created.
In this article I explored how you can initially setup your WordPress project with one single Docker Compose descriptor file. In my next article I will talk about how to manage environment-specific WordPress configurations, which is necessary as soon as you want to have a Continuous Delivery process in place.
I hope this article can be useful to you.