Back to Blog
Lesson 30 of the Docker: Containers & Your First Image course
DevOpsAugust 17, 20263 min read

Advanced Dockerfile Directives: Health Checks and Build Arguments

Master production-grade Dockerfiles by implementing healthchecks and build-time arguments to improve container robustness and configuration flexibility.

dockerdevopsdockerfilecontainerscloud-native
Urban scene of stacked shipping containers with modern architecture background in Tianjin, China.

Previously in this course, we covered optimizing image size to keep your deployments lean and efficient. While small images are essential, a professional-grade container must also be self-aware and flexible. In this lesson, we add two critical capabilities to our Dockerfiles: build-time parameterization and automated runtime monitoring.

Why Robustness Matters

In production, a container might show as "running" according to the Docker daemon, even if the application inside has deadlocked or crashed. Similarly, hardcoding configuration values inside your Dockerfile prevents you from reusing the same image across different environments (like staging vs. production). By mastering ARG and HEALTHCHECK, you transform your static templates into dynamic, resilient services.

Passing Build-Time Arguments with ARG

The ARG directive allows you to define variables that users can pass at build time using the --build-arg flag. Unlike environment variables (covered in managing environment variables), ARG values are only available during the image build process.

Think of ARG as a way to inject "build-time context," such as a specific version number, a library branch, or a build-time flag.

Dockerfile
# Example Dockerfile with ARG
FROM node:18-alpine

# Define an argument with a default value
ARG APP_VERSION=1.0.0

# Use the argument to set an environment variable or label
ENV VERSION=$APP_VERSION
RUN echo "Building version: $VERSION" > /version.txt

CMD ["node", "app.js"]

To build this, you would run: docker build --build-arg APP_VERSION=2.1.5 -t my-app:latest .

Implementing a HEALTHCHECK

A HEALTHCHECK tells Docker how to test if your service is actually performing its duties. If the command returns a non-zero exit code, Docker marks the container as unhealthy. This is vital for orchestration tools (like Swarm or Kubernetes) to automatically restart failed instances.

A basic health check uses curl or a simple script to ping your application's endpoint:

Dockerfile
# Adding a health check to our Dockerfile
FROM nginx:alpine

# Test the web server every 30 seconds
# The container will be marked unhealthy if the command fails for 3 consecutive times
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
  CMD curl -f http://localhost/ || exit 1

Hands-on Exercise: Improving Your Project

For your current project, let’s add these directives to your primary service Dockerfile:

  1. Add an ARG: Define an API_PORT argument that defaults to 8080. Use it to configure your application's listening port.
  2. Add a HEALTHCHECK: If your app exposes an endpoint (e.g., /health), add a HEALTHCHECK instruction to verify the status code is 200.
  3. Build and Verify: Build your image with docker build --build-arg API_PORT=9000 -t my-robust-app .. Run the container and use docker ps to see the "health" status column.

Common Pitfalls

  • Assuming ARG persists: Remember that ARG values are not available in the final container at runtime. If you need a value at runtime, you must pass it to an ENV variable during the build, as shown in the example above.
  • Over-complicating Health Checks: Keep your health check commands lightweight. If your HEALTHCHECK command is too heavy (e.g., runs a complex database query), it can consume significant CPU and memory on your host.
  • Silent Failures: If your HEALTHCHECK fails but your container doesn't restart, ensure your orchestration layer is configured to monitor the health state. Docker alone does not automatically kill/restart containers based on health status without an orchestrator.

FAQ

Q: Can I use ARG for passwords or secrets? A: No. ARG values are stored in the image history and can be inspected via docker history. Use secrets management tools or environment variables injected at runtime instead.

Q: What if my base image doesn't have curl? A: Use a fallback like wget or a small shell script. If you are using minimal base images (like "distroless"), you may need to include a tiny binary to perform the health check.

Q: Can I have multiple HEALTHCHECK instructions? A: No, only the last HEALTHCHECK instruction in a Dockerfile takes effect.

Recap

We’ve upgraded our Docker knowledge by adding ARG for build-time flexibility and HEALTHCHECK for runtime reliability. These patterns are foundational for moving from local experimentation to professional, production-grade container deployments.

Up next: Understanding User Permissions — we'll move away from running as root to secure our containers.

Similar Posts