|
testcontainers-cpp 0.2.0
Native C++20 Testcontainers over the Docker Engine API
|
A RAII handle to a running Docker Compose project. More...
#include <testcontainers/DockerComposeContainer.hpp>
Public Member Functions | |
| DockerComposeContainer (std::vector< std::string > compose_files) | |
| Build from host compose files (default client = Local). | |
| DockerComposeContainer (const std::string &compose_file) | |
| Single-file convenience. | |
| DockerComposeContainer (const DockerComposeContainer &)=delete | |
| DockerComposeContainer & | operator= (const DockerComposeContainer &)=delete |
| DockerComposeContainer (DockerComposeContainer &&) noexcept | |
| A moved-from handle owns nothing: destroying it tears nothing down. | |
| DockerComposeContainer & | operator= (DockerComposeContainer &&) noexcept |
| Releases the target's own stack/temp file before adopting the source's. | |
| ~DockerComposeContainer () | |
| Best-effort stop() (never throws). | |
| DockerComposeContainer & | with_client (ComposeClientKind kind) & |
| Override the client kind on an existing instance (so e.g. | |
| DockerComposeContainer && | with_client (ComposeClientKind kind) && |
| DockerComposeContainer & | with_exposed_service (std::string service, ContainerPort port) & |
| Record a service + container port to wait for at start() (an EXTRA TCP probe on top of compose --wait). | |
| DockerComposeContainer && | with_exposed_service (std::string service, ContainerPort port) && |
| DockerComposeContainer & | with_exposed_service (std::string service, int instance, ContainerPort port) & |
| DockerComposeContainer && | with_exposed_service (std::string service, int instance, ContainerPort port) && |
| DockerComposeContainer & | with_scale (std::string service, int instances) & |
| Run instances containers of service (up --scale <service>=<n>; repeatable — the last value per service wins; overrides the file's deploy.replicas). | |
| DockerComposeContainer && | with_scale (std::string service, int instances) && |
| DockerComposeContainer & | with_ambassador (std::string service, ContainerPort port) & |
| Reach service's port from the host WITHOUT the service publishing it: start() brings up one extra "ambassador" container (a socat relay, see with_ambassador_image) joined to the compose project network, with an ephemeral published port forwarding to service:port over the network. | |
| DockerComposeContainer && | with_ambassador (std::string service, ContainerPort port) && |
| DockerComposeContainer & | with_ambassador_image (std::string image) & |
| Override the socat relay image used by with_ambassador (default: "alpine/socat:1.8.0.3", or the TESTCONTAINERS_SOCAT_CONTAINER_IMAGE env var / socat.container.image key of ~/.testcontainers.properties when set). | |
| DockerComposeContainer && | with_ambassador_image (std::string image) && |
| DockerComposeContainer & | with_profile (std::string profile) & |
| Activate a compose profile (repeatable). | |
| DockerComposeContainer && | with_profile (std::string profile) && |
| DockerComposeContainer & | with_project_name (std::string name) & |
| Override the compose project name (default: "tc" + random hex). | |
| DockerComposeContainer && | with_project_name (std::string name) && |
| DockerComposeContainer & | with_compose_image (std::string image) & |
| Override the containerised client's long-lived cli image (default: "docker:26.1-cli", or the TESTCONTAINERS_COMPOSE_CONTAINER_IMAGE env var / compose.container.image key of ~/.testcontainers.properties when set). | |
| DockerComposeContainer && | with_compose_image (std::string image) && |
| DockerComposeContainer & | with_env (std::string key, std::string value) & |
| Set a single environment variable on the compose invocation. | |
| DockerComposeContainer && | with_env (std::string key, std::string value) && |
| DockerComposeContainer & | with_env_vars (std::map< std::string, std::string > env) & |
| Set environment variables in bulk (merged over any already set). | |
| DockerComposeContainer && | with_env_vars (std::map< std::string, std::string > env) && |
| DockerComposeContainer & | with_build (bool build=true) & |
| Build images before starting (--build). Default off. | |
| DockerComposeContainer && | with_build (bool build=true) && |
| DockerComposeContainer & | with_pull (bool pull=true) & |
| Pull images before starting (--pull always). Default off. | |
| DockerComposeContainer && | with_pull (bool pull=true) && |
| DockerComposeContainer & | with_wait (bool wait=true) & |
| Use compose's native --wait for readiness. Default ON. | |
| DockerComposeContainer && | with_wait (bool wait=true) && |
| DockerComposeContainer & | with_wait_timeout (std::chrono::seconds timeout) & |
| Readiness timeout, default 60s. | |
| DockerComposeContainer && | with_wait_timeout (std::chrono::seconds timeout) && |
| DockerComposeContainer & | with_remove_volumes (bool remove=true) & |
| Remove volumes on teardown (down --volumes). Default true. | |
| DockerComposeContainer && | with_remove_volumes (bool remove=true) && |
| DockerComposeContainer & | with_remove_images (bool remove=true) & |
| Remove images on teardown (down --rmi all). Default false. | |
| DockerComposeContainer && | with_remove_images (bool remove=true) && |
| void | start () |
| Bring the stack up: resolve the client, run compose up -d ... --wait, discover the service containers by the compose project label, and wait for each with_exposed_service host port to accept a TCP connection. | |
| std::string | get_service_host (const std::string &service) const |
| The host to reach a service on (the daemon host; "localhost" for a pipe / unix socket — the same for every instance). | |
| std::uint16_t | get_service_port (const std::string &service, ContainerPort port) const |
| The published host port mapping service's container port (IPv4-pref), on the first (lowest-numbered) instance. | |
| std::uint16_t | get_service_port (const std::string &service, int instance, ContainerPort port) const |
| The published host port mapping container port on instance instance (numbered from 1) of a scaled service. | |
| std::string | get_service_container_id (const std::string &service) const |
| The discovered container id backing service — the first (lowest-numbered) instance (throws if unknown). | |
| std::string | get_service_container_id (const std::string &service, int instance) const |
| The discovered container id backing instance instance (numbered from 1) of a scaled service. | |
| std::vector< int > | service_instances (const std::string &service) const |
| The running instance numbers of service, ascending (a single-instance service yields {1}). | |
| ContainerLogs | get_service_logs (const std::string &service, const LogOptions &opts={}) const |
| A snapshot of service's stdout / stderr logs — the first (lowest-numbered) instance's. | |
| ContainerLogs | get_service_logs (const std::string &service, int instance, const LogOptions &opts={}) const |
| The log snapshot of instance instance (numbered from 1) of a scaled service. | |
| void | follow_service_logs (const std::string &service, const LogConsumer &consumer, const LogOptions &opts={}) const |
| Stream service's logs (first instance) to consumer until the container stops or the consumer returns false. | |
| void | follow_service_logs (const std::string &service, int instance, const LogConsumer &consumer, const LogOptions &opts={}) const |
| The instance-selecting form of the blocking stream above. | |
| FollowEnd | follow_service_logs (const std::string &service, const LogConsumer &consumer, std::chrono::steady_clock::time_point deadline, const LogOptions &opts={}) const |
| Deadline-bounded stream of service's logs (first instance): also stops when deadline passes, returning why the stream ended instead of blocking until the container stops. | |
| FollowEnd | follow_service_logs (const std::string &service, int instance, const LogConsumer &consumer, std::chrono::steady_clock::time_point deadline, const LogOptions &opts={}) const |
| The instance-selecting form of the deadline-bounded stream above. | |
| void | stop () |
| Tear the stack down (compose down) and remove leftovers by the project label. | |
| const std::string & | project_name () const noexcept |
| The compose project name (used for the project label and container names). | |
| const std::vector< std::string > & | compose_files () const noexcept |
| The compose files this handle drives (host paths). | |
| ComposeClientKind | client_kind () const noexcept |
| The selected client kind (default Local). | |
| const std::string & | compose_image () const noexcept |
| The containerised client's cli image ("ambassador" is the socat relay — see ambassador_image()). | |
| const std::map< std::string, std::string > & | env () const noexcept |
| The environment variables set on the compose invocation. | |
| const std::vector< std::string > & | profiles () const noexcept |
| The active compose profiles, in the order added. | |
| const std::map< std::string, int > & | scales () const noexcept |
| The requested per-service instance counts (service -> n). | |
| const std::vector< std::pair< std::string, ContainerPort > > & | ambassadors () const noexcept |
| The registered ambassador targets, in the order added. | |
| const std::string & | ambassador_image () const noexcept |
| The socat relay image with_ambassador uses. | |
| bool | build () const noexcept |
| --build flag. | |
| bool | pull () const noexcept |
| --pull always flag. | |
| bool | wait () const noexcept |
| --wait flag. | |
| std::chrono::seconds | wait_timeout () const noexcept |
| --wait-timeout value. | |
| bool | remove_volumes () const noexcept |
| down --volumes flag. | |
| bool | remove_images () const noexcept |
| down --rmi all flag. | |
Static Public Member Functions | |
| static DockerComposeContainer | with_local_client (std::vector< std::string > compose_files) |
| static DockerComposeContainer | with_containerised_client (std::vector< std::string > compose_files) |
| static DockerComposeContainer | with_auto_client (std::vector< std::string > compose_files) |
| static DockerComposeContainer | from_yaml (const std::string &compose_yaml) |
| Inline YAML convenience: writes a temp .yml file (cleaned up on destruction) and uses it as the single compose file; default Local. | |
A RAII handle to a running Docker Compose project.
Three client modes, selected by ComposeClientKind:
Readiness uses compose v2's native --wait --wait-timeout <secs> (default on, 60s) PLUS — as an extra guarantee — the existing per-with_exposed_service TCP-connect probe after up, which confirms the published port is actually open even for services without a healthcheck.
Discovery + teardown is unchanged: after up we discover service containers by the com.docker.compose.project label; on stop()/destruction we run compose down and a best-effort project-label sweep.
Move-only: it owns the running compose project (and, in containerised mode, the long-lived cli container) and tears everything down on stop()/destruction.
A plain public header (no Boost/Asio/subprocess/filesystem leakage): all of that lives in the .cpp and the internal src/compose/ files.
|
explicit |
Build from host compose files (default client = Local).
The files are referenced by absolute path at start() (they are not read here); for containerised mode they are copied into the cli container.
|
explicit |
Single-file convenience.
|
delete |
|
noexcept |
A moved-from handle owns nothing: destroying it tears nothing down.
| testcontainers::DockerComposeContainer::~DockerComposeContainer | ( | ) |
Best-effort stop() (never throws).
|
static |
|
static |
|
static |
|
static |
Inline YAML convenience: writes a temp .yml file (cleaned up on destruction) and uses it as the single compose file; default Local.
|
delete |
|
noexcept |
Releases the target's own stack/temp file before adopting the source's.
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_client | ( | ComposeClientKind | kind | ) | & |
Override the client kind on an existing instance (so e.g.
from_yaml(...).with_client(Containerised) works).
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_client | ( | ComposeClientKind | kind | ) | && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_exposed_service | ( | std::string | service, |
| ContainerPort | port ) & |
Record a service + container port to wait for at start() (an EXTRA TCP probe on top of compose --wait).
The port must be published by the service (via ports:) so the host can reach it. For a scaled service this probes the first (lowest-numbered) instance; the three-argument overload probes a specific one.
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_exposed_service | ( | std::string | service, |
| ContainerPort | port ) && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_exposed_service | ( | std::string | service, |
| int | instance, | ||
| ContainerPort | port ) & |
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_exposed_service | ( | std::string | service, |
| int | instance, | ||
| ContainerPort | port ) && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_scale | ( | std::string | service, |
| int | instances ) & |
Run instances containers of service (up --scale <service>=<n>; repeatable — the last value per service wins; overrides the file's deploy.replicas).
Scaling to 0 starts none. Instances are numbered from 1 and selected via the instance-taking accessor overloads.
A service cannot scale past 1 while publishing a FIXED host port — the instances would collide over it. Publish the container port alone (e.g. - "6379") so each instance gets its own ephemeral host port.
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_scale | ( | std::string | service, |
| int | instances ) && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_ambassador | ( | std::string | service, |
| ContainerPort | port ) & |
Reach service's port from the host WITHOUT the service publishing it: start() brings up one extra "ambassador" container (a socat relay, see with_ambassador_image) joined to the compose project network, with an ephemeral published port forwarding to service:port over the network.
get_service_port(service, port) then transparently resolves to the ambassador's published port. Repeatable — all targets share the one ambassador container.
Limits: the forward targets the SERVICE name (compose-network DNS), so a scaled service is reached round-robin per connection — per-instance targeting needs published ports; every target must live on one shared project network; and a with_exposed_service TCP probe on an ambassador port only proves the RELAY is listening (socat accepts, then dials the service per connection) — gate real readiness on compose --wait / healthchecks or your own round-trip.
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_ambassador | ( | std::string | service, |
| ContainerPort | port ) && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_ambassador_image | ( | std::string | image | ) | & |
Override the socat relay image used by with_ambassador (default: "alpine/socat:1.8.0.3", or the TESTCONTAINERS_SOCAT_CONTAINER_IMAGE env var / socat.container.image key of ~/.testcontainers.properties when set).
The hub image-name prefix applies to the resolved value at start().
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_ambassador_image | ( | std::string | image | ) | && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_profile | ( | std::string | profile | ) | & |
Activate a compose profile (repeatable).
Services carrying profiles: in the YAML only start when one of their profiles is active; profile-less services always start. The profiles stay active for the teardown down too, so profile-gated services are removed with the rest of the stack. Prefer this over setting COMPOSE_PROFILES via with_env: when both are given they do not merge, and which one wins varies by compose version.
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_profile | ( | std::string | profile | ) | && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_project_name | ( | std::string | name | ) | & |
Override the compose project name (default: "tc" + random hex).
The project is registered with the Ryuk reaper at start(): EVERYTHING carrying this com.docker.compose.project label — containers, project networks and volumes — is removed shortly after the test process exits. Do not reuse the name of a compose stack that must outlive the tests.
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_project_name | ( | std::string | name | ) | && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_compose_image | ( | std::string | image | ) | & |
Override the containerised client's long-lived cli image (default: "docker:26.1-cli", or the TESTCONTAINERS_COMPOSE_CONTAINER_IMAGE env var / compose.container.image key of ~/.testcontainers.properties when set).
Ignored by the Local client. The hub image-name prefix applies to the resolved value at start().
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_compose_image | ( | std::string | image | ) | && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_env | ( | std::string | key, |
| std::string | value ) & |
Set a single environment variable on the compose invocation.
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_env | ( | std::string | key, |
| std::string | value ) && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_env_vars | ( | std::map< std::string, std::string > | env | ) | & |
Set environment variables in bulk (merged over any already set).
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_env_vars | ( | std::map< std::string, std::string > | env | ) | && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_build | ( | bool | build = true | ) | & |
Build images before starting (--build). Default off.
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_build | ( | bool | build = true | ) | && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_pull | ( | bool | pull = true | ) | & |
Pull images before starting (--pull always). Default off.
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_pull | ( | bool | pull = true | ) | && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_wait | ( | bool | wait = true | ) | & |
Use compose's native --wait for readiness. Default ON.
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_wait | ( | bool | wait = true | ) | && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_wait_timeout | ( | std::chrono::seconds | timeout | ) | & |
Readiness timeout, default 60s.
Applies to compose --wait (--wait-timeout <secs>) AND to each exposed service's TCP probe; the phases are budgeted separately (each gets the full timeout), not shared under one deadline.
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_wait_timeout | ( | std::chrono::seconds | timeout | ) | && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_remove_volumes | ( | bool | remove = true | ) | & |
Remove volumes on teardown (down --volumes). Default true.
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_remove_volumes | ( | bool | remove = true | ) | && |
| DockerComposeContainer & testcontainers::DockerComposeContainer::with_remove_images | ( | bool | remove = true | ) | & |
Remove images on teardown (down --rmi all). Default false.
| DockerComposeContainer && testcontainers::DockerComposeContainer::with_remove_images | ( | bool | remove = true | ) | && |
| void testcontainers::DockerComposeContainer::start | ( | ) |
Bring the stack up: resolve the client, run compose up -d ... --wait, discover the service containers by the compose project label, and wait for each with_exposed_service host port to accept a TCP connection.
Throws DockerError on any failure (a non-zero compose exit includes its output).
| std::string testcontainers::DockerComposeContainer::get_service_host | ( | const std::string & | service | ) | const |
The host to reach a service on (the daemon host; "localhost" for a pipe / unix socket — the same for every instance).
| std::uint16_t testcontainers::DockerComposeContainer::get_service_port | ( | const std::string & | service, |
| ContainerPort | port ) const |
The published host port mapping service's container port (IPv4-pref), on the first (lowest-numbered) instance.
A (service, port) pair registered via with_ambassador resolves to the ambassador's published relay port instead. Throws if the service is unknown or the port isn't published.
| std::uint16_t testcontainers::DockerComposeContainer::get_service_port | ( | const std::string & | service, |
| int | instance, | ||
| ContainerPort | port ) const |
The published host port mapping container port on instance instance (numbered from 1) of a scaled service.
Throws if the service or the instance is unknown, or the port isn't published.
| std::string testcontainers::DockerComposeContainer::get_service_container_id | ( | const std::string & | service | ) | const |
The discovered container id backing service — the first (lowest-numbered) instance (throws if unknown).
| std::string testcontainers::DockerComposeContainer::get_service_container_id | ( | const std::string & | service, |
| int | instance ) const |
The discovered container id backing instance instance (numbered from 1) of a scaled service.
Throws if the service or the instance is unknown (the error lists the running instance numbers).
| std::vector< int > testcontainers::DockerComposeContainer::service_instances | ( | const std::string & | service | ) | const |
The running instance numbers of service, ascending (a single-instance service yields {1}).
Throws if the service is unknown.
| ContainerLogs testcontainers::DockerComposeContainer::get_service_logs | ( | const std::string & | service, |
| const LogOptions & | opts = {} ) const |
A snapshot of service's stdout / stderr logs — the first (lowest-numbered) instance's.
A service whose YAML sets tty: true writes a raw/unframed stream: set opts.tty to read it. Throws if the service is unknown.
Pass options as a spelled-out LogOptions{...} (or omit them) in every log accessor: a bare {} in the options slot reads as int 0 to overload resolution and selects the instance form here — and is ambiguous against the deadline in the follow forms.
| ContainerLogs testcontainers::DockerComposeContainer::get_service_logs | ( | const std::string & | service, |
| int | instance, | ||
| const LogOptions & | opts = {} ) const |
The log snapshot of instance instance (numbered from 1) of a scaled service.
| void testcontainers::DockerComposeContainer::follow_service_logs | ( | const std::string & | service, |
| const LogConsumer & | consumer, | ||
| const LogOptions & | opts = {} ) const |
Stream service's logs (first instance) to consumer until the container stops or the consumer returns false.
Blocking — run on your own thread for background consumption. See DockerClient::follow_logs.
| void testcontainers::DockerComposeContainer::follow_service_logs | ( | const std::string & | service, |
| int | instance, | ||
| const LogConsumer & | consumer, | ||
| const LogOptions & | opts = {} ) const |
The instance-selecting form of the blocking stream above.
| FollowEnd testcontainers::DockerComposeContainer::follow_service_logs | ( | const std::string & | service, |
| const LogConsumer & | consumer, | ||
| std::chrono::steady_clock::time_point | deadline, | ||
| const LogOptions & | opts = {} ) const |
Deadline-bounded stream of service's logs (first instance): also stops when deadline passes, returning why the stream ended instead of blocking until the container stops.
See the DockerClient overload for the deadline mechanics.
| FollowEnd testcontainers::DockerComposeContainer::follow_service_logs | ( | const std::string & | service, |
| int | instance, | ||
| const LogConsumer & | consumer, | ||
| std::chrono::steady_clock::time_point | deadline, | ||
| const LogOptions & | opts = {} ) const |
The instance-selecting form of the deadline-bounded stream above.
| void testcontainers::DockerComposeContainer::stop | ( | ) |
Tear the stack down (compose down) and remove leftovers by the project label.
Idempotent; the destructor calls it best-effort.
|
inlinenoexcept |
The compose project name (used for the project label and container names).
|
inlinenoexcept |
The compose files this handle drives (host paths).
|
inlinenoexcept |
The selected client kind (default Local).
|
inlinenoexcept |
The containerised client's cli image ("ambassador" is the socat relay — see ambassador_image()).
|
inlinenoexcept |
The environment variables set on the compose invocation.
|
inlinenoexcept |
The active compose profiles, in the order added.
|
inlinenoexcept |
The requested per-service instance counts (service -> n).
|
inlinenoexcept |
The registered ambassador targets, in the order added.
|
inlinenoexcept |
The socat relay image with_ambassador uses.
|
inlinenoexcept |
--build flag.
|
inlinenoexcept |
--pull always flag.
|
inlinenoexcept |
--wait flag.
|
inlinenoexcept |
--wait-timeout value.
|
inlinenoexcept |
down --volumes flag.
|
inlinenoexcept |
down --rmi all flag.