Docker best practices

Antithesis runs your system in our testing environment using the configurations in your docker-compose.yaml file. For an overview of the process, please check out our setup guide.

Here are some best practices we suggest you follow to get the most out of your testing.

There’s an example docker-compose.yaml file below with explanatory comments.

Dos

Set container names for all of your services

If you don’t set one, Antithesis generates a container name that may be of the form antithesis-<service-name>-<number>.

Use the same name for container and host names

It’s ideal to use the same name for container_name and hostname. In the report, logging output will be listed under the hostname and if no hostname is supplied, it’ll be inferred, possibly from the container_name.

Configure service healthchecks

To set up Docker provided healthchecks for your services, add the healthcheck attribute, per service, in your docker-compose.yaml configuration. It’s convenient when configuring a system with dependencies — when one service depends on another service to be healthy before being started itself. It’s also useful when trying to emit a setup_complete signal.

Configure the order of service startup and shutdown

Configure the depends_on attribute for services that have dependencies on other services.

Prevent entrypoint process from being assigned pid 1

Set init: true in your containers so the entrypoint process is not assigned to pid 1. It’s not possible to get a core dump for a process with pid 1.

Don’ts

Don’t use compose build for any of your services

Antithesis expects to receive pre-built images before bringing up your system since there’s no internet access within our testing environment.

Don’t change the default logging driver

If you specify a custom logging driver, Antithesis will generate logs as normal, but won’t display them in the debugging artifacts we send you.

Don’t use underscores in hostname

Per the standards for DNS domain names, underscores are not included in the permissible characters. Using underscores in the hostname can create issues in hostname resolution.

Don’t configure an internal network

If you do specify internal: true, your system will not be able to connect to the Antithesis network.

Don’t set a pull policy

Antithesis pulls all the container images before spinning up your system because there’s no internet access inside the testing environment. So, if you set a pull policy for your services that tries to pull images from a registry, it will fail.

Example docker-compose file

Here’s a docker-compose.yaml with comments highlighting the above the points:

version: '3.8'
services:
etcd0:
image: 'docker.io/bitnamilegacy/etcd:3.5'
# Don't set a pull policy that forces to pull the image from a registry
# pull_policy: always
container_name: etcd0 # Set the container name
hostname: etcd0 # Use the same name for container_name and hostname and don't use _ in the hostname
environment:
ETCD_NAME: "etcd0"
ETCD_INITIAL_ADVERTISE_PEER_URLS: "http://etcd0:2380"
ETCD_LISTEN_PEER_URLS: "http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
ETCD_ADVERTISE_CLIENT_URLS: "http://etcd0.etcd:2379"
ETCD_INITIAL_CLUSTER_TOKEN: "etcd-cluster-1"
ETCD_INITIAL_CLUSTER: "etcd0=http://etcd0:2380,etcd1=http://etcd1:2380,etcd2=http://etcd2:2380"
ETCD_INITIAL_CLUSTER_STATE: "new"
ALLOW_NONE_AUTHENTICATION: "yes"
healthcheck: # Configure Docker provided healthchecks for your services
test: ["CMD", "etcdctl", "endpoint", "health"]
interval: 5s
timeout: 5s
retries: 3
init: true # Prevent entrypoint pid 1
# Don't configure an internal network
# networks:
# - etcd-example
etcd1:
image: 'docker.io/bitnamilegacy/etcd:3.5'
container_name: etcd1 # Set the container name
hostname: etcd1 # Use the same value for container_name and hostname and don't use _ in the hostname
environment:
ETCD_NAME: "etcd1"
ETCD_INITIAL_ADVERTISE_PEER_URLS: "http://etcd1:2380"
ETCD_LISTEN_PEER_URLS: "http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
ETCD_ADVERTISE_CLIENT_URLS: "http://etcd1.etcd:2379"
ETCD_INITIAL_CLUSTER_TOKEN: "etcd-cluster-1"
ETCD_INITIAL_CLUSTER: "etcd0=http://etcd0:2380,etcd1=http://etcd1:2380,etcd2=http://etcd2:2380"
ETCD_INITIAL_CLUSTER_STATE: "new"
ALLOW_NONE_AUTHENTICATION: "yes"
healthcheck:
test: ["CMD", "etcdctl", "endpoint", "health"]
interval: 5s
timeout: 5s
retries: 3
init: true # Prevent entrypoint pid 1
# Don't configure an internal network
# networks:
# - etcd-example
etcd2:
image: 'docker.io/bitnamilegacy/etcd:3.5'
container_name: etcd2 # Set the container name
hostname: etcd2 # Use the same value for container_name and hostname and don't use _ in the hostname
environment:
ETCD_NAME: "etcd2"
ETCD_INITIAL_ADVERTISE_PEER_URLS: "http://etcd2:2380"
ETCD_LISTEN_PEER_URLS: "http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
ETCD_ADVERTISE_CLIENT_URLS: "http://etcd2.etcd:2379"
ETCD_INITIAL_CLUSTER_TOKEN: "etcd-cluster-1"
ETCD_INITIAL_CLUSTER: "etcd0=http://etcd0:2380,etcd1=http://etcd1:2380,etcd2=http://etcd2:2380"
ETCD_INITIAL_CLUSTER_STATE: "new"
ALLOW_NONE_AUTHENTICATION: "yes"
healthcheck:
test: ["CMD", "etcdctl", "endpoint", "health"]
interval: 5s
timeout: 5s
retries: 3
init: true # Prevent entrypoint pid 1
# Don't configure an internal network
# networks:
# - etcd-example
health-checker:
image: 'etcd-tutorial-health-checker:tutorial'
container_name: health-checker # Set the container name
# No hostname set because it will not be connected by any other services and this service will exit after publishing a setup_complete message
# hostname: health-checker
depends_on: # Docker will not start health-checker service until etcd0, etcd1, and etcd2 are marked as healthy
etcd0:
condition: service_healthy
etcd1:
condition: service_healthy
etcd2:
condition: service_healthy
entrypoint: ['/entrypoint.py']
# Don't configure an internal network
# networks:
# - etcd-example
client1:
image: 'etcd-tutorial-client:tutorial'
container_name: client1 # Set the container name
hostname: client1 # Use the same name for container_name and hostname and don't use _ in the hostname
entrypoint: "sleep infinity"
init: true # Prevent entrypoint pid 1
# Don't change the default logging driver as Antithesis relies on it. 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.
# logging:
# driver: "local"
# Don't configure an internal network
# networks:
# - etcd-example
client2:
image: 'etcd-tutorial-client:tutorial'
container_name: client2 # Set the container name
hostname: client2 # Use the same name for container_name and hostname and don't use _ in the hostname
entrypoint: "sleep infinity"
init: true # Prevent entrypoint pid 1
# Don't configure an internal network
# networks:
# - etcd-example
# Don't configure an internal network. This prevents your system from connecting to the Antithesis network.
# networks:
# etcd-example:
# internal: true
  • 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