Skip to content

Dockerization Guidelines

Ben Burke edited this page Nov 23, 2021 · 1 revision

I aspire to the following guidelines when packaging things for this repo. With production and/or critical software, some additional steps like version-pinning and health checks are highly recommended.

NOTE! I am in the process of updating some of these guidelines.

  • Dockerfile instructions (e.g.; FROM, RUN, COPY, ENTRYPOINT) should be in UPPERCASE letters.

  • For the FROM instruction:

    • Use scratch if possible
    • If the software vendor has created an official image and it is well-designed and well-maintained, it can be used as a base
    • Otherwise use well-maintained OS distributions from the docker hub "library" (see also: docker hub "official" repos):
    • Avoid third-party base images as much as possible
  • Always include a maintainer label

  • Limit layers and layer sizes as much as possible with the general layer structure:

    1. OS-level package dependencies + cleanup (e.g. apk add or apt install)
    2. App-level package dependencies + cleanup (e.g., pip install or npm install). Try to add these via manifest files like requirements.txt or package.json to enable security scanning.
    3. App code (usually via COPY or curl) as near to the end of the file as possible
  • Fetch via verified TLS. Verify gpg signatures and checksums as much as possible.

  • Drop privileges when possible (with RUN adduser ... or equivalent then USER)

  • For RUN instructions:

    • Start long instructions with set -eux
    • Split complex commands across multiple lines using the continuation character \
    • Try to keep things sorted alphabetically unless a different order is significantly more intuitive
    • Generally use one command per line...
    • ...but split complex commands so they have one argument group per line
    • Things like package installs get one package per line, always indented one additional level, sorted alphabetically, ending with a sentinel like true or : or ; if the package install is the last thing in the run command.

    For example:

     RUN apk add --no-cache \
       git \
       make \
     ;
    

    Or:

     RUN set -eux; \
       pip install -r requirements.txt; \
       pip cache purge;
    

    Or:

     RUN set -eux; \
       apk add --no-cache \
         py3-pip \
         python3 \
       ; \
       pip3 install \
         pycodestyle \
       ;
    
  • For entrypoint scripts and other helpers: if you can't clearly and readably write it in POSIX-compliant shell script (#!/bin/sh) then use a real programming language instead. Do not use bash-isms. See shellhaters.org's helpful links, Bruce Barnett's POSIX Shell tutorial (part of "The Grymoire"), and Rich's POSIX shell tricks for useful POSIX shell help.

  • Lint and check everything (e.g., with tools like shellcheck, pylint, go lint, etc.)

  • Use build args to parameterize things like version numbers in package downloads. If you do so, include an adjacent comment with the URL a human and use to check for updates / release notes.

  • For contained services, follow the 12 factors

  • Don't embed secrets in images, don't put secrets in environment variables

Clone this wiki locally