Introduction
In a recent project, I encountered the need to dynamically load different base images based on the Node.js version I wanted for testing.
Docker came to the rescue, offering a simple yet powerful solution using command-line arguments within the FROM
section of a Dockerfile.
The Dockerfile
Let’s start with a straightforward example of a Dockerfile with the dynamic version loading included.
ARG NODE_VERSION_TAG
FROM node:${NODE_VERSION_TAG} as build
The ARG keyword sets up a build-time variable named NODE_VERSION_TAG
.
In the FROM
clause, we immediately utilize this variable with ${NODE_VERSION_TAG}
, dynamically loading the specified version/tag of the node image.
Building with dynamic arguments
When you execute the build process you can specify an argument as follows:
docker build --build-arg NODE_VERSION_TAG=latest -t custom-image-name:v1.0 .
You can also choose any other tag associated with different Node.js versions and underlying OS combinations.
docker build --build-arg NODE_VERSION_TAG=21.2.0 -t custom-image-name:v1.0 .
The container would then be built using the node image at version 21.2.0 as its base.
Extending for image name and tag
To take it a step further, you can dynamically alter both the image name and tag.
ARG BASE_IMAGE_NAME
ARG BASE_IMAGE_TAG
FROM ${BASE_IMAGE_NAME}:${BASE_IMAGE_TAG} as build
Now, you can build with different base images.
docker build --build-arg BASE_IMAGE_NAME=node --build-arg BASE_IMAGE_TAG=21.2.0 -t custom-image-name-node:v1.0 .
docker build --build-arg BASE_IMAGE_NAME=rust --build-arg BASE_IMAGE_TAG=1.74.0 -t custom-image-name-rust:v1.0 .
This approach extends the versatility of your Dockerfile, allowing you to seamlessly adapt to various base images and tags.
Github Actions workflow
As a bonus here is a Github Actions workflow that uses this technique to build a docker image against multiple versions of node.js.
name: Node.js Version Matrix
on:
push:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14, 16, 18]
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Build and Test
run: |
docker build --build-arg NODE_VERSION_TAG=${{ matrix.node-version }} -t myapp-${{ matrix.node-version }}:test .
docker run myapp-${{ matrix.node-version }}:test npm test
This workflow is performing the following actions.
- The workflow triggers on pushes to the main branch.
- It defines a job named “test” that runs on the latest version of Ubuntu.
- The build matrix is configured with three different Node.js versions: 14, 16, and 18.
- The actions/checkout action is used to fetch the repository.
- The actions/setup-node action is used to set up the specified Node.js version from the matrix.
- The build and test steps use the docker build command with the
NODE_VERSION_TAG
argument set to the corresponding Node.js version from the matrix. - The docker run command executes your project’s tests inside the Docker container.
With this workflow, your project will be built and tested against multiple Node.js versions, providing you with valuable insights into its compatibility across different environments.