Skip to main content

Parameterized Dockerfiles

This article refers to Platform v3.1.0. The current Platform version is v3.2.0.

Overview

A reusable Dockerfile is parameterised — it accepts values from the outside so that the same recipe can produce images for development, staging, and production. Docker provides two mechanisms:

  • ARGbuild-time parameters set during docker build (overridable with --build-arg).
  • ENVruntime environment variables baked into the image (overridable with -e on docker run).

This article shows when to use each, then walks through a small Node.js example.

Video walkthrough

Watch this step on YouTube: Parametrized Dockerfiles.

Build-time vs runtime parameters

Build-time — ARG

Set values that influence the image being built but are not part of the running container's environment.

Typical uses:

  • Picking the base image version.
  • Compile-time switches (DEBUG=1, WITH_FEATURE=true).
  • Build-only secrets that should not be embedded in the final image.
ARG NODE_VERSION=14
FROM node:${NODE_VERSION}

Runtime — ENV

Set environment variables that are present inside the running container. The application reads them at runtime via process.env, os.getenv(), etc.

Typical uses:

  • Switching the app between development and production modes.
  • Pointing the app at a different upstream URL per deployment.
ENV APP_ENV=production

Overriding parameters from the CLI

Override ARG at build time

docker build -t parameterized-app:1.0 --build-arg NODE_VERSION=16 .

NODE_VERSION is set to 16 for this build, overriding the default 14 in the Dockerfile.

Override ENV at run time

docker run -p 8080:8080 -e APP_MODE=development parameterized-app:1.0

APP_MODE is set to development, overriding the default production baked into the image.

Practice — parameterised Node.js app

1. Create the project

mkdir 03_01_parameterized-dockerfile
cd 03_01_parameterized-dockerfile

2. Application files

app.js:

const http = require('http');
const appMode = process.env.APP_MODE || 'development';

const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(`Application is running in ${appMode} mode!\n`);
});

server.listen(8080, () => {
console.log(`Server running on http://localhost:8080 in ${appMode} mode.`);
});

package.json:

{
"name": "parameterized-dockerfile",
"version": "1.0.0",
"main": "app.js",
"dependencies": {
"http": "^0.0.1-security"
}
}

3. Dockerfile

# Build-time argument for Node.js version
ARG NODE_VERSION=14

# Base image (parametrised)
FROM node:${NODE_VERSION}

# Working directory
WORKDIR /app

# Application files
COPY package*.json .
COPY app.js .

# Install dependencies
RUN npm install

# Runtime environment variable
ENV APP_MODE=production

# Port
EXPOSE 8080

# Default command
CMD ["node", "app.js"]

4. Build and run

Build the image with a custom Node version:

docker build -t parameterized-app:1.0 --build-arg NODE_VERSION=16 .

Run the container in development mode:

docker run -p 8080:8080 -e APP_MODE=development parameterized-app:1.0

5. Verify

curl http://localhost:8080

Expected output:

Application is running in development mode!

Summary

ARG for build-time parameters, ENV for runtime parameters — combined, they let one Dockerfile target many environments. Use --build-arg to pick a base image version or compile flag, and -e (or the environment: block in Compose) to point the running app at the right environment.