100 Days of Learning: Day 13 & 14 – Running WordPress locally using Docker and using highlight.js

Here is my Log book

Adding code syntax highlighting (to my blog)

We interrupt this broadcast (Lego database project) to first take a detour in adding code syntax highlighting to the blog.

One of the biggest reasons I started a blog is to document how I setup and develop things so that the "6 months from now" future me can have a recipe of how stuff works.

Fate, it seems, is not without a sense of irony – Morpheus

My blog runs on WordPress and I developed my own custom theme back in 2019. However I now find myself in a position where I have no clue how any of this stuff works and I really wish I did write that post about how it works back then.

I will spare you the details of how all this works and maybe one day I will write a post about it. The short summary is this:

  • Git repo for the theme. It uses npm, gulp and sass.
  • Git repo that manages a Docker setup that spawn Apache, PHP and WordPress in one container and MariaDB in another. This is used to run the blog locally on my machine while I develop themes or plugins etc.

Learning action point: I should write a backup script that backs up my blog to S3 and have a script that can restore from S3 to the local Docker blog.

At least I left myself some good instructions on how to setup and run most of this but it could have been better. I guess that is the problem with documentation in general. You really have to dog food it to see if you missed any steps etc. or even better is to get someone else to follow your recipe and see if it just clicks.

Running a local instance of WordPress (Apache, PHP) and MariaDB using Docker

I will share the docker-compose.yml file I use to spin up a WordPress instance. But please be aware that this is based of stuff I did in 2019 and right now I am just focussing on getting this working again so that I can make changes to my WordPress theme and test it before installing it on the live site.

EDIT: I modified my original compose file to be more in line with this tutorial.

NOTE: I only run this locally. I am sure there must be better ways to supply secrets than to have it in the docker compose file.

version: "3.9"
services:
    # Create a container for running a MySQL Database (access it from 127.0.0.1:8081)
    wordpress-db:
        # Official mariadb docker image
        image: mariadb
        ports:
            # Map local port 8081 to the MySQL docker's 3306
            - "8081:3306"
        restart: always
        volumes:
            - wordpress-db-data:/var/lib/mysql
        environment:
            MYSQL_ROOT_PASSWORD: INSERT_YOUR_PASSWORD_HERE
            MYSQL_DATABASE: wordpress
            MYSQL_USER: wordpress
            MYSQL_PASSWORD: wordpress        

    # Create a container for running WordPress (access it from 127.0.0.1:8080)
    wordpress:
        depends_on:
            - wordpress-db
        # Official WordPress docker image
        image: wordpress
        restart: always
        volumes:
            # Map local ./ directory as /var/www/html (so that the install persists)
            - ./wordpress:/var/www/html
        ports:
            # Map local 8080 to Apache port 80
            - "8080:80"
        links:
            - wordpress-db:mysql
        environment:
            WORDPRESS_DB_HOST: wordpress-db:3306
            WORDPRESS_DB_USER: wordpress
            WORDPRESS_DB_PASSWORD: wordpress
            WORDPRESS_DB_NAME: wordpress
volumes:
    wordpress-db-data: {}

Spin up the containers

$ docker-compose up -d
...
Creating wordpress-db_1 ... done
Creating wordpress_1    ... done

A new directory named "wordpress" will be created locally and you will start seeing wordpress files being created there.

To monitor the container logs

$ docker-compose logs -f
...
wordpress_1     | WordPress not found in /var/www/html - copying now...

Go grab a coffee and wait for the wordpress installation files to be created. Then $ open http://127.0.0.1:8080

To stop the containers

$ docker-compose stop

Where I have gone wrong in my use of Docker is that I need to learn to better backup and restore "things". In my example above, I am persisting the /var/www/html (where wordpress is installed) out to my local machine … but where I have failed (and only seeing it now) is that I never backed up the MariaDB database that goes with the WordPress setup!

EDIT: I came across Docker Volumes as a way to persist container data. The docker compose above ^^ reflects this change.

Learning action point: Backup and restore Docker volumes.

For more information on the Official WordPress Docker image

Profit!

I can now access the local running WordPress instance.

I can also access the MariaDB database on port 8081 from MySQLWorkbench.

Adding highlight.js for code syntax highlighting

I like to use Markdown for all of my own documentation as well as writing this blog. At the moment I write the blog posts in Notion and then export the Markdown before adding it to WordPress.

After inspecting the rendered html I noticed that the html produced is like the following.

<pre>
	<code class="language-python">
		# Some python code here
	</code>
</pre>

Turns out that highlight.js can easily apply syntax highlighting to these elements.

As I mentioned earlier, my theme uses Node.js, and gulp to monitor for changes to sass (css generation) and javascript files.

I ran into another issue with trying to get my local version of my blog / development setup working again (since 2019) and that is to do with gulp 3.x not working with newer node.js versions. Again another reason why I need to learn more about Docker and actually this whole blog system should be "frozen" into a container. See the last section of this post regarding the troubleshooting I went through.

<head>

I added the following to my header.php file to fetch highlight.js from Cloudflare CDN.

See this link for more options.

<head>
	...
	<!-- highlight.js -->
	<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.1/styles/default.min.css">
	<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.1/highlight.min.js"></script>
	<script>hljs.highlightAll();</script>
	...
</head>

Refreshed the browser and surprisingly this worked first time.

Next I need to setup a colour scheme that works with the blog theme. This is surprisingly very easy. Just go to the demo site and choose I theme you like. Note the name down (e.g. "Dracula") and then just replace the above link tag (e.g. …/styles/dracula.min.css). You can also use this to help in finding the correct link.

I liked Night-Owl but did not liked that it used italics for keywords, function names etc. So I ended up cloning and modifying it and placed it under the same sass system currently being used by my theme.

I just had to make one more modification to the background colour for <pre> tags to match that of Night Owl and I was ready to deploy the new theme to production.

Node, gulp and trouble

Below is some of the steps I had to follow to just get gulp from my theme working in 2021. I so wish I just containerized the system.

# Which node is currently installed
$ nvm list
->     v15.10.0
default -> node (-> v15.10.0)

# Which versions of node is available to download and install
$ nvm ls-remote

#-----------------

# Uninstall the global gulp
$ sudo npm uninstall -g gulp-cli

# Install 10.15.1 like it is 2019
$ nvm install 10.15.1
$ nvm use 10.15.1
Now using node v10.15.1 (npm v6.4.1)

# Reinstall global gulp
$ sudo npm install -g gulp-cli
$ gulp --version
CLI version: 2.3.0
Local version: Unknown

# cd to where the node project is
$ node install
internal/modules/cjs/loader.js:583
    throw err;
...

# To fix this issue
$ rm -rf node_modules
$ rm package-lock.json
$ npm install

# Next issue about not finding local gulp
$ npm install gulp
# Nope
# Try some more stuff
# Nope

$ npm install gulp@3.9.1 --save
$ gulp --version
CLI version: 2.3.0
Local version: 3.9.1

$ gulp watch
# It works! finally