GitLab Runner: Running your tests with Testcontainers

This documentation is part of the Building Docker images guide. You can view the complete guide here: Build and push Docker images efficiently from your GitLab CI/CD pipelines using Stackhero runners and Docker-in-Docker.

👋 Welcome to the Stackhero documentation!

Stackhero offers a straightforward GitLab Runner cloud solution that makes running your GitLab CI/CD jobs efficient and hassle-free. Here’s what you can expect:

  • Unlimited CI/CD minutes: run your pipelines as often as you need, with no per-minute billing or unexpected charges.
  • Multiple concurrent jobs: speed up your development by running several jobs in parallel.
  • The Docker executor with Docker-in-Docker support: easily build and push container images as part of your CI/CD process.
  • Works seamlessly with both GitLab.com and self-managed GitLab instances.
  • A private, dedicated infrastructure with fast NVMe/SSD storage ensures stable and predictable build performance.
  • Available in 🇪🇺 Europe and 🇺🇸 USA regions to meet your team’s requirements.

Save time: you can connect your first GitLab Runner and start running pipelines in just a few minutes!

Testcontainers is a testing library, available for Java, Go, Node.js, Python, .NET and other languages, that starts real services as disposable Docker containers while your tests run. Instead of mocking a database or a message broker, your integration tests interact with an actual PostgreSQL, MySQL, Redis or Kafka instance, created before the tests and removed immediately afterwards. It is especially popular in Java and Spring projects.

Testcontainers requires a Docker daemon, so it runs with exactly the same Docker-in-Docker configuration as above. No extra variable is needed:

test:
  stage: test
  # Use the image your tests require (a JDK here), not necessarily the docker image:
  image: gradle:jdk21
  services:
    - name: docker:29-dind
      alias: docker
  variables:
    DOCKER_HOST: "tcp://docker:2375"
    DOCKER_TLS_CERTDIR: ""
  script:
    - gradle test

Testcontainers reads DOCKER_HOST to locate the daemon, and it reuses that same docker hostname to access the ports published by the containers it starts. Both work seamlessly, as the docker alias resolves on your job's network.

Keep DOCKER_HOST in your Testcontainers jobs. Without it, Testcontainers falls back to the Docker socket mounted by the runner, then tries to reach your test containers on the host IP address, which your job cannot connect to. The usual symptom is the Ryuk helper container failing with Wait strategy failed. Container is removed, or Timed out waiting for log output matching '.*Started.*'.