I wanted to make some changes to the excellent Autonomie theme, but because I’m yet a WordPress development tyro I wanted an environment that I could break. At the same time I didn’t want to manually copy changes from local to the real remote env if those changes did turn out to work. There’s probably a better way of doing all this, but here’s what worked for me.
- Install Docker
- (optional) Edit your hosts file and make
local.hostpoint at127.0.0.1. This is maybe unnecessary, but browsers and various tools often have special treatment for “localhost” or 127.0.0.1, which has caused problems for me in the past. - Locally, create a root dev directory and subdirectories
db,wordpress, and whatever themes you want to work on (I usedautonomie-dev). You can skip the theme directory if your theme doesn’t require any special build steps. I git-cloned Autonomie. - Create a
docker-compose.yamlin the root directory. See below. - Run
docker compose up -d. This should get an empty WordPress installation started. docker compose downto stop it, so we could import the remote installation.- Copy over the remote wordpress directory into the local
wordpress/ overwriting any existing files. I usedrsync -av --delete remote:/path/to/wordpress/ wordpress/from root. - If you don’t want to import your remote content, skip this step. Otherwise:
docker compose up dbto start only MySQL- On the remote side run
mysqldumpand import locally viamysql -ppassword < dump.sql docker compose up phpmyadmin. Log in to http://localhost:8180 with the MySQL username + password. In the “options” table update two records to point tohttp://localhost:8080/(orhttp://local.host:8080/, if you updated the hosts file). The records aresiteurlandhomeunder theoption_namecolumn. This ensures that your local setup doesn’t redirect to your real remote domain.
docker compose up -d. You should be able to see your site onhttp://localhost:8080(orhttp://local.host:8080if you changed the hosts file). Now you can change the theme files as needed.
I also wanted to be able to version control the theme with Git and have it publish the local changes on the remote side when I push. For that I followed this tutorial with some tweaks:
- Set up a bare git repo outside the web root on your remote host with
git init --bare .- e.g. if your web root is
/var/www/html/wordpressrungit init --bare /var/www/html/your_theme
- e.g. if your web root is
- Create an empty theme directory. I used
autonomie-dv, so for me the location was/var/www/html/wordpress/wp-content/themes/autonomie-dv. Set this up in the local wordpress install too. - In the bare git repo, under
hookscreate a file calledpost-update. Make it executable withchmod ug+x post-update. Contents are below. Now whenever you push into this repository it’ll copy over the theme files into your actual remote installation. - Inside your local theme directory at the root level,
git init .and then add the bare repo as a git remote:git remote add origin your-ssh-host:/var/www/html/your_theme. - (optional) Specifically for Autonomie, I removed
_buildfrom.gitignorebecause I didn’t want to run the build step remotely. I wanted to build locally and then have the git hook just copy the files over. I may change my mind about this later. I also tweaked thegrunt cleanstep to not remove the_builddirectory, because that would break the Docker volume bind and require restarting the containers for every change to remount the recreated directory.- I tweaked the
watchtarget in Gruntfile.js to trigger on more file extensions, so I could rungrunt build watchand have it automatically rebuild on any local changes.
- I tweaked the
Now when you git push you should see rsync output that copies the files over.
docker-compose.yaml
services:
db:
restart: unless-stopped
image: mysql:8
command: '--mysql-native-password=ON --disable-log-bin --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci'
environment:
MYSQL_DATABASE: "wordpress"
MYSQL_ROOT_PASSWORD: "password"
MYSQL_USER: "wordpress"
MYSQL_PASSWORD: "password"
volumes:
- "./db:/var/lib/mysql"
phpmyadmin:
depends_on:
- db
image: phpmyadmin/phpmyadmin:latest
container_name: phpmyadmin
ports:
- 8180:80
environment:
PMA_HOST: db
MYSQL_ROOT_PASSWORD: "password"
wordpress:
depends_on:
- db
restart: unless-stopped
image: wordpress
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: "password"
# If you imported your DB and it uses a table prefix uncomment
# this and update as needed.
# WORDPRESS_TABLE_PREFIX: "wp_abc"
volumes:
- "./wordpress:/var/www/html"
# Uncomment the next line and update the paths for your theme.
# My local theme dir is autonomie-dev, but the theme name in
# WordPress is dv-autonomie. You could totally name them the
# same. Also note that I'm using _build/ because Autonomie
# requires a build step (using grunt) and that's where it
# outputs the results.
# - "./autonomie-dev/_build:/var/www/html/wp-content/themes/dv-autonomie:ro"
ports:
- "127.0.0.1:8080:80"
post-update
#!/bin/sh
# Check out the theme into a temporary directory and then
# copy it over via rsync into the actual WordPress theme location
export target="../wordpress/wp-content/themes/autonomie-dv"
export GIT_WORK_TREE="/tmp/autonomie-dv"
mkdir -p "$GIT_WORK_TREE"
git checkout -f
# This will overwrite the target location. If you're not sure that
# you got it right, add '-n' to do a dry-run. i.e.:
# rsync -avn --delete "${GIT_WORK_TREE}/_build/" "${target}/"
rsync -av --delete "${GIT_WORK_TREE}/_build/" "${target}/"