Docking Manoeuvres

Necessity gives birth not only to invention, but can lead to updating and upgrading skills. This year, moving to developing on a machine too lightweight to run a virtual machine necessitated using Docker to create my local development environments, which I was only to happy to learn given its ubiquity.

Docker, for those who don’t know, provides a tool-set for packaging applications, or even whole application clusters, into deployable containers, including a standard set of dependencies and environments. Container technology represents an advance over virtual machines. In my use-case, containers have far less overhead than the virtual machine (VM) technology I used to use for local development. Instead of needing an entire VM, containers approach the problem more efficiently by leveraging the underlying system and resources.

Docker tends to be used a lot not just for development but for deployment. Since all that is necessary for the application to run is packaged in the container, this makes deploying applications across different host systems much less painful, and relatively hassle-free, at least in theory.

But there’s a big learning curve with Docker I feel. Representing as it does a slight paradigm shift in the way we develop and deploy, it requires a different mindset and adjustment to learn. Recently I switched machines again and decided to re-build everything I’d learned in docker this year from scratch, in relation to my main use case, which is simply running a local instance of the WordPress CMS, with which to develop custom themes and plugins. For this tool I use docker-compose, which I’ll get to later

Basic Docker

But first I thought I’d take a step down the docker rabbit hole and revise the very basics, since there were some things I thought I might have missed in my haste to get a local WP environment running.

Normally in this situation I search the web for beginner tutorials and courses, and use my critical judgement to choose the best one for me. I ended up looking at two principle resources to get me up to speed with the very basics of Docker.

Docker in 2 hours

This video from provides a useful introduction, that helped me get to grips with some essential commands.

The course is somewhat hands on, with tasks and quizzes included via the interactive DevOps learning platform KodeKloud, “the True Learn-By-Doing platform!”. Great if you want that but not quite what I was looking for. I didn’t want the friction of signing up to a website to complete the course, but it’s quite possible to work through the examples in the course locally. The course introduces understanding such essential topics within docker as port mapping, data persistence using volume mapping, environment variables, before moving on to creating an image, including managing commands, networking and storage. The course also includes lectures on docker-compose (a way of configuring multiple containers at once), online cloud-based repositories of docker images (docker registry), a deeper look at the docker engine itself, and running docker orchestrations in production. The course consists of discrete lectures that can be worked through at the learner’s own pace.

Docker for beginners

The other resource I looked at, “docker for beginners“, makes a good stab at being “the one-stop shop for getting your hands dirty with Docker”, aiming to demystify the software and guide the learner through “hands-on experience with building and deploying” applications running in docker.

I found this resource, produced by Prakhar Srivastav, a software engineer working on development tools for google, more suitable for my needs – a straightforward linear path through Docker basics, using its own dedicated git repository (hosted on github).

Ptakhar begins with walking us through the basics of pulling a docker image and running it, but without the fine detail and useful commands given to us by freecodecamp’s video course. Referring to and switching between the two thus gave me a well-triangulated view of the software.

Prakhar continues with “baby steps” – pulling an image of a simple static html site that uses nginx as a dependency demonstrates how docker can provision a simple webserver for us.

Next Prakhar provides a slightly more complex application – a standalone Flask webapp, randomly displaying cat gifs, for us to wrap up in a docker container, to teach us how to make our own docker images from our apps. At this point in the tutorial however, I ran into a problem. Using the provided Dockerfile, it was easy to build the image. However when attempting to run the container, the code threw an error:

Traceback (most recent call last):
File "/usr/src/app/./", line 1, in
from flask import Flask, render_template
File "/usr/local/lib/python3.10/site-packages/flask/", line 21, in
from .app import Flask, Request, Response
File "/usr/local/lib/python3.10/site-packages/flask/", line 34, in
from .sessions import SecureCookieSessionInterface
File "/usr/local/lib/python3.10/site-packages/flask/", line 14, in
from collections import MutableMapping
ImportError: cannot import name 'MutableMapping' from 'collections' (/usr/local/lib/python3.10/collections/

I like following slightly outdated tutorials, since when encountering a bug relating to the ever-changing rules of various dependencies, it’s satisfying to track down the issue and fix it. It’s a good way to learn the problem-solving skills needed. In this case, here’s the Dockerfile provided:

FROM python:3

# set a directory for the app
WORKDIR /usr/src/app

# copy all the files to the container
COPY . .

# install dependencies
RUN pip install --no-cache-dir -r requirements.txt

# define the port number the container should expose

# run the command
CMD ["python", "./"]

Note the only line without a comment, the first, the FROM command, which instructs Docker to initialise a “new build stage and sets the Base Image for subsequent instructions” [docs]. As is well known, if a tag is not added to specify a version, docker will assume you want the latest version of the image. In this case, pulling the python:3 image pulls the latest version, 3.10.

My approach was to search the web for the last line of the error:

ImportError: cannot import name 'MutableMapping' from 'collections' (/usr/local/lib/python3.10/collections/

Which led me to a note on Stackoverflow that importing from collections has been deprecated in python since 3.3, and stops working in 3.10

I simply tried a solution that worked: altering the FROM command in the Dockerfile to specify python:3.9 (the latest version before the breaking change) instead fixes the problem, and indeed is the proposed solution to the bug on the docker-curriculum github repository. At the end of the thread though, a user proposes a different solution: the example app provided, built in the Python framework Flask, specifies using Flask v1.0; the github user JohnFowlerDXC suggests simply updating this to specify the latest version of Flask, which of course takes account of the breaking change to Python, and then Docker can continue assuming the latest version of Python. This strikes me as a much better solution since it updates Flask as well as ensure the app always uses the latest version of Python. Sure, further similar updates might need to take place down the line, in case of any further changes in Python that might require an update to Flask, so some might argue it’s better to fix a version that works, and indeed this would be leveraging one of Docker’s advantages, which is precisely this ability to specify precisely versioned and provisioned stable environments. However, in this case, updating Flask and paying the cost of keeping it updated seems to me preferable, just in order to keep up with the latest software.

So I completed the tutorial with this version of the sample code, continuing to use the latest version of python as per the author’s intentions, but updating the internal Python app to use the latest version of Flask. It all worked as expected.

Next time, I’ll walk through how I use docker and docker-compose daily to run containerised WordPress environments on my local machine.

Until then, this git repository contains a long list of docker resources to get your teeth into:

WordPress Plugin Review: Your Channel

Everything you want in a YouTube plugin?

A client of mine, a renaissance man, felt it was about time his ideas had an audience, and so requested a website to self-publish his writings, as well as setting up a YouTube channel. We wanted a way for the website to promote the channel, not just by providing a link but with a dedicated space on the site to embed his YouTube videos as they are released.

I thought a WordPress plugin the obvious solution, and so I set about researching those that met this use case. After a false start, I decided on Your Channel, a freemium plug-in by Plugin Builders. The previous plugin I tried, whose name escapes me now, was only able to show videos in a playlist trapped inside a single embedded iframe. I wanted something to show each video, ideally in a grid layout, and with Your Channel I found just what I was looking for.

Your Channel – the pros

I like a plugin that plays well with my theme, and doesn’t add any annoying styling that needs overriding, leading to code bloat. This plugin seems to fulfil that need, and I haven’t needed to add any styling at all to the video grid. It’s well presented with a cool player, and applies sensible responsive design principles. The grid layout is an option, as is the style of the player – inline or lightbox. The inline player option seems to me perfectly good. You can see the results over at my client’s video page:

Videos at

Your Channel – the cons

Perfection of course is elusive. The plugin is as I mentioned freemium, by which a number of useful and ‘nice to have’ but not essential features are available in the ‘pro’ version of the plugin, such as a slider and carousel theme and the ability to specify the start times of videos (although both these examples could in theory be added by a site developer if needed).

On the WordPress Dashboard, the plugin menu is well placed as an extra item in the Settings menu. The setting interface for the plugin could be improved in my view: some of the wording could be clearer, and until you hover and click over a section heading in the instructions, it’s not obvious they are collapsible accordion sections. Adding an open/close icon to each section would help make operating the plugin a smoother experience.

More worringly, at the time of writing, the plugin was last updated one month ago, has not been tested with the very latest versions of WordPress, and currently presents a bug leading to error warnings on the plugin’s setting page. Hopefully these issues will be fixed in the near future.

Conclusion and alternatives

Other than that I would recommend this plugin for the use case. Other similar plugins are available, and the good people at WPBeginner have curated their pick of these.

Disclaimer: this post is not paid or promoted by the makers of the Your Channel plugin.

the annotated notepad

I feel I just learned a lot about using git from this great little talk.

Meanwhile, I was impressed by this excellent approach to teaching git by MIT. Explaining git’s underlying data model first, and then looking at the commands, the lecturer walks through what basic git commands are doing at a lower level. A really useful and concise way of teaching how to use a tool while fostering an understanding of the how and why it works, demystifying the software.

Private Posts in WordPress

In WordPress, posts can be set to Public, Private or Password Protected, in the Document menu. Password Protected is out of scope for this article; it’s not a feature I’ve used much. I do however often make Private posts, useful for keeping educational notes and information, for example.

By default, Private posts have a front-end view of the post only logged-in users can see, the post title prefixed with ‘Private:’ . Other than that, the post behaves normally, appearing in the main posts query, and in archives, nestled amongst public posts in whatever order your theme specifies.

Can this feature be improved? In my case, I would prefer not to have my private posts displayed in this way: I’d much rather have my Private posts in their own archive, their own view for users authorised to see them, separate from the public blog. Imagined this way, anyone wanting to keep a private journal alongside their public blog might find this a preferable arrangement.

Sounds like a perfect idea for a custom plugin.

Private Posts Keep

Modifying Private Posts in a custom plugin

I broke down my plugin design with three goals in mind:

  • removing private posts from the main posts view and archives
  • creating a new archive-style view exclusively for private posts
  • creating a Private Posts Widget, for an alternative view and easy front-end access.

I decided to call the plugin Private Posts Keep. In giving Private posts their own area, I was reminded of keep within a castle, hence the perhaps obscure name based on this metaphor. The most straightforward title, to be honest, might be ‘Segregate Private Posts’ since that’s a clear and accurate description of both the intent, and the effect, of the plugin. Hmm, maybe a compromise title would be ‘Private Posts Sanctum’?

Enough of what to call it; let’s get to work making it function. First, let’s make a start on our first two goals, by creating two classes.

Inside our main class, class-pp-keep.php, we’ll create a few functions:

public function rem_pp( $query ) {
  if( current_user_can( 'read_private_posts' ) ){
  /*affects main query on posts page or archives.			 
    if ( $query->is_main_query() &&  $query->is_home() || $query->is_archive() ) {
      $query->set( 'post_status', 'publish' );

That takes care of modifying the main query on the posts page or an archive page. However, we’ll find on single post views our navigation links to the next and previous posts won’t reflect this change of emphasis. Let’s fix this with another function to filter these navigation links:

public function get_adjacent_post_mod($where){
  if (is_single()){
    global $wpdb, $post;
    if ( get_post_status ( ) == 'private' ) {
      $where = str_replace( "AND ( p.post_status = 'publish' OR p.post_status = 'private' )", "AND p.post_status = 'private'", $where );
      return $where;	
    } else {
      $where = str_replace( "AND ( p.post_status = 'publish' OR p.post_status = 'private' )", "AND p.post_status = 'publish'", $where );
      return $where;	

And we need somewhere to display those now missing Private posts. It’s possible to programmatically insert posts in the database, so that’s what we’ll do. The function first checks a Page with our desired title doesn’t exist, and if not creates it, set to Private, and fills it with the specified content, including a shortcode, for outputting a list of Private posts. we’ll define elsewhere in the plugin.

public function create(){
			$post = '';
			if( get_page_by_title('Private Archive') == NULL )
			// Create post object
			$post = array(
			  'post_title'    => 'Private Archive',
			  'post_status'   => 'private',
			  'post_type'     => 'page',
			  'post_content'   => 'This page is intended for your private posts.

			// Insert the post into the database
			$insert_post = wp_insert_post( $post, true);//now you can use $post_id within add_post_meta or update_post_meta	
			return $insert_post;	

The shortcode is defined in a function in a separate file. Finally we add our functions to the appropriate WordPress hooks, in our constructor function for the class, like so:

add_action( 'pre_get_posts', array(&$this, 'rem_pp'));
add_action( 'wp_loaded', array(&$this, 'create'));
add_filter( 'get_next_post_where', array(&$this, 'get_adjacent_post_mod'));
add_filter( 'get_previous_post_where', array(&$this, 'get_adjacent_post_mod'));

Our rem_pp() function is added to the pre_get_posts action hook. Note we need to add our navigation links filter to two separate hooks, get_next_post_where & get_previous_post_where

Our widget is created in a separate class, class-pp-keep-widget.php.

In our main plugin file, pp-keep.php, which runs the plugin, we’ll tie all this together:

Plugin Name: Private Posts Keep
Description: Segregates Private Posts
License: GPL2
/* exit if directly accessed */
defined( 'ABSPATH' ) || exit;
define( 'PPKEEP_PATH', plugin_dir_path( __FILE__ ) );

require_once( __DIR__ . '/pp-keep-shortcode.php' );
require_once( __DIR__ . '/class-pp-keep.php' );
require_once( __DIR__ . '/class-pp-keep-widget.php' );
if( class_exists( 'PP_Keep' ) ) {
	$PPKeep = new PP_Keep();// instantiate the plugin class

if ( class_exists( 'PP_Keep_Widget' ) ) {
	// Register and load the widget
	function pp_load_widget() {
		register_widget( 'PP_Keep_Widget' );
	add_action( 'widgets_init', 'pp_load_widget' );

 * Activate the plugin
function ppkeep_activate()
	// Do nothing
} // END public static function activate
 * Deactivate the plugin
function ppkeep_deactivate()
	$page = get_page_by_title('Private Archive');
	if (isset($page)){
		$page_id= $page->ID;
	wp_delete_post($page_id, true);
} // END public static function deactivate

function ppkeep_uninstall () {
	if ( ! current_user_can( 'activate_plugins' ) )
} // END public static function uninstall
register_activation_hook(__FILE__, 'ppkeep_activate');
register_deactivation_hook(__FILE__, 'ppkeep_deactivate');
register_uninstall_hook(__FILE__, 'ppkeep_uninstall');

The file runs a basic security check, defined( 'ABSPATH' ) || exit; and loads up our shortcode and classes . The activation, deactivation, and uninstall hooks are features available to plugin authors so code can be triggered when the user performs these actions. Here they are standard, except for the deactivate hook, which I’ve set to delete the private Page the plugin creates.

Try it out for yourself

The plugin works and the full plugin source code is freely available on my github. To install in your WordPress site, you’ll have to download the .zip archive:

Then go to your WordPress Admin>Plugins, and hit ‘Add New’ then ‘Upload Plugin’. Uploading the .zip file will install the plugin for you to activate.

After activation, you will find private posts are now gone from your main posts page and archives, but are listed on a Private Posts Archive page the plugin has created for you, which should show up on your Dashboard under ‘Pages’. You can edit this page as normal, but ensure it keeps the shortcode which outputs a simple list of Private Posts by title, with their permalinks. Alternatively you can add the shortcode anywhere you like.

You will find a Widget available which you can add to your sidebar. The widget will only show up for users authorised to read private posts, and displays a short list of the latest, along with a link to the Private Posts Archive page the plugin creates.

How can the plugin be improved?

The code which delete the Archive page on deactivation, and the link to the page in the widget, use the title and url of the page to function. This depends on the user neither changing the title nor deleting the page, which cannot be guaranteed (see github issue for more details).

Moreover, there aren’t many options available to the user. The widget has no options other than the widget title, and there are no options to modify how the Archive page displays the private posts.

Finally, I have a suspicion the plugin wouldn’t be accepted into the Plugin directory without a good code review and some refactoring. The code works, and does what it says on the tin, but it isn’t necessarily elegantly written and designed.

I wrote it back during the turn of 2015/16, but life rather got in the way of me developing it further. Nevertheless it’s a useful plugin that adds value to the native private posts feature of WordPress, and well worth revisiting.

You can follow along with development of the plugin, or even help out yourself, at the following url:

PHP basics

As a kinesthetic learner, my preference when taking a course in code is to build what I’m shown, but tweak, improve, build on and document what I learn as I go along.

Returning to professional web development after a long break, I needed a refresher course in php, so I took a look at the php basics video series from codecourse:

With a series like this, where examples have a minimal front end, I like to build a suitable front-end as I go, shaping it to the needs of the project. To me this is an ideal way to build a site, but isn’t always possible in a client project. Personal projects are ideal for this kind of discipline, and it’s amazing what can come out of it.

Continue reading PHP basics

Uploading with html5/php

Resources on handling file uploads.

Front end



Hillary Clinton’s old website

On Sunday, Hillary Rodham Clinton announced she would definitely like to be the next President of the United States of America. Before that announcement looked like this: a holding page linking to the website of her official office. on 27th March 2015, retrieved from on 27th March 2015, retrieved from

Blue, a notoriously popular colour in web design, seems deployed here according to colour theory:always reassuringly safe, friendly and almost frivolous when light, while the darker blue brings a more serious tone. The background gradient gives an abstract sense of a horizon; the ground and the sky; don’t stop thinking about tomorrow. We’re meant to be reassured. The contrasting darker blue used for the ‘Hillary’ headline – really a logo – fits it quite well: we’re on first name terms with Mrs Clinton, but we’re still encouraged to take her name seriously as a strong and powerful proposition. The colour contrast emphasises the seriousness of ‘Hillary’ as a concept. We’re meant to be impressed.
The gradient is deployed as a background image rather than modern css: old-fashioned but fine for a lightweight single page site. There’s a technical fail, however, whereby the bottom curve of the ‘y’ descender in the logo (also deployed as an image) has been truncated by over-zealous cropping. This could have been avoided with modern web typography – or a steadier hand.

But never mind because the typography itself is interesting. Continue reading Hillary Clinton’s old website