Dockerfile static vs build time vs runtime contexts

Well we’ve been using Docker quite a bit in production and it has been a learning experience for sure. A good one in that you start with a simple Dockerfile which looks a lot like a shell script and then realize how powerful the ideas are. The main confusion is this separation between what should go into a particular image and why. Here’s a quick set of tips:

  1. Static means the stuff that really never changes. The most common thing here is a list of packages that need to be installed. These are not user specific nor are they installation specific. Sometimes you can just apt-get them and sometimes you have to download and install. The way you know you are in this world is that you really can just run as the default root and you either installing packages or building and then deleting the source.
  2. Build time. This is the tricky one. If you look at most Dockerfiles, they intermix things that are really about packages and infrastructure and then things that need to be done to have a given image run in a given configuration. So for instance if you are building something and you want that server to connect to a test server, this is the perfect place to use ARG and --build-arg for instance. This also makes automated build really easy because an automated builder will have different configurations for this (like PROXY=loopback) for instance than a production image or a debug image. The most interesting case is using Docker CI where you put a Dockerfile at the root of your git repo. Then you want to be able to
  3. Runtime configuration. For instance you want the user context to be a specific person so that you can use if for development, so you want a specific volume to be at a specific place. Or you want the UIDs and GIDs to be correct so that you can mount an external volume. These are best handled as shell variables that you pass into docker run. For instance, “docker run -it tong/text -v /home/rich:/home/rich PATH+=/home/rich/bin bash` means that you will run the image richt/test and then bind in my home directory for fast work and set the PATH correctly just for that image. It means that you if you have multiple workspaces, you can fix them up at run time.