As you may have noticed if we’ve been connected for a while, I’ve finally gotten back around to getting my long-neglected personal site up and running and modernized. It’s been long overdue.
While I did briefly consider other blogging and CMS platforms, in the end, I’m most familiar with WordPress so I decided with limited time to go with something I’m already familiar with.
Unit Testing/Sandboxing WordPress
That said, I definitely wanted a WordPress unit test/sandbox environment to play around with and get up to speed on the latest in the world of WordPress and test before actually applying changes to this site. It’s not difficult to have WordPress go wonky by applying too many or conflicting plugins and then try and back everything out. While plugins will still be persisted using this approach, it’s still a lot easier to spin up a new WordPress instance using containers than to try and de-foobar my main site on any foobar decisions made.
There have been a lot of advances in technology in the last 5 years and instead of building a test VM, the natural choice was to use Docker containers for this. I’m majorly happy with this direction as a WordPress sandbox environment. But it turns out, getting what I wanted up and running on Apple Silicon took some working out. So I thought I’d publicize my internal Engineering Notebook on this one in case it helps anyone else.
What I Wanted
What I wanted was a traditional WordPress environment, but in a Docker configuration. As a packaged configuration, I needed:
- The latest version of WordPress
- A relatively recent version of MySQL for the DB backend
- Adminer for simple web-based MySQL Administration
I found a few really helpful articles that got me going in the right direction, but again, running MacOS on an M1 as my sandbox posed a few issues I had to overcome. There’s a myriad of articles on running WordPress on Docker; I’ll let you find those on your own.
This article is focused on helping you get over the hurdle of getting to a working state on Apple Silicon.
Articles I Used
Here are the articles I used:
- How to install WordPress on Docker (Windows, MacOS, and Linux)
- How to Quickly Deploy WorkPress as a Docker Container
- Setting Up a MySQL Database in Docker
I also referred to the official Docker Containers documentation for WordPress and MySQL, the latter because my main issue was getting a working MySQL version or a variant to work on my machine (using the ARM architecture and arm64
tag):
Data Persistence
One of the biggest issues to consider when building a container is data persistence. Persistence inside the container will be lost if the container is stopped and a new container is started from the original image without a commit. If memory serves (I could be wrong), persistence of the WordPress components and the MySQL components weren’t always taken into consideration in those articles.
Rooting myself in a relative path we’ll call ./docker/wordpress
, I created the following directories:
chris@Zion WordPress % mkdir media mysql wordpress chris@Zion WordPress % ls -lF drwxr-xr-x@ 49 chris staff 1568 May 18 13:38 media/ drwxr-xr-x@ 21 chris staff 672 Apr 21 12:52 mysql/ drwxr-xr-x@ 25 chris staff 800 May 16 21:37 wordpress/
Now I have places to root any volumes to my Docker container for WordPress and MySQL persistence. media
is simply a place to store any downloaded or created media as in the past I’ve found once I’ve grabbed a media artifact like an image, it’s nice to have it around. And most especially since I’m sandboxing, if I grab a media artifact, test, and then want to run this into production (here on this site), I need the original media artifact (since “push to production” for such a tiny operation) is a copy/paste operation. (This is not bound to any volume on the container — it’s merely for my convenience and for “development” in the same directory root.)
Final Solution for Apple Silicon using Docker Compose
From here, I’ll just cut to the final solution since there are, again, a myriad of articles explaining the basics of Docker. The articles I’ve referenced above do a good job of this. I used Docker Compose as the final solution since Docker Compose provides the most efficient, economical way of encapsulating the entire Docker environment I want to run as a single package concept or single action.
The only thing I’ll add is… make sure you’re running the Docker engine on your Mac so all of this works. For instructions for installing Docker on MacOS Apple Silicon… click here. Make sure of course that you select the proper version:
The overall issue I was having was finding a true MySQL version from the official Docker Hub that would run and be supported on Apple Silicon, which is based on the ARM architecture. While some versions of MySQL had ARM versions, I couldn’t really get any to run for various reasons.
The solution? I switched to MariaDB as a MySQL substitute using an arm64
tag which seemed to work fine right out of the gate. Problem solved.
I renamed my mysql
directory to maria
, then used this Docker Compose YAML file (created in my docker rooted directory as above) to get it all running. Yes, I used straight-out default port 80 for my sandbox. Of course, adjust your YAML file appropriately to run on any off ports. (Bear in mind, some of the configuration files in the internal image for the software you are running may also need to be adjusted, depending on how you map ports. I would leave ports as default inside the container and map ports externally. Example: "9080:80"
, meaning expose as port 9080
but map to port 80
in the container.)
version: "3" services: adminer: image: adminer ports: - "8080:8080" mariadb: image: mariadb restart: always ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: <root db password goes here> MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: <wordpress db user password goes here> volumes: - ./maria:/var/lib/mysql wordpress: depends_on: - mariadb image: wordpress restart: always ports: - "80:80" environment: WORDPRESS_DB_HOST: mariadb WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: <wordpress db user password goes here> WORDPRESS_DB_NAME: wordpress volumes: - ./wordpress:/var/www/html volumes: mysql:
From here, it’s a simple docker-compose up
command in a Terminal window (docker-compose up -d
if you want to run detached — I run in a Terminal screen
session and like seeing the logs at times for again, sandboxing).
Here’s my final solution from a rooted directory standpoint and from where I can now launch the WordPress Docker container:
chris@Zion WordPress % ls -lF -rw-r--r--@ 1 chris staff 739 Apr 14 03:34 docker-compose.yaml drwxr-xr-x@ 16 chris staff 512 May 6 23:00 maria/ drwxr-xr-x@ 51 chris staff 1632 May 19 12:03 media/ drwxr-xr-x@ 25 chris staff 800 May 16 21:37 wordpress/ chris@Zion WordPress % docker-compose up -d
This is working well for me and is fully supporting the underlying ARM requirements for running on Apple Silicon.
Hope this helps! It’s a beautiful Spring day here in the Twin Cities, MN USA.
Update 2/18/2024
It’s probably worth pointing out that the port designations in the docker-compose
file above expose those ports “publicly” in some way. If you’re just running this on your desktop/laptop — probably not a big deal (but again could be, depending on your local or current network — airport WiFi, company LAN/VPN, etc.)
Refer to the Docker documentation on Networking to understand how to restrict exposing ports. MySQL and WordPress will need to be on the same network, which could be (should be?) running on a local, internal Docker network. There are at least a couple ways to do this. Again, refer to the Docker documentation on Networking for this.