Comprehensive Dockerfile Reference & Advanced Mechanics

Published on


Dockerfile Advanced Deep Dive

1. Meta-Configuration (The “Brain Upgrade”)

Dockerfiles have a hidden mode at the very top (Line 1). These are Parser Directives, not comments.

The Syntax Directive

# syntax=docker/dockerfile:1

This acts like a software update for the Docker builder.

Benefits:

  • Unlocks modern Dockerfile features.
  • Allows usage of new syntax even on older Docker versions.
  • Required to use BuildKit optimizations and Here-Docs.

2. Variable Mastery: ARG vs ENV (Ghosts vs Zombies)

Mixing ARG and ENV is a classic way to create weird, fragile builds.

FeatureNicknameLifetimeScopeBest For
ARGGhost 👻Build-time onlyLayer-specificVersions, build flags
ENVZombie 🧟RuntimeWhole containerApp config, ports, URLs

Pro Tip 1: The “Spare Tire” Default Syntax

ENV PORT=${BUILD_PORT:-8080}

If BUILD_PORT is undefined, Docker automatically uses 8080.


Pro Tip 2: The ARG Scoping Trap

ARG before FROM is visible to FROM, but not to later build steps unless you re-declare it.

ARG VERSION=latest
FROM alpine:$VERSION

ARG VERSION
RUN echo $VERSION

If you forget the second ARG VERSION, RUN echo $VERSION prints nothing.


3. Advanced File Operations

Rule: Default to COPY. Only use ADD when you explicitly need its “superpowers”.

ADD vs COPY

CommandSuperpowers
COPYSimple, explicit, predictable caching
ADDRemote URL download + auto-extract tar/zip archives

The “Here-Doc” (Inline File Creation)

Write config files directly in the Dockerfile:

COPY <<EOF /app/config.txt
User=Admin
Mode=Production
EOF

No separate config file needed in the build context.


4. BuildKit Optimization: Cache Mounts

The Problem

By default, Docker forgets everything between builds and re-downloads package indexes every time:

  • apk
  • apt
  • pip etc.

The Solution

Use BuildKit’s cache mounts.

Alpine example:

RUN --mount=type=cache,target=/var/cache/apk,sharing=locked \
    apk update && \
    apk add curl

Rules:

  • --mount=... goes immediately after RUN.
  • target must be the package manager’s cache dir.
  • Use && so apk add only runs if apk update succeeds.

5. Runtime Control: Executables

Make the container behave like a single-purpose binary.

  • ENTRYPOINT → The command.
  • CMD → Default arguments (overridable at docker run).
ENTRYPOINT ["curl"]
CMD ["https://google.com"]

Running the container is now basically like running curl https://google.com.


6. The Exec Form Trap (Critical)

Shell form vs exec form:

CMD echo $HOME
  • Goes through a shell.
  • $HOME expands correctly. ✅
CMD ["echo", "$HOME"]
  • No shell → no variable expansion.
  • Prints the literal string $HOME. ❌

Golden Rule:
If you need dynamic environment variables at runtime, use:

  • Shell form, or
  • A small shell script as your ENTRYPOINT, and keep CMD as plain arguments.

By – Chinmay Bagad

Thank you for reading. This article is part of the PaperAstro starter template.