Skip to content

About

Github Actions helpers for using testcontainers

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

30 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gha-testcontainers

This repo tries to help enable two goals for users of testcontainers:

  1. Faster builds – pull the Testcontainers images in the background so it runs in parallel to JDK, dependency cache and build setup.
  2. Automatic image bumps – create Dockerfiles instead of inlining image names in code. So that Dependabot can do its job.

In a nutshell what we are trying to do it to stop waiting for testcontainers, i.e. logs like

: ✔︎ Docker server version should be at least 1.6.0
: Pulling docker image: postgis/postgis:17-3.5. Please be patient; this may take some time but only needs to be done once.
: Starting to pull image
: Pulling image layers:  0 pending,  0 downloaded,  0 extracted, (0 bytes/0 bytes)
...
: Pulling image layers:  0 pending, 18 downloaded, 18 extracted, (208 MB/208 MB)
: Pull complete. 18 layers, pulled in 7s (downloaded 208 MB at 29 MB/s)

so this can save from 5 to 30 seconds per build, depending on the number and size of images. It does not use any cache.

Features

The project has three parts:

  • GitHub Action – pre-pulls images from Dockerfile(s), in the background. Not a workflow.
  • Small Dockerfile parser – extracts image names from Dockerfile(s) for passing on to testcontainers.
  • Dependabot config example – Copy-paste ready

Usage

Dockerfiles

Create a directory with very simple Dockerfiles, preferably

Dockerfile.myapp

e.g. src/test/resources/testcontainers/Dockerfile.redis:

FROM redis:7.2

or with digest

FROM redis@sha256:...

The action reads only the first FROM line, in the form FROM image[:tag][@digest]. It does not build Dockerfiles or support builders/stage aliases (AS), flags, build args or inline comments.

GitHub Action

Call pre-pull-docker-images right after checkout, before JDK and caches are restored:

- uses: actions/checkout@v7
- name: Pre-pull Docker images in background
  uses: entur/gha-testcontainers/.github/actions/pre-pull-docker-images@v1
  with:
    dockerfile-paths: src/test/resources/testcontainers
- name: Set up Java 25
  uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1
  with:
    java-version: 25
    distribution: liberica
...

or the equivalent for Gradle.

Input Required Description
dockerfile-paths yes Whitespace/newline-separated paths searched recursively for files named Dockerfile*.
registry no Registry address to log in to (e.g. ghcr.io). Default docker.io.
registry-login no Registry username. Login only happens if both login and password are set.
registry-password no Registry password or access token.
prepare-report no true records each pull's output, exit code and duration for the report action. Default false.
Output Description
images Newline-separated list of images that were pre-pulled.

Pulls run detached - they continue in the background after the step ends. Their output is discarded unless you set prepare-report: true, see Reports.

Reports

Background pulls are silent: if one fails (typo in a tag, missing credentials, rate limit), Testcontainers just pulls the image itself later and nothing tells you the pre-pull was wasted. Set prepare-report: true and add the pre-pull-docker-images-report action to see, per image, whether it was pulled, failed or was still running, how long it took, and the tail of its log:

- uses: actions/checkout@v7
- uses: entur/gha-testcontainers/.github/actions/pre-pull-docker-images@v1
  with:
    dockerfile-paths: src/test/resources/testcontainers
    prepare-report: true
# ...
# your steps here, e.g. set up Java and restore dependency caches
# ...
- uses: entur/gha-testcontainers/.github/actions/pre-pull-docker-images-report@v1
- run: mvn verify
- if: always()
  uses: entur/gha-testcontainers/.github/actions/pre-pull-docker-images-report@v1

The report is printed in the job log (one group per image) and added to the job summary; each report step adds its own section. Use the same version of both actions. Composite actions cannot run a step at the end of the job by themselves, which is why the report is a separate step.

Input Required Description
fail-on-error no true fails the step if a pull has failed. Pulls still running never fail it. Default false.

This repository's example workflow builds the Maven example with and without the pre-pull.

Bootstrapping testcontainers in tests

Add a parser to get the right image into testcontainers. Alternatively write your own.

// classpath resource: src/test/resources/testcontainers/Dockerfile.redis
String image = DockerfileImages.fromResource("testcontainers/Dockerfile.redis");
var redis = new GenericContainer<>(DockerImageName.parse(image));

Get our parser from no.entur.testcontainers:dockerfile-helper:1.0.1, alternatively directly copy the class DockerfileImages.java.

Keeping images up to date (via Dependabot)

Dependabot's docker ecosystem understands FROM lines in files named Dockerfile*, so it bumps the tag or digest in your test Dockerfiles with no extra tooling. Add to .github/dependabot.yml:

version: 2
updates:
  - package-ecosystem: "docker"
    directory: "/src/test/resources/testcontainers"
    schedule:
      interval: "weekly"
    cooldown:
      default-days: 7
    groups:
      testcontainers:
        patterns:
          - "*"
    ignore:
      - dependency-name: "bitnamisecure/redis"
  • directory must match where the Dockerfiles live (same as the action's dockerfile-paths) and starts with /. It is not recursive: add one entry per directory (or use directories: with globs).
  • Dependabot picks up files whose name contains Dockerfile (e.g. Dockerfile.redis), so Dockerfile.<name> works out of the box.
  • groups collects all image bumps into a single PR; cooldown delays brand-new releases.
  • ignore is for images deliberately pinned (e.g. a known-bad latest); add a comment in the Dockerfile explaining why.
  • Digest-pinned images (FROM image@sha256:...) are bumped too, as long as a tag is present (FROM image:1.2@sha256:...) - without a tag Dependabot has nothing to track.

See examples/maven/.github/dependabot.yaml.

Permissions and secrets

The action needs no GITHUB_TOKEN permissions and no secrets: pulling public images is anonymous.

  • Only pass registry-login/registry-password if you need private images or higher rate limits, and then use a read-only pull token, not a personal password. For ghcr.io, github.actor with secrets.GITHUB_TOKEN and packages: read avoids a stored secret altogether.
  • Credentials reach the login via environment variables and --password-stdin (never on a command line or interpolated into the script), and are written to the runner's Docker config for the lifetime of the job, as the background pulls need them. Use ephemeral/GitHub-hosted runners, or log out yourself on shared runners.
  • Dockerfile content is treated as untrusted (e.g. from a pull request). A stateful character whitelist allows letters, digits and . _ / : - [ ] in image names/tags, letters, digits and _ + . - in digest algorithms, and only hexadecimal characters in the digest. References cannot start with an option or contain shell syntax, whitespace or control characters. This is not a full Docker/OCI grammar validator. Logged values have control characters stripped, the images output uses a random delimiter, and images are passed to docker pull -- so they can never be parsed as options.
  • The action does not write files into the checkout. Collected image lists are stored under $RUNNER_TEMP, and background pull output goes to /dev/null, so repository symlinks cannot redirect pull logs into runner files. With prepare-report: true, pull output instead goes to a directory under $RUNNER_TEMP (refused if it is a symlink or not owned by the runner user), in files named after a hash of the image, never after the image itself. The report action treats that output as untrusted: only printable ASCII is shown, every log line is prefixed so it cannot form a workflow command (::...) or close the summary's code fence, and only the tail is shown.
  • Pin the action to a commit SHA for supply-chain safety.

About

Github Actions helpers for using testcontainers

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages