Using docker to replace all command line programs

‹ Wesley's Software Philosophy v1 | Running awscli inside of Docker ›

Sometimes you want to run the same version of a command line program across many operating systems. Maybe your development environment is in Mac OSX and your CI system or production environment is Ubuntu. In these cases you can use Docker to package the command line program into a container which will then be consistent everywhere.

docker run has a volume mount command line option that lets you do this. For example this command will create a file called myfile in the current directory, however the resulting file is owned by root, which is not ideal.

docker run --rm -v "`pwd`:/work" ubuntu:16.04 touch /work/myfile

You can switch user IDs by passing the -u command line option to docker run like this, but certain programs like your shell will complain because the user id and group id do not exist in /etc/passwd and /etc/groups

GOOD:

% docker run --rm -u "`id -u`:`id -g`" -v "`pwd`:/work" ubuntu:16.04 touch /work/myfile

NOT SO GOOD:

% docker run --rm -i -t -u "`id -u`:`id -g`" -v "`pwd`:/work" ubuntu:16.04 bash -l
groups: cannot find name for group ID 1000
I have no name!@bb73f1bfa0ff:/$

One way to work around this is to create an entrypoint script inside your container which:

  1. Creates a user and group inside the container matching your user and group outside the container
  2. Runs your command with the given user and group

An example Dockerfile for Ubuntu 16.04 with just such an entrypoint script is available at github.com/wtanaka/docker-xenial-uid and is hosted at Docker Hub at wtanaka/xenial-uid.

A similar file for Alpine Linux 3.7 can be found at github.com/wtanaka/docker-alpine-37-uid and wtanaka/alpine-37-uid.

(Update March 31, 2018) This technique is being used with:

Subscribe to All Posts - Wesley Tanaka