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.host
point 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.yaml
in the root directory. See below. - Run
docker compose up -d
. This should get an empty WordPress installation started. docker compose down
to 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 db
to start only MySQL- On the remote side run
mysqldump
and 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 aresiteurl
andhome
under theoption_name
column. 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:8080
if 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/wordpress
rungit 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
hooks
create 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
_build
from.gitignore
because 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 clean
step to not remove the_build
directory, because that would break the Docker volume bind and require restarting the containers for every change to remount the recreated directory.- I tweaked the
watch
target in Gruntfile.js to trigger on more file extensions, so I could rungrunt build watch
and 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}/"