Functional tests on containers with Google container-structure-test
Over the years, I've built hundreds of Docker images for dozens of major companies in Europe & USA. Every time, the same question needs to be answered: "how can we test this image before using it?".
Most of these companies answered this question by adding an additional final layer, aiming to run a command designed to act like a safety cutoff:
FROM public.ecr.aws/docker/library/alpine:3.19
WORKDIR /home
# Install additional packages
RUN apk add --update --no-cache nodejs python3 aws-cli
# Test packages
RUN aws --version # Build will fail if AWS CLI not installed for some reasons.
RUN python --version # Same logic here.
[...]
Even though this method gets the job done, it's not a straightforward approach to creating and maintaining tests.
Google to the rescue
Google is famously known for the "Borg project", which became few years after his creation the omnipresent "Kubernetes".
Since then, Google released in open source various tools, such as Kaniko or Distroless, which became one of the pillars of the success of containers.
Container-structure-test is also a product from Google, providing a framework to validate the structure of a container image. Metadata, contents of the filesystem, or command outputs can be checked. Let's see some usage example.
Testing the metadata
Container environments variables can be tested using the following configuration. This is powerful to make sure a monitoring configuration is correctly set, or to prevent passwords to be set:
metadataTest:
envVars: # Check if this environment variable is correctly set.
- key: PROMETHEUS_ENDPOINT
value: http://production.yetanotherdomainname.com/prometheus
UnboundEnvVars: # Check if this environment variable is not set.
- key: 'AWS_SECRET_ACCESS_KEY'
Testing the filesystem
Testing the filesystem can be beneficial when you need to verify that a specific directory has read/write permissions or to confirm its ownership:
fileExistenceTests:
- name: 'main.py'
path: '/app/'
shouldExist: true
permissions: '-rw-r--r--'
uid: 1000
gid: 1000
isExecutableBy: 'group'
Command output
This setting allows to run the command of your choice and assert the output:
commandTests:
- name: "Check Python version"
command: "python"
args: ["--version"]
expectedOutput: ["3.11"]
Usage
You can install the tool using a single line command:
# Linux
curl -LO https://github.com/GoogleContainerTools/container-structure-test/releases/latest/download/container-structure-test-linux-amd64 && chmod +x container-structure-test-linux-amd64 && mkdir -p $HOME/bin && export PATH=$PATH:$HOME/bin && mv container-structure-test-linux-amd64 $HOME/bin/container-structure-test
Please check the link at the bottom for others operatings systems. Please also note the Docker image is not maintained anymore.
Once installed, you can create a test file:
# file: container-structure-tests.yml
schemaVersion: "2.0.0"
commandTests:
- name: "Check Python"
command: "python"
args: ["--version"]
expectedOutput: ["3.11"]
fileExistenceTests:
- name: 'main.py'
path: '/app/'
shouldExist: true
permissions: '-rw-r--r--'
uid: 1000
gid: 1000
isExecutableBy: 'group'
and execute it:
container-structure-test test \
--image yetanotherdomain.com/registry/myapp:v8.6.11 \ # Your image to test.
--config container-structure-tests.yml.yaml