Working around Docker's COPY command copying as root using GNU M4

I’ve been working with Docker a lot recently, and have been switching to non-root users within the Dockerfile using the USER instruction (not for security reasons, but in order to test software not as root). As a result, I’ve been suffering a little from this issue - essentially, files copied into a Docker image using ADD or COPY are copied with the owner as root, irrespective of the ownership outside the Docker image. According to this comment, this behaviour in Dockerfiles won’t change, at least in the near future.

Irrespective of the merits of this, I needed a solution. There is an (inelegant) way to work around this, which is to switch to root, copy the file in, change its ownership, and switch back to a regular user. I could do this directly inside the Dockerfile, but this requires a lot of extra boilerplate code bulking out the Dockerfile.

As a result, I turned to an ancient templating technology to make my Dockerfile more manageable - m4. I’ve created an m4 macro file which can be included in a Dockerfile. The full version (called docker-copy-as-user) is on github, but a small flavour is:

`USER root
COPY $1 $2
RUN chown testuser $2/$1

A file that contains this macro can be included in a Dockerfile (which I now like to call Dockerfile.m4) with the incantation include(`docker-copy-as-user'). This can then be used by including the ‘meta-instruction’ COPYASUSER filename target/dir user-to-own-it. For example, Dockerfile.m4 might look like:

FROM ubuntu:15.04

RUN useradd -ms /bin/bash testuser
USER testuser
WORKDIR /home/testuser

COPYASUSER /tmp testuser
RUN unzip

This can then be pre-processed before you run docker build with:

m4 -I directory/where/docker-copy-as-user/is Dockerfile.m4 > Dockerfile

Note: I am very much a newbie to both Docker and m4. Please don’t read the above as being the optimal answer. In particular, your final (processed) Dockerfile still ends up pretty bulky, so this will still have performance implications due to the number of layers. I’d be glad to hear any suggested improvements.

Getting the Logitech Presenter R800 Working with QuickTime Player on the Mac

Based on my previous post about getting my Logitech R800 presenting tool working with Keynote using Karabiner, I’ve now spent some time extending my private.xml to add support for QuickTime Player also. It now supports (inside QuickTime Player):

  • Left: Rewind the video at various speeds.
  • Right: Fast-forward the video at various speeds.
  • “Start presentation”: Go into fullscreen.
  • “Blank presentation”: Pause/play presentation.

This is very useful when giving a “live” demo from a QuickTime video, as you can pause/play/rewind etc. all from the presenter tool.

How I Used Basic Debian Packaging with Git

I was recently looking for a way to support building a basic Debian package for email2pdf - a fairly simple Python program I maintain. In particular, I wanted to:

  • Keep the Debian build process simple - its packaging has always been a bit of a mystery to me.

  • Ensure that the git revision was in some way reflected in the Debian version number in a mostly monotonic way, which solely the git revision would not, since it’s merely a SHA1 hash.

The first bit turned out to be easier than I thought, since it turns out all you really need for a basic Debian package is a control file that looks a bit like this (for the moment, this assumes a version number hardcoded in this file):

Package: my_package_name
Version: 1.0.0
Section: base
Priority: optional
Architecture: all
Depends: some, other, debian-packages
Recommends: yet-another-package
Maintainer: Andrew Ferrier <>
Description: Some short description
 A much longer description that goes on for ages and ages and ages.

Once you have that, you put it in a directory tree called DEBIAN/, together with any files you want to put in the package, and run dpkg-deb --build at the root of it. For example:

mkdir -p DEBIAN/
mkdir -p DEBIAN/usr/bin
cp control/file/above DEBIAN/control
cp some/other/location/myprogram DEBIAN/usr/bin
dpkg-deb --build . .

(You can see a fuller example here in the builddeb_real target here).

However, the second part - to determine an appropriate version string for the Debian package - was fiddlier. Eventually, I settled on a similar technique to the one described here.

However, rather than git describe --tags --long, as recommended in the answer, I instead use git describe --dirty. This has the following advantages:

  • It ensures that if a Debian package is produced during development, when the git tree might be dirty, that -dirty is appended to the package version to distinguish it from a non-dirty one.

  • Not using --tags means that lightweight (non-annotated tags) are not used, which means we can use lightweight tags for miscellaneous purposes, and use annotated tags only for “released” versions of the software. In general, I only push annotated tags up to repositories (this then integrates nicely with GitHub’s “Releases” concept).

  • Not using --long means that ‘released’ versions (where the current commit exactly matches an annotated tag) have a clean and well-defined version string, like ‘0.9’. Commits that don’t have an associated annotated tag have a commit string like ‘0.9-12-gf385006’, so the second number (‘12’ in this case) is the number of commits since ‘0.9’, and hence monotonically increases. The short commit ID (‘gf385006’) makes it easier to locate the exact version from the Debian package in git.

Once we have a way to determine the version string (git describe --dirty), now we need a way to get this into the Debian package control file. This can be done with a simple sed script:

sed 's/Version: .*/Version: $(GITDESCRIBE)/' debian/DEBIAN/control_template > debian/DEBIAN/control

control_template is basically a template-ized version of control, where the Version field contains a placeholder (see the real version from email2pdf as an example).

Once the above sed command has been executed, the dpkg-deb --build command can be executed as above.

Blog Refresh

Recently I relaunched this blog on This was for several reasons:

  • I wanted to get away from Wordpress. I’d been beholden to it as a tool for a little too long, and it’s become somewhat heavyweight, and was also exposing to a lot of spam. By removing a database backend and the ability to add comments, this should go.

  • I wanted to give a refreshed look and feel. I’ve redesigned everything from scratch using Bootstrap. The look and feel is still a work in progress, but I now get the chance to play with everything from scratch rather than worry about Wordpress themes.

  • I wanted to experiment with using Jekyll, especially as part of a Grunt pipeline. This allows me to use Markdown for editing posts, and lots of other cool features, as well as track my website content through Git.

  • I wanted to chance to energise myself and get myself writing again!

If anyone notices any issues with the new blog, please do let me know.

email2pdf - "Automatic" Conversion of Emails to PDFs

Like many folks, I am increasingly trying to go paperless, and am basing this strategy around the PDF format. I already have some good workflows set up with my network scanner to scan documents to PDF, which get automatically transferred to the desktop of my Mac for myself to file using rsync.

However, I also get a lot of emails which I’d like to capture in PDF format. Currently, for each one, I have to go into my email program, and ‘print them out’ using a PDF printer. It’s not too difficult, but it can still be a hassle when there are several to process.

What I’ve done, therefore, is begun to build a different workflow, centred around a separate email address I’ve set up on my domain. The idea is that I forward emails there that I wished to PDF-ized, and they are periodically retrieved by getmail (which I have running from a cronjob on an Ubuntu machine I have). I’ve then written another utility, which I am calling email2pdf, which acts as an MDA to “deliver” the mail into PDF format.

So far it can process basic text and HTML email (the latter using wkhtmltopdf), or can retrieve a single individual PDF document that’s attached. I’ve got a list of enhancements and other issues that I’d love to work on when I have time.

You are welcome to use or modify email2pdf (it’s MIT-licensed); I would welcome any pull requests for improvement.

subscribe via RSS