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

GitHub - GoogleContainerTools/container-structure-test: validate the structure of your container images
validate the structure of your container images. Contribute to GoogleContainerTools/container-structure-test development by creating an account on GitHub.

Read more