Testcontainers Python

repository·main·Indexed 25 days ago

https://github.com/testcontainers/testcontainers-python

A Python library for managing throwaway instances of any service that can run in a Docker container, facilitating functional and integration testing. It provides programmatic control over container lifecycles and includes community modules for common services such as PostgreSQL, Kafka, LocalStack, Elasticsearch, Redis, and various cloud emulators for AWS, Azure, and Google Cloud.

Tokens
39.4K
Snippets
131
Records
255
Agent score
81%

What's inside testcontainers-python

  1. Use DockerRegistryContainer for local image testing with Buildx

    main
    When using Docker Buildx to build images (especially multi-arch images), you cannot easily test them locally without a registry, as Buildx typically pushes to Docker Hub by default. DockerRegistryContainer provides a way to spin up a local registry container, allowing you to push your built images to a local endpoint for testing within your test suite.
  2. How the Testcontainers Garbage Collector works

    main

    Testcontainers for Python uses a specialized container called "Ryuk" (the reaper) to ensure resources are cleaned up. Ryuk is automatically started when you create your first test container. It is designed to remove containers even in scenarios where standard Python cleanup might fail, such as:

    1. Normal Python process exit.
    2. Unexpected Python process termination.
    3. System crashes or power loss.

    Ryuk tracks containers using a unique session ID assigned to each test session, which enables safe cleanup even when running tests in parallel.

  3. Configure connection modes

    main

    Testcontainers-Python supports three connection modes to determine how containers are accessed. You can set this via the TESTCONTAINERS_CONNECTION_MODE environment variable or the connection.mode property in .testcontainers.properties.

    Supported modes:

    1. bridge_ip (default): Uses the bridge network IP address.
    2. gateway_ip: Uses the gateway IP address.
    3. docker_host: Uses the Docker host address.
  4. How Docker host detection works

    main

    Testcontainers-Python attempts to automatically detect the Docker environment. If automatic detection fails, it follows this specific precedence order for customization:

    1. tc.host property in ~/.testcontainers.properties (e.g., tc.host=tcp://my.docker.host:1234)
    2. TC_HOST or TESTCONTAINERS_HOST_OVERRIDE environment variable
    3. DOCKER_HOST environment variable
    4. The current Docker context (via docker context use)
    5. Default Docker socket path (without unix schema, e.g., /var/run/docker.sock)
    6. docker.host property in ~/.testcontainers.properties (e.g., docker.host=tcp://my.docker.host:1234)
    7. Rootless Docker socket paths (checking ${XDG_RUNTIME_DIR}/.docker/run/docker.sock, ${HOME}/.docker/run/docker.sock, etc.)

    If no host is detected, a DockerHostError is raised.

  5. Configure Testcontainers connection modes

    main

    Testcontainers-Python supports three connection modes to determine how containers are accessed. This is useful for configuring how your test code interacts with containers in different environments like Docker-in-Docker (DinD) or local development.

    1. bridge_ip (default): Uses the bridge network IP address. Best for DinD scenarios, direct container-to-container communication, or when containers need to communicate over a bridge network.
    2. gateway_ip: Uses the gateway IP address. Best for DinD scenarios or when containers need to access the host network/services running on the host.
    3. docker_host: Uses the Docker host address. Best for local development or when running tests outside of containers to access containers from the host machine.

    You can set the connection mode using the TESTCONTAINERS_CONNECTION_MODE environment variable or the connection.mode property in a .testcontainers.properties file.

  6. How Docker socket path detection works

    main

    Testcontainers-Python automatically detects the Docker socket path. If customization is needed, it follows this order:

    1. TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE environment variable (used by Ryuk, Docker Compose, etc.)
    2. If on Windows with Docker Desktop, it returns the //var/run/docker.sock UNC path. Otherwise, it returns the default rootless Docker socket path.
    3. The current Docker host (using the detection strategies mentioned in the Docker host detection guide).
    4. If the socket contains the unix:// schema, the schema is removed.
    5. The default location /var/run/docker.sock is used as a fallback.

    If the host cannot be discovered, a DockerHostError is raised.

  7. Container communication methods

    main

    There are three primary ways to enable communication between containers:

    1. Network Aliases: Assign an alias to a container using with_network_aliases(["alias"]). Other containers on the same network can reach it via alias:port.
    2. Container IP Addresses: Use get_container_host_ip() to retrieve the IP address of a container for direct communication.
    3. Host Networking: Use with_network_mode("host") to make the container use the host's network stack directly.
  8. Get started with Testcontainers Python

    main

    Testcontainers Python allows you to use Docker containers for functional and integration testing. You can spin up specific database containers (like PostgreSQL) and use convenience methods like get_connection_url() to connect your application code to the running container.

    >>> from testcontainers.postgres import PostgresContainer
    >>> import sqlalchemy
    
    >>> with PostgresContainer("postgres:16") as postgres:
    ...     engine = sqlalchemy.create_engine(postgres.get_connection_url())
    ...     with engine.begin() as connection:
    ...         result = connection.execute(sqlalchemy.text("select version()"))
    ...         version, = result.fetchone()
    >>> version
    'PostgreSQL 16...'
  9. Authenticate with Docker registries using built-in credentials

    main

    Testcontainers-Python can automatically use credentials already stored in your Docker credential store. This is the simplest method for accessing private registries if you have already performed a docker login on your machine.

    from testcontainers.community.generic import GenericContainer
    
    # Docker will automatically use stored credentials
    container = GenericContainer("private.registry.com/myimage:latest")