Docker Integration Setup
Relevant source files
The following files were used as context for generating this wiki page:
- src/flext_tests/_docker_parts/docker_part_01.py
- src/flext_tests/_docker_parts/docker_part_02.py
- src/flext_tests/_docker_parts/docker_part_03.py
- src/flext_tests/_docker_parts/docker_part_04.py
- src/flext_tests/_docker_parts/docker_part_05.py
- src/flext_tests/_docker_parts/docker_part_06.py
- src/flext_tests/_models/docker.py
- tests/integration/test_docker_integration.py
The Docker Integration system in flext-tests provides a robust, fluent DSL (Domain Specific Language) for managing containerized environments during testing. It abstracts low-level Docker SDK and Docker Compose operations into high-level commands, allowing developers to define, start, and verify the readiness of test dependencies like databases or LDAP servers.
The core of the system is the FlextTestsDocker class (often referred via the alias tk), which handles client initialization, persistent state management for "dirty" containers, and complex orchestration flows such as idempotency checks and port-readiness validation.
Sources: src/flext_tests/_docker_parts/docker_part_01.py:1-20, README.md:1-20, tests/integration/test_docker_integration.py:15-30
Core Architecture and Components
The integration is built as a layered inheritance chain of "parts," each responsible for a specific aspect of Docker management.
Architecture Overview
The system uses a combination of python-on-whales for Docker Compose orchestration and the standard docker-py (Docker SDK) for fine-grained container inspection and lifecycle management.
The diagram above shows the flow from high-level DSL calls to the underlying libraries and persistent state.
Sources: src/flext_tests/_docker_parts/docker_part_01.py:15-25, src/flext_tests/_docker_parts/docker_part_03.py:15-20, src/flext_tests/_docker_parts/docker_part_04.py:15-25
Key Data Models
The system relies on structured Pydantic models to define configurations and capture container state.
| Model | Description | Key Fields |
|---|---|---|
ContainerConfig | Defines a target Docker service to manage. | container_name, compose_file, service, port, startup_timeout, force_recreate |
ContainerInfo | Represents the runtime state of a container. | name, status, ports (mapping), image, container_id |
Sources: src/flext_tests/_models/docker.py:18-65
The Fluent DSL Interface
The public interface for interacting with Docker is primarily through class methods that return a configured instance of FlextTestsDocker (aliased as tk).
tk.shared(container_name): Resolves a pre-defined container configuration from centralized settings (e.g.,flext-oracle-db-test).tk.compose(compose_file): Configures a target based on an explicit path to a Docker Compose file.tk.stack(compose_file): Alias forcompose, typically used for multi-service environments where individual container inspection is not required.
Sources: src/flext_tests/_docker_parts/docker_part_05.py:18-70, tests/unit/_docker_parts/builders.py:25-50
Execution Lifecycle and Readiness
The execute() method is the primary entry point for ensuring a container is ready for use. It implements a self-healing logic flow.
The diagram illustrates the logic used to determine if a container needs recreation or just a start command.
Sources: src/flext_tests/_docker_parts/docker_part_06.py:16-45
Readiness Checks
Readiness is determined by wait_for_port_ready. This method attempts to open a TCP socket to the configured host and port, retrying until the startup_timeout (default 30s) is reached.
Sources: src/flext_tests/_docker_parts/docker_part_04.py:72-88, src/flext_tests/_models/docker.py:35-40
State Management and Isolation
To prevent test pollution and handle infrastructure failures, the system tracks "dirty" containers.
Dirty State Tracking
If a test marks a container as dirty (e.g., via mark_container_dirty), the next call to execute() or cleanup_dirty_containers() will trigger a full recreation of that container with fresh volumes.
State is persisted in ~/.flext/docker_state_{worker_id}.json.
Sources: src/flext_tests/_docker_parts/docker_part_02.py:19-75
Worker Isolation
The worker_id parameter (defaulting to "master") is used to isolate persistent state files. This allows parallel test execution (e.g., via pytest-xdist) to manage separate sets of containers without state collision.
Sources: src/flext_tests/_docker_parts/docker_part_01.py:24-27, src/flext_tests/_docker_parts/docker_part_02.py:23-26
Configuration and Helpers
The system provides several internal helpers to bridge the gap between Docker's raw output and the project's internal models.
- Port Resolution:
_resolve_readiness_portmaps container-side ports to their dynamically assigned host-side ports by inspecting theContainerInfoport mapping. - Path Resolution:
_compose_pathresolves relative compose file paths against theworkspace_root.
Sources: src/flext_tests/_docker_parts/docker_part_01.py:53-75, src/flext_tests/_docker_parts/docker_part_03.py:48-55
Conclusion
Docker Integration in flext-tests ensures a reliable and idempotent test environment. By combining persistent state tracking with a high-level fluent DSL, it minimizes the boilerplate required to manage complex external dependencies. The system's ability to handle worker isolation and automatic container recreation makes it suitable for both local development and CI/CD pipelines.
Sources: README.md:10-15, tests/integration/test_docker_integration.py:45-55