What is Antithesis? How we’re different Problems we solve Security approach Demo Fintech Customer stories Working with Antithesis Contact us Backstory Leadership Careers Brand

Setup guide

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

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

Before you do anything else

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

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

Here’s something important to keep in mind: Antithesis runs your system in a hermetic simulation environment — meaning no internet access at all. (Think of it as giving your software an internet sabbatical.) 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.

1. 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.

  1. Compile your software to run on x86-64 CPUs.

  2. If your services perform network calls to the public web on startup, for example, to fetch a software dependency or data file, you should move this into the container build process instead - your software will be running without access to the internet.

For example, DON’T do this:

FROM docker.io/ubuntu:24.04
COPY src/my_app /opt/my_app
CMD curl --fail https://example.com/data > /opt/data && /opt/my_app /opt/data

DO this instead:

FROM docker.io/ubuntu:24.04
COPY src/my_app /opt/my_app
RUN curl --fail https://example.com/data > /opt/data
CMD /opt/my_app /opt/data

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>

If you don’t specify the tag name when building the Docker container image, Docker will automatically tag the most recent build of the image as latest.

2. 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.

We’ve put together a list of commonly used mocks in our Handling External Dependencies page. It’s a great resource if you want more details.

As a last resort, you can always write your own mock.

3. Set up container orchestration

Once you’ve packaged your software and its dependencies, it’s time to wire everything up.

Create a directory in your local filesystem, called config, containing:

  • 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.

This config directory will also get packaged and uploaded to the Antithesis registry along with your service container images, but for now, you should just create it locally.

Here’s an example docker-compose.yaml

version: '3.0'

services:
  application1:
    container_name: application1
    hostname: application1
    image: mycompany/app:antithesis-tag

  application2:
    container_name: application2
    hostname: application2
    image: mycompany/app:antithesis-tag

  database:
    container_name: database
    hostname: database
    image: docker.io/mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: your_root_password
      MYSQL_DATABASE: your_database_name
      MYSQL_USER: your_user_name
      MYSQL_PASSWORD: your_user_password
    volumes: 
      - ./volumes/database:/usr/bin/database/data
  • The database service has requested an external volume mount. Data stored in these directories will be mapped out of the container filesystem and will outlive the container’s own lifetime. The volume declarations refer to empty directories created in the configuration directory. Since we’re going to use the configuration directory as our working directory, these relative paths will resolve correctly.
  • The services in the above example can reach each other by hostname. We automatically generate suitable DNS entries from the names of each of the services and inject them into the environment of every other service.

Do not change the logging driver in your docker-compose.yaml, as Antithesis relies on the default logging driver. If you do specify a custom logging driver, Antithesis will generate logs as normal, but not display them in the debugging artifacts we send you.

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 you can also email us at support@antithesis.com if you need help here, or refer to the Docker Compose documentation.

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! Now you’ll need to add a test template to make it go.

4. 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. Checking Test Templates Locally documentation details this process. 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>

5. Add a ready signal

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.

Antithesis only expects to receive one setup_complete message from any of the containers in your system. Antithesis will treat the first such message sent by any running process as its signal to begin testing and injecting faults. Emitting further setup_complete messages has no effect, but if your system isn’t actually ready when the first one is sent, this can lead to unexpected problems.

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!" }}}

details must not terminate with a newline, because the entire message must be JSONL. More details on this syntax here.

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!

6. Build a configuration image

Once you have everything working locally, package your config directory as well. Since you’re already sending the container images for your software and its dependencies, we’ll reuse the same process to receive your configuration files. Antithesis will extract all the files from the config image to run your system. Creating a tagged config image will also help you maintain a versioning system for your configurations.

Create a Dockerfile in the root of your config directory. Copy all configuration files and add them to a scratch image:

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

7. Push your containers

When you start a POC, 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 containers and 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 would tag 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

8. Run your first test

Antithesis provides webhook endpoints that allow you to run tests on demand. This curl command kicks off a test. We sent you the username and password when you started your POC.

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"
    } }'

The antithesis.images parameter should be a list of all images with its tags as mentioned in your docker-compose.yaml.

Do not pass the config image in antithesis.images; it should only be passed to antithesis.config_image.

All lists of parameters should be ; delimited. For more information on these and other parameters, please consult our webhook reference.

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 integration.

9. Do some reading

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
  • How Antithesis Works
  • Tutorial
  • Testing with Antithesis
  • Build and run an etcd cluster
  • Meet the Test Composer
  • User manual
  • Setup guide
  • Properties and Assertions
  • Properties in Antithesis
  • Assertions in Antithesis
  • Properties to Test For
  • Sometimes Assertions
  • Test Composer
  • Test Composer Basics
  • Test Composer Reference
  • Principles of Test Composition
  • Checking Test Templates Locally
  • Webhooks
  • Launching a test
  • Retrieving logs
  • Launching a debugging session
  • Webhook API
  • Reports
  • Triage report
  • Bug report
  • Multiverse debugging
  • Overview
  • Exploring the multiverse
  • Querying with event sets
  • The Environment and its utilities
  • Using the Antithesis Notebook
  • Cookbook
  • The Environment and Multiverse
  • The Antithesis Environment
  • Fault Injection
  • CPUID
  • Reference
  • Handling External Dependencies
  • SDK reference
  • Go
  • Tutorial
  • Instrumentor
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • Java
  • Tutorial
  • Instrumentation
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • C
  • C++
  • Tutorial
  • C/C++ Instrumentation
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • JavaScript
  • Python
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • Rust
  • Tutorial
  • Instrumentation
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • .NET
  • Languages not listed above
  • Assert (reference)
  • Lifecycle (reference)
  • Tooling integrations
  • CI integration
  • Discord and Slack integrations
  • Configuring Antithesis
  • Instrumentation
  • User management
  • Sizing your deployment
  • Best practices
  • Is Antithesis working?
  • Optimizing for Antithesis
  • Finding more bugs
  • FAQ
  • About Antithesis POCs
  • Release notes
  • Release notes