Docker Compose setup guide

This is a step-by-step guide to packaging your software, pushing it to the Antithesis registry, and running it in our Docker environment.

If you’re a Docker user, follow this guide. If you’re already running your software with Kubernetes, check out the Kubernetes Setup Guide.

If you’re trying to learn to use Antithesis, our tutorials walk you through it.

Before you do anything else

  1. Make sure you have a container registry and credentials — or contact us to request them.

  2. Antithesis runs your software using Linux container images, much as Docker and Kubernetes do. So it’s helpful to have some understanding of:

    • Docker
    • Your software’s dependencies
  3. Antithesis runs your system in a hermetic simulation environment — meaning no internet access at all. Anything your system needs must either be packaged into the environment or mocked appropriately.

Need help?

If you run into trouble, or simply want to make sure your testing is as thorough as possible, our solutions engineering team would be happy to help — email us at: support@antithesis.com or join our Discord.

Containerize your software

You’ll package your software and its dependencies and upload them to the Antithesis registry. If you’re already deploying with containers, read this note, then jump to the next step.

If this is your first time containerizing software, here’s a basic example to get you started:

Create a Dockerfile in the root directory of your project to containerize it. Your structure might look like this:

my_project/
src/
my_app/
..
Dockerfile

Build a Docker image for your software, compiled for x86-64 CPUs. Be sure to replace <image-name> and <tag-name> appropriately.

docker build --platform linux/amd64 . -t <image-name>:<tag-name>

Containerize your dependencies

Since there’s no internet access inside the Antithesis environment, all of your software’s dependencies need to be deployed alongside it.

There are two ways to do this.

  1. Deploy the actual service, just as you would in production.
  2. Upload a mock of the service.

Deploy the actual service

If the dependency is something you control, e.g. a local database node, follow the previous step to build a container image. You’ll upload it to the Antithesis registry along with your software.

For third-party services, many open-source tools (like Redis, Kafka, MongoDB, MySQL, etc.) are already hosted on public registries such as Docker Hub or Quay. If so, you can simply specify the registry and image when setting up orchestration.

Upload a mock

If a third-party dependency doesn’t offer a public container image, you’ll need a mock of the service. Many companies provide mocks in containerized form (e.g. Stripe provides Stripe-mock), and third-party providers, e.g. Localstack, provide sophisticated pre-built mocks of common dependencies like AWS. Treat these like any other open-source, containerized dependency and specify the registry and image when setting up orchestration.

Handling external dependencies offers more details, and a list of commonly used mocks.

Set up container orchestration

We expect you to deliver a container image that contains a specific directory structure of what to run. We call this the config image.

In this image, include:

  • Any configuration files expected by the containers: license files, settings, environment variables file, or other resources.
  • A container orchestration file, docker-compose.yaml.

The docker-compose.yaml file in this directory lists each of the services you want to have running, the container image that the service should be started from, any external volumes that should be mounted into that container, and other options.

Here’s an example docker-compose.yaml which uses a .env file to declare environment variables. Docker compose offers multiple ways to set environment variables within your containers.

# env variables
POSTGRES_ROOT_PASSWORD=your_root_password
POSTGRES_DATABASE_NAME=your_database_name
POSTGRES_USERNAME=your_user_name
POSTGRES_PASSWORD=your_user_password
version: '3.0'
services:
application1:
container_name: application1
hostname: application1
image: mycompany/my_app_1:my_tag
application2:
container_name: application2
hostname: application2
image: mycompany/my_app_2:my_tag
database:
container_name: database
hostname: database
image: docker.io/library/postgres:17.2
environment:
POSTGRES_ROOT_PASSWORD: ${POSTGRES_ROOT_PASSWORD}
POSTGRES_DATABASE: ${POSTGRES_DATABASE_NAME}
POSTGRES_USER: ${POSTGRES_USERNAME}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- ./volumes/database:/usr/bin/database/data

This is often the trickiest part of the process for users who don’t already deploy software in containers. If you simply follow the example above, you should be on solid ground, but if you run into trouble, here are a few resources you might find helpful:

Here are the contents of our example config directory:

ls -a config/
.
..
docker-compose.yaml
license

Test your setup locally

To test your container orchestration locally, from inside your config directory, run:

docker-compose up

This should produce a running system.

However, we want to test that this all still works without any access to the internet. If you’re on a Linux machine, first enter a network namespace before running the command:

pwd
/home/user/config
unshare -n
[2] $ docker-compose up
...
[Lots of output]
...

If everything still comes up and works, and your services all find each other, then the hardest part is done!

When pushing your container images to our registry, you’ll also send us the config image.

To build a config image, copy all configuration files and add them to a scratch image.

FROM scratch
COPY docker-compose.yaml /docker-compose.yaml

Now you’ll need to add a test template to make it go.

Provide a basic test template

To test your system and find bugs, Antithesis needs to exercise your software. We do this using a test template — code that makes your software do something. There’s a lot you can do with test templates (see Test composition or our tutorial on this for more), but to test your setup, you can use one of your existing integration tests.

To do this, use the following naming conventions to enable Antithesis to detect and run your test. These conventions should be followed exactly.

  1. Create a directory called /opt/antithesis/test/v1/quickstart in any of your containers.

  2. Paste an existing integration test into an executable named singleton_driver_<your_test_name>.<extension> in the directory you just created. Make sure your executable has an appropriate shebang in the first line, e.g. #!/usr/bin/env bash

Now you’ll need to validate that your system can find the test template you just defined — details here. The easiest way to do this is to call docker compose exec on your test command and see if it runs.

docker compose exec <your_service_name> /opt/antithesis/test/v1/quickstart/singleton_driver_<your_test_name>

Add a ready signal for fuzzing

Before running any tests, Antithesis initializes your software and its dependencies. Once your system is up and running, it should emit a setup_complete message to initiate testing.

Our SDKs provide pre-built ways to emit this message. If you cannot use our SDKs, write the following JSONL message to $ANTITHESIS_OUTPUT_DIR/sdk.jsonl — in our environment, we’ll ensure that this variable and the directory it points to always exist.

{"antithesis_setup": { "status": "complete", "details": {"message": "Set up complete - ready for testing!" }}}

Now that you’ve added a test template and enabled your software to tell Antithesis to begin fault injection, you’re ready to deploy to the Antithesis environment for testing!

Push your images

When you become a customer, we configure a container registry for you and send you a credential file $TENANT_NAME.key.json.

To authenticate to your container registry, run the following command:

cat $TENANT_NAME.key.json | docker login -u _json_key https://us-central1-docker.pkg.dev --password-stdin

Now you’re locally authenticated to the registry and can run all other Docker commands as normal.

Push your custom and non-public images (including your config image) to: us-central1-docker.pkg.dev/molten-verve-216720/$TENANT_NAME-repository/.

For example, if your local image is named my_app, you’d tag it as it’s referenced in your docker-compose.yaml and push it as follows:

docker tag my_app:my_tag us-central1-docker.pkg.dev/molten-verve-216720/$TENANT_NAME-repository/my_app
docker push us-central1-docker.pkg.dev/molten-verve-216720/$TENANT_NAME-repository/my_app:my_tag

Images that are publicly available (e.g. docker.io/library/postgres:17.2) can be referenced directly in your config files, you do not need to copy them into the Antithesis registry.

Run your first test

You can use this webhook endpoint to kick off a test run using the username and password we sent you when you became a customer.

curl --fail -u 'user:password' \
-X POST https://<tenant>.antithesis.com/api/v1/launch/basic_test \
-d '{"params": { "antithesis.description":"basic_test on main",
"antithesis.duration":"30",
"antithesis.config_image":"config_image_with_tag",
"antithesis.images":"my_images_with_version_list",
"antithesis.report.recipients":"foo@email.com;bar@email.com"
} }'
  • All container images mentioned in docker-compose.yaml will be automatically pulled into the testing environment.
  • Images needed for setup but not mentioned in docker-compose.yaml should be passed in the antithesis.images parameter with an image name and tags/digests. If it’s public image, include a full path to the image (eg. "antithesis.images":"docker.io/library/postgres:17.2").
  • Do not pass the config image in antithesis.images; it should only be passed to antithesis.config_image.
  • Consult the endpoint reference for more details.

Since you’re just learning the ropes here, we’ve set Antithesis up to test for 30 minutes, but once you’re up and running you’ll be able to specify a longer testing duration. You can also get results through other channels, e.g. via a Slack or Discord integration.

Review the triage report

Within an hour, you’ll receive an email with a link to a triage report. We suggest you read about the triage report and test properties while you wait!

Congratulations — you’re now set up with Antithesis!

From here, we suggest:

Later on, you’ll probably also want to configure your CI system to automate the process of building your software and kicking off webhooks.

  • Introduction
  • Welcome to Antithesis
  • How Antithesis works
  • Using Antithesis with AI
  • Get started
  • Setup guide
  • Overview
  • For Docker Compose users
  • For Kubernetes users
  • Test an example system
  • Overview
  • With Docker Compose
  • Overview
  • Build and run an etcd cluster
  • Add a test template
  • With Kubernetes
  • Overview
  • Build and run an etcd cluster
  • Add a test template
  • Product
  • Test templates
  • Overview
  • Creating test templates
  • Test commands
  • How to check a test template locally
  • How to port tests to Antithesis
  • Test launchers
  • The triage report
  • Overview
  • Findings
  • Environment
  • Utilization
  • Properties
  • Logs Explorer & multiverse map
  • Debugging
  • Overview
  • Causality analysis
  • Multiverse debugging
  • Simple Multiverse debugging
  • Advanced
  • Overview
  • The Antithesis multiverse
  • Querying with event sets
  • Environment utilities
  • Using the Antithesis Notebook
  • Cookbook
  • Tooling integrations
  • CI integration
  • Discord and Slack integrations
  • Issue tracker integration - BETA
  • Configuration
  • Access and authentication
  • The Antithesis environment
  • Best practices
  • Docker best practices
  • Kubernetes best practices
  • Optimizing for testing
  • Concepts
  • Properties and Assertions
  • Overview
  • Properties in Antithesis
  • Assertions in Antithesis
  • Sometimes Assertions
  • Properties to test for
  • Fault injection
  • Reference
  • Webhooks
  • Overview
  • Launching a test
  • Launching a debugging session
  • webhook reference
  • Antithesis API
  • Handling external dependencies
  • SDK reference
  • Overview
  • Define test properties
  • Generate randomness
  • Manage test lifecycle
  • Assertion catalog
  • Coverage instrumentation
  • Go
  • Go SDK
  • Instrumentor
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • Java
  • Java SDK
  • Using the SDK
  • Building your software
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • C SDK
  • C++
  • C++ SDK
  • C/C++ Instrumentation
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • JavaScript
  • Python
  • Python SDK
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • Rust
  • Rust SDK
  • Instrumentation
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • .NET
  • .NET SDK
  • Instrumentation
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • Languages not listed above
  • Fallback SDK
  • Assert (reference)
  • Lifecycle (reference)
  • Assertion Schema
  • FAQ
  • Product FAQs
  • About Antithesis POCs
  • Release notes
  • Release notes
  • General reliability resources
  • Reliability glossary
  • Techniques for better software testing
  • Autonomous testing
  • Deterministic simulation testing
  • Property-based testing
  • White paper — How much does an outage cost?
  • Catalog of reliability properties for key-value datastores
  • Catalog of reliability properties for blockchains
  • Test ACID compliance with a ring test