|
testcontainers-cpp 0.2.0
Native C++20 Testcontainers over the Docker Engine API
|
A synchronous client for the Docker Engine HTTP API. More...
#include <testcontainers/docker/DockerClient.hpp>
Classes | |
| class | Session |
| While alive, THIS client instance keeps its daemon connection open across requests and reuses it for consecutive idempotent GET calls — all other requests keep opening fresh connections, so a stale-connection retry can never replay a side effect. More... | |
| struct | PullRetry |
| Bounded-retry policy for pull_image (see set_pull_retry). More... | |
| struct | ContainerPathStat |
| Metadata of a container path, decoded from the X-Docker-Container-Path-Stat header of a HEAD /containers/{id}/archive probe — a cheap existence/size check before a download (no archive is transferred). More... | |
Public Member Functions | |
| DockerClient (DockerHost host) | |
| Construct a client for an explicitly resolved host. | |
| DockerClient (const DockerClient &other) | |
| DockerClient & | operator= (const DockerClient &other) |
| DockerClient (DockerClient &&other) noexcept | |
| DockerClient & | operator= (DockerClient &&other) noexcept |
| ~DockerClient ()=default | |
| const DockerHost & | host () const noexcept |
| void | set_transport_timeouts (const docker::TransportTimeouts &timeouts) |
| Transport deadlines applied to every connection this client opens (a copy of the client carries its timeouts along). | |
| const docker::TransportTimeouts & | transport_timeouts () const noexcept |
| void | set_pull_retry (const PullRetry &retry) |
| Retry policy for pull_image: an HTTP 5xx reply to POST /images/create is retried up to attempts total tries with a doubling backoff — that status is how the daemon relays transient registry trouble (an auth-token endpoint blip, a 502 mid-handshake). | |
| const PullRetry & | pull_retry () const noexcept |
| void | set_max_response_body (std::optional< std::uint64_t > limit) |
| Cap the response body size the BUFFERED request paths are willing to hold in memory — request(), logs(), the string copy_from_container — so a runaway reply becomes a DockerError instead of unbounded allocation. | |
| std::optional< std::uint64_t > | max_response_body () const noexcept |
| Response | request (std::string_view method, std::string_view target, std::string_view body={}, const std::vector< std::pair< std::string, std::string > > &headers={}) |
| Perform an HTTP request against the daemon and return the full response. | |
| bool | ping () |
| GET /_ping — true if the daemon answers with a 2xx status. | |
| std::string | server_os () |
| GET /version — the daemon's operating system (the Os field, e.g. | |
| bool | is_windows_engine () |
| True when the daemon is running in Windows-containers mode (server_os() contains "windows", case-insensitive). | |
| void | pull_image (const std::string &image, const std::optional< RegistryAuth > &auth=std::nullopt) |
| POST /images/create?fromImage=... — pull an image (blocks until done). | |
| bool | image_exists (const std::string &reference) |
| GET /images/{reference}/json — true when reference ("name[:tag]" or an image ID) resolves on the daemon. | |
| ImageInspect | inspect_image (const std::string &reference) |
| GET /images/{reference}/json — a structured snapshot of the image (reference is "name[:tag]", an image ID, or a digest). | |
| std::string | inspect_image_raw (const std::string &reference) |
| GET /images/{reference}/json — the RAW response body (the full inspect JSON), so callers can read any field ImageInspect does not model. | |
| void | build_image (const std::string &context_tar, const docker::BuildOptions &options, const docker::BuildLogConsumer &consumer={}) |
| POST /build — build an image from a tar build context (context_tar, an application/x-tar body). | |
| void | build_image (const docker::BodyProducer &context, const docker::BuildOptions &options, const docker::BuildLogConsumer &consumer={}) |
| Streaming POST /build: context writes the tar build context incrementally into the sink it is handed, and each block goes out as one chunk of the request body — the context is never held in memory whole (GenericBuildableImage::build() streams host files this way). | |
| std::string | create_container (const CreateContainerSpec &spec, const std::optional< RegistryAuth > &auth=std::nullopt) |
| POST /containers/create — returns the new container id. | |
| void | start_container (const std::string &id) |
| POST /containers/{id}/start. | |
| ContainerInspect | inspect_container (const std::string &id) |
| GET /containers/{id}/json — throws DockerError if the container is gone. | |
| std::string | inspect_container_raw (const std::string &id) |
| GET /containers/{id}/json — the RAW response body (the full inspect JSON), so callers can read any field ContainerInspect does not model. | |
| std::vector< ContainerSummary > | list_containers (const std::vector< std::pair< std::string, std::string > > &label_filters, bool all=true) |
| GET /containers/json filtered by label equality. | |
| void | stop_container (const std::string &id, std::optional< int > timeout_secs=std::nullopt) |
| POST /containers/{id}/stop (optional grace period in seconds). | |
| void | remove_container (const std::string &id, bool force=true, bool remove_volumes=true) |
| DELETE /containers/{id} — force-kill and remove anonymous volumes by default. | |
| ContainerLogs | logs (const std::string &id, const LogOptions &opts={}) |
| GET /containers/{id}/logs — fetch a snapshot of the container's logs and demultiplex the (non-TTY) stream into separate stdout / stderr text. | |
| void | follow_logs (const std::string &id, const LogOptions &opts, const LogConsumer &consumer) |
| GET /containers/{id}/logs?follow=1 — stream the multiplexed logs, decoding frames and invoking consumer per chunk until the stream ends (container stops) or consumer returns false. | |
| FollowEnd | follow_logs (const std::string &id, const LogOptions &opts, const LogConsumer &consumer, std::chrono::steady_clock::time_point deadline) |
| Deadline-bounded follow_logs: same streaming, but the wait for the next chunk is additionally bounded by the absolute deadline — when it passes, the stream is closed and DeadlineExpired reported instead of blocking until the container stops. | |
| ExecResult | exec (const std::string &id, const std::vector< std::string > &cmd) |
| Run cmd inside the running container and capture its output and exit code, using default options. | |
| ExecResult | exec (const std::string &id, const std::vector< std::string > &cmd, const ExecOptions &opts) |
| Run cmd inside the running container with opts (env / working dir / user / privileged / tty / stdin / detach) and capture its output and exit code. | |
| ExecResult | exec (const std::string &id, const std::vector< std::string > &cmd, const ExecOptions &opts, const LogConsumer &consumer) |
| Streaming variant of exec: starts cmd with opts and delivers output to consumer incrementally as the daemon flushes it (blocking until the command finishes or consumer returns false). | |
| ExecStreamResult | exec (const std::string &id, const std::vector< std::string > &cmd, const ExecOptions &opts, const LogConsumer &consumer, std::chrono::steady_clock::time_point deadline) |
| Deadline-bounded streaming exec: same incremental delivery, but feeding stdin and the wait for each next output chunk are additionally bounded by the absolute deadline — when it passes, the stream is closed and the result says DeadlineExpired instead of blocking until the command finishes. | |
| void | resize_exec (const std::string &exec_id, TtySize size) |
| POST /exec/{exec_id}/resize — resize a STARTED tty exec's pseudo-TTY to size (the foreground command gets SIGWINCH and sees the new rows x columns). | |
| void | resize_container_tty (const std::string &id, TtySize size) |
| POST /containers/{id}/resize — resize the pseudo-TTY of a container created with tty (the foreground process gets SIGWINCH). | |
| void | copy_to_container (const std::string &id, const CopyToContainer &source) |
| PUT /containers/{id}/archive?path=/ — copy a host file, in-memory bytes, or a host directory tree into the container by extracting a tar at the root. | |
| void | copy_to_container (const std::string &id, const std::vector< CopyToContainer > &sources) |
| Batched copy: ONE PUT /containers/{id}/archive whose tar carries the entries of all sources in order (later sources win on a target collision, exactly as consecutive single copies would). | |
| std::string | copy_from_container (const std::string &id, const std::string &container_path) |
| GET /containers/{id}/archive?path=<container_path> — fetch the tar archive of the file or directory at container_path. | |
| void | copy_from_container (const std::string &id, const std::string &container_path, const docker::ByteSink &sink) |
| Streaming download: the same GET /containers/{id}/archive, but the raw tar bytes are delivered to sink in blocks as they arrive instead of being buffered. | |
| void | copy_from_container_to (const std::string &id, const std::string &container_path, const std::filesystem::path &dest_dir) |
| Download the file or directory at container_path and EXTRACT it into the host directory dest_dir (created if missing), streaming: each file's bytes go from the wire straight to disk. | |
| ContainerPathStat | container_path_stat (const std::string &id, const std::string &container_path) |
| HEAD /containers/{id}/archive?path=... — stat a container path without downloading it (see ContainerPathStat). | |
| std::string | create_network (const std::string &name, const std::vector< std::pair< std::string, std::string > > &labels={}) |
| POST /networks/create — create a user-defined network, returning its id. | |
| std::string | create_network (const NetworkCreateSpec &spec) |
| POST /networks/create from a full spec; returns the new network id. | |
| std::vector< NetworkInspect > | list_networks (const std::vector< std::pair< std::string, std::string > > &filters={}) |
| GET /networks?filters=... — list networks, one NetworkInspect per entry (the daemon leaves the attached-containers detail unpopulated in list responses). | |
| NetworkInspect | inspect_network (const std::string &id) |
| GET /networks/{id} — a structured snapshot of a network (id may be a name or an id, as the Docker API accepts both): driver, flags, IPAM pools, options, labels, and the currently attached containers. | |
| std::string | inspect_network_raw (const std::string &id) |
| GET /networks/{id} — the RAW inspect JSON for a network (id may be a name or an id, as the Docker API accepts both), so callers can read any field NetworkInspect does not model. | |
| void | connect_network (const std::string &network_id, const std::string &container_id, const std::vector< std::string > &aliases={}) |
| POST /networks/{id}/connect — attach an existing container, optionally with DNS aliases on this network. | |
| void | disconnect_network (const std::string &network_id, const std::string &container_id, bool force=false) |
| POST /networks/{id}/disconnect — detach a container from a network. | |
| void | remove_network (const std::string &id) |
| DELETE /networks/{id} — remove a network (204 expected). | |
| std::string | create_volume (const VolumeCreateSpec &spec) |
| POST /volumes/create — create a named volume (201 expected), returning the daemon's Name for it. | |
| VolumeInspect | inspect_volume (const std::string &name) |
| GET /volumes/{name} — inspect a volume (200 expected). | |
| std::vector< VolumeInspect > | list_volumes (const std::vector< std::pair< std::string, std::string > > &filters={}) |
| GET /volumes?filters=... — list volumes, one VolumeInspect per entry. | |
| VolumePruneResult | prune_volumes (const std::vector< std::pair< std::string, std::string > > &filters={}) |
| POST /volumes/prune?filters=... — batch-remove unused volumes, returning the daemon's report (deleted names + reclaimed bytes). | |
| void | remove_volume (const std::string &name, bool force=false) |
| DELETE /volumes/{name}?force=<bool> — remove a volume (204 expected). | |
Static Public Member Functions | |
| static DockerClient | from_environment () |
| Construct a client using DockerHost::resolve(). | |
A synchronous client for the Docker Engine HTTP API.
By default each request opens a fresh connection to the daemon over the resolved transport (unix socket / Windows named pipe / TCP / TLS) — the correctness-first choice the Rust reference (bollard) also makes. A scoped Session opts one instance into keep-alive reuse for consecutive GETs (used internally by the wait-strategy polling loops, where the per-request TCP/TLS handshake actually costs); a process-wide connection pool is deliberately NOT provided (see docs/TODO.md for the analysis).
|
explicit |
Construct a client for an explicitly resolved host.
|
inline |
|
inlinenoexcept |
|
default |
|
inline |
|
inlinenoexcept |
|
static |
Construct a client using DockerHost::resolve().
|
inlinenoexcept |
|
inline |
Transport deadlines applied to every connection this client opens (a copy of the client carries its timeouts along).
Endpoints known to be long-polling widen the io deadline internally (stop waits up to its grace period, build may have long silent steps); the streaming call sites (follow_logs, exec attach reads) disable it regardless — or, on their deadline-bounded overloads, re-arm it from the remaining budget instead.
|
inlinenoexcept |
|
inline |
Retry policy for pull_image: an HTTP 5xx reply to POST /images/create is retried up to attempts total tries with a doubling backoff — that status is how the daemon relays transient registry trouble (an auth-token endpoint blip, a 502 mid-handshake).
Anything else fails on the first try: 4xx are permanent, an error embedded in the 200 progress stream is how daemons report a nonexistent image, and a transport deadline expiry (TransportTimeoutError) is never retried. attempts below 1 counts as 1. A copy of the client carries the policy along.
|
inlinenoexcept |
|
inline |
Cap the response body size the BUFFERED request paths are willing to hold in memory — request(), logs(), the string copy_from_container — so a runaway reply becomes a DockerError instead of unbounded allocation.
std::nullopt (the default) keeps the historical no-limit behavior. The paths that manage their own reads (the sink download, copy_from_container_to, follow_logs, exec output, build progress) are not affected by the cap. A copy of the client carries the cap along.
|
inlinenoexcept |
| Response testcontainers::DockerClient::request | ( | std::string_view | method, |
| std::string_view | target, | ||
| std::string_view | body = {}, | ||
| const std::vector< std::pair< std::string, std::string > > & | headers = {} ) |
Perform an HTTP request against the daemon and return the full response.
target is the path, sent VERBATIM (e.g. "/_ping", "/v1.43/containers/json") — this raw escape hatch does no API-version pinning; an unversioned path gets the daemon's default (newest) version. The typed methods below all pin their paths to the negotiated version.
| bool testcontainers::DockerClient::ping | ( | ) |
GET /_ping — true if the daemon answers with a 2xx status.
| std::string testcontainers::DockerClient::server_os | ( | ) |
GET /version — the daemon's operating system (the Os field, e.g.
"linux" / "windows"). Cached process-wide on first success: the engine mode (Linux vs Windows containers) does not change mid-process. Throws DockerError if the daemon is unreachable or the response is malformed.
| bool testcontainers::DockerClient::is_windows_engine | ( | ) |
True when the daemon is running in Windows-containers mode (server_os() contains "windows", case-insensitive).
Used to skip the Linux-only Ryuk reaper and to route engine-specific tests.
| void testcontainers::DockerClient::pull_image | ( | const std::string & | image, |
| const std::optional< RegistryAuth > & | auth = std::nullopt ) |
POST /images/create?fromImage=... — pull an image (blocks until done).
image is "name[:tag]" (tag defaults to "latest").
When auth is provided it is sent verbatim as X-Registry-Auth; otherwise credentials are auto-resolved from the Docker config for the image's registry. A public pull (no credentials found) is unaffected. Transient daemon/registry 5xx replies are retried per the pull_retry() policy (3 tries with a 1s-then-2s backoff by default — see set_pull_retry for what is and is not retried).
| bool testcontainers::DockerClient::image_exists | ( | const std::string & | reference | ) |
GET /images/{reference}/json — true when reference ("name[:tag]" or an image ID) resolves on the daemon.
A purely local check: no registry is contacted. Throws DockerError on any daemon error other than a 404.
| ImageInspect testcontainers::DockerClient::inspect_image | ( | const std::string & | reference | ) |
GET /images/{reference}/json — a structured snapshot of the image (reference is "name[:tag]", an image ID, or a digest).
A purely local lookup: no registry is contacted. Throws DockerError if the image is absent (404 -> NotFoundError) or the daemon errors.
| std::string testcontainers::DockerClient::inspect_image_raw | ( | const std::string & | reference | ) |
GET /images/{reference}/json — the RAW response body (the full inspect JSON), so callers can read any field ImageInspect does not model.
Throws DockerError exactly like inspect_image.
| void testcontainers::DockerClient::build_image | ( | const std::string & | context_tar, |
| const docker::BuildOptions & | options, | ||
| const docker::BuildLogConsumer & | consumer = {} ) |
POST /build — build an image from a tar build context (context_tar, an application/x-tar body).
Blocks until the build finishes. The build progress is decoded as it arrives: each output line goes to consumer (when set), so long builds are observable live. Throws DockerError on a non-200 status or a build error embedded in the streamed output — the error message carries the tail of the step output for debugging.
| void testcontainers::DockerClient::build_image | ( | const docker::BodyProducer & | context, |
| const docker::BuildOptions & | options, | ||
| const docker::BuildLogConsumer & | consumer = {} ) |
Streaming POST /build: context writes the tar build context incrementally into the sink it is handed, and each block goes out as one chunk of the request body — the context is never held in memory whole (GenericBuildableImage::build() streams host files this way).
Response handling (live progress decoding, embedded-error detection, the widened silent-step deadline) matches the string overload; on a mid-upload rejection the daemon's error status is preferred over the raw transport error.
| std::string testcontainers::DockerClient::create_container | ( | const CreateContainerSpec & | spec, |
| const std::optional< RegistryAuth > & | auth = std::nullopt ) |
POST /containers/create — returns the new container id.
If the image is missing (404), pulls it (threading auth through) and retries once.
| void testcontainers::DockerClient::start_container | ( | const std::string & | id | ) |
POST /containers/{id}/start.
| ContainerInspect testcontainers::DockerClient::inspect_container | ( | const std::string & | id | ) |
GET /containers/{id}/json — throws DockerError if the container is gone.
| std::string testcontainers::DockerClient::inspect_container_raw | ( | const std::string & | id | ) |
GET /containers/{id}/json — the RAW response body (the full inspect JSON), so callers can read any field ContainerInspect does not model.
Throws DockerError if the container is gone (404) or the daemon returns a non-200.
| std::vector< ContainerSummary > testcontainers::DockerClient::list_containers | ( | const std::vector< std::pair< std::string, std::string > > & | label_filters, |
| bool | all = true ) |
GET /containers/json filtered by label equality.
all includes stopped containers. label_filters become Docker's filters={"label":["k=v",...]}.
| void testcontainers::DockerClient::stop_container | ( | const std::string & | id, |
| std::optional< int > | timeout_secs = std::nullopt ) |
POST /containers/{id}/stop (optional grace period in seconds).
| void testcontainers::DockerClient::remove_container | ( | const std::string & | id, |
| bool | force = true, | ||
| bool | remove_volumes = true ) |
DELETE /containers/{id} — force-kill and remove anonymous volumes by default.
| ContainerLogs testcontainers::DockerClient::logs | ( | const std::string & | id, |
| const LogOptions & | opts = {} ) |
GET /containers/{id}/logs — fetch a snapshot of the container's logs and demultiplex the (non-TTY) stream into separate stdout / stderr text.
Always a snapshot (follow=0); use follow_logs() to stream.
| void testcontainers::DockerClient::follow_logs | ( | const std::string & | id, |
| const LogOptions & | opts, | ||
| const LogConsumer & | consumer ) |
GET /containers/{id}/logs?follow=1 — stream the multiplexed logs, decoding frames and invoking consumer per chunk until the stream ends (container stops) or consumer returns false.
Blocking: run on your own thread for background consumption. Always streams (follow=1). Throws DockerError if the initial response is not 200.
| FollowEnd testcontainers::DockerClient::follow_logs | ( | const std::string & | id, |
| const LogOptions & | opts, | ||
| const LogConsumer & | consumer, | ||
| std::chrono::steady_clock::time_point | deadline ) |
Deadline-bounded follow_logs: same streaming, but the wait for the next chunk is additionally bounded by the absolute deadline — when it passes, the stream is closed and DeadlineExpired reported instead of blocking until the container stops.
Returns why the stream ended. Used by the log wait strategy; also handy for "collect output for at most N seconds" consumers. Throws like the unbounded overload (a deadline that expires while CONNECTING or reading the response header surfaces as the transport's own TransportTimeoutError, not as DeadlineExpired).
| ExecResult testcontainers::DockerClient::exec | ( | const std::string & | id, |
| const std::vector< std::string > & | cmd ) |
Run cmd inside the running container and capture its output and exit code, using default options.
Equivalent to the opts overload with a default-constructed ExecOptions.
| ExecResult testcontainers::DockerClient::exec | ( | const std::string & | id, |
| const std::vector< std::string > & | cmd, | ||
| const ExecOptions & | opts ) |
Run cmd inside the running container with opts (env / working dir / user / privileged / tty / stdin / detach) and capture its output and exit code.
Creates the exec (POST /containers/{id}/exec), starts it (POST /exec/{exec_id}/start) and reads the exit code (GET /exec/{exec_id}/json).
With opts.detach == true the command is only STARTED (fire-and-forget, docker exec -d): create + start are two plain round-trips, nothing is attached, and the returned ExecResult keeps its defaults — empty output and exit_code 0; the command is still running, so its real status is unknown. detach + stdin_data throws DockerError before any daemon interaction (nothing is attached, so there is no stdin to feed).
With opts.tty == false the returned stream is the multiplexed frame format and is demuxed into stdout_data / stderr_data. With opts.tty == true the stream is raw and unframed: all of it goes to stdout_data and stderr_data is left empty. When opts.stdin_data is set those bytes are written to the exec's stdin and the send side is then half-closed so a reader (e.g. cat) sees EOF; on a transport that cannot half-close (TLS, or a byte-mode named pipe) this throws DockerError instead of hanging the reader. The Windows named pipe to a real daemon half-closes fine (the daemon pipe is message-mode).
| ExecResult testcontainers::DockerClient::exec | ( | const std::string & | id, |
| const std::vector< std::string > & | cmd, | ||
| const ExecOptions & | opts, | ||
| const LogConsumer & | consumer ) |
Streaming variant of exec: starts cmd with opts and delivers output to consumer incrementally as the daemon flushes it (blocking until the command finishes or consumer returns false).
With opts.tty == false the stream is demuxed and each chunk is reported with its LogSource; with opts.tty == true the raw stream is reported as LogSource::Stdout.
Returns an ExecResult whose exit_code is read from the exec inspect (0 when the command was still running after an early consumer stop — the deadline overload below reports that distinction); stdout_data / stderr_data are left empty (the output was delivered to consumer). opts.detach is rejected with a DockerError before any daemon interaction: a detached exec produces no output stream to deliver.
| ExecStreamResult testcontainers::DockerClient::exec | ( | const std::string & | id, |
| const std::vector< std::string > & | cmd, | ||
| const ExecOptions & | opts, | ||
| const LogConsumer & | consumer, | ||
| std::chrono::steady_clock::time_point | deadline ) |
Deadline-bounded streaming exec: same incremental delivery, but feeding stdin and the wait for each next output chunk are additionally bounded by the absolute deadline — when it passes, the stream is closed and the result says DeadlineExpired instead of blocking until the command finishes.
Stopping delivery does NOT kill the command: it keeps running inside the container, so the result's exit_code is present only when the exec inspect says the command had finished (virtually always the case after FollowEnd::StreamEnded; after an early stop it is a race). Deadline mechanics match the follow_logs overload: connecting, the create/start round-trips, and reading the response header run under the transport's io deadline, so an expiry there surfaces as TransportTimeoutError, not as DeadlineExpired; everything after the header — the stdin writes included — is the deadline's. opts.detach is rejected like the overload above.
| void testcontainers::DockerClient::resize_exec | ( | const std::string & | exec_id, |
| TtySize | size ) |
POST /exec/{exec_id}/resize — resize a STARTED tty exec's pseudo-TTY to size (the foreground command gets SIGWINCH and sees the new rows x columns).
ExecOptions::on_started delivers the exec id at exactly the first moment this call is valid; the daemon rejects resizing an exec that has not started (and one whose command already exited). ExecOptions::console_size sets the INITIAL size without this call.
| void testcontainers::DockerClient::resize_container_tty | ( | const std::string & | id, |
| TtySize | size ) |
POST /containers/{id}/resize — resize the pseudo-TTY of a container created with tty (the foreground process gets SIGWINCH).
The daemon rejects resizing a container without a TTY or one that is not running.
| void testcontainers::DockerClient::copy_to_container | ( | const std::string & | id, |
| const CopyToContainer & | source ) |
PUT /containers/{id}/archive?path=/ — copy a host file, in-memory bytes, or a host directory tree into the container by extracting a tar at the root.
Entry names are the target normalized (leading '/' stripped; a Windows drive-rooted target like "C:\x" becomes "x"). A single-file source needs its parent directory to already exist in the container; a directory source creates the target chain itself. The tar is produced and uploaded in blocks (a chunked request body): host files are read as they go out, so the payload is never held in memory whole. Throws DockerError on failure (non-200, or the host source cannot be read).
| void testcontainers::DockerClient::copy_to_container | ( | const std::string & | id, |
| const std::vector< CopyToContainer > & | sources ) |
Batched copy: ONE PUT /containers/{id}/archive whose tar carries the entries of all sources in order (later sources win on a target collision, exactly as consecutive single copies would).
One round-trip and one archive regardless of the source count; an empty vector is a no-op. Streams like the single-source overload; throws like it too.
| std::string testcontainers::DockerClient::copy_from_container | ( | const std::string & | id, |
| const std::string & | container_path ) |
GET /containers/{id}/archive?path=<container_path> — fetch the tar archive of the file or directory at container_path.
Returns the raw tar bytes (extract with docker::extract_tar). Throws DockerError on 404 (no such container or path) or any non-200. Buffers the whole archive — for payloads that should not sit in memory use the sink overload or copy_from_container_to.
| void testcontainers::DockerClient::copy_from_container | ( | const std::string & | id, |
| const std::string & | container_path, | ||
| const docker::ByteSink & | sink ) |
Streaming download: the same GET /containers/{id}/archive, but the raw tar bytes are delivered to sink in blocks as they arrive instead of being buffered.
Status errors (404 -> NotFoundError) are thrown before the first block; an exception from sink aborts the download and propagates unchanged.
| void testcontainers::DockerClient::copy_from_container_to | ( | const std::string & | id, |
| const std::string & | container_path, | ||
| const std::filesystem::path & | dest_dir ) |
Download the file or directory at container_path and EXTRACT it into the host directory dest_dir (created if missing), streaming: each file's bytes go from the wire straight to disk.
Regular files and directories are materialized (permission bits best-effort); symlinks and other special entries are skipped; an entry that would escape dest_dir (absolute path or "..") throws DockerError. A single-file path lands as dest_dir/<basename>; a directory path lands as dest_dir/<dirname>/... (Docker archives are rooted at the requested path's base name).
| ContainerPathStat testcontainers::DockerClient::container_path_stat | ( | const std::string & | id, |
| const std::string & | container_path ) |
HEAD /containers/{id}/archive?path=... — stat a container path without downloading it (see ContainerPathStat).
Throws NotFoundError on 404, DockerError on any other non-200 or an undecodable header.
| std::string testcontainers::DockerClient::create_network | ( | const std::string & | name, |
| const std::vector< std::pair< std::string, std::string > > & | labels = {} ) |
POST /networks/create — create a user-defined network, returning its id.
labels are emitted as the network's Labels map (e.g. for Ryuk reaping).
| std::string testcontainers::DockerClient::create_network | ( | const NetworkCreateSpec & | spec | ) |
POST /networks/create from a full spec; returns the new network id.
| std::vector< NetworkInspect > testcontainers::DockerClient::list_networks | ( | const std::vector< std::pair< std::string, std::string > > & | filters = {} | ) |
GET /networks?filters=... — list networks, one NetworkInspect per entry (the daemon leaves the attached-containers detail unpopulated in list responses).
Each filters pair is {category, expression}, e.g. {"label", "key=value"} or {"name", "my-net"}. Distinct categories AND together; repeated label expressions also AND, while repeated name expressions OR (any-match). The daemon matches network names by SUBSTRING, so callers wanting an exact name must compare .name on the results. Throws DockerError on any non-200.
| NetworkInspect testcontainers::DockerClient::inspect_network | ( | const std::string & | id | ) |
GET /networks/{id} — a structured snapshot of a network (id may be a name or an id, as the Docker API accepts both): driver, flags, IPAM pools, options, labels, and the currently attached containers.
Throws DockerError on any non-200 (NotFoundError on 404).
| std::string testcontainers::DockerClient::inspect_network_raw | ( | const std::string & | id | ) |
GET /networks/{id} — the RAW inspect JSON for a network (id may be a name or an id, as the Docker API accepts both), so callers can read any field NetworkInspect does not model.
Throws DockerError on any non-200 (NotFoundError on 404).
| void testcontainers::DockerClient::connect_network | ( | const std::string & | network_id, |
| const std::string & | container_id, | ||
| const std::vector< std::string > & | aliases = {} ) |
POST /networks/{id}/connect — attach an existing container, optionally with DNS aliases on this network.
| void testcontainers::DockerClient::disconnect_network | ( | const std::string & | network_id, |
| const std::string & | container_id, | ||
| bool | force = false ) |
POST /networks/{id}/disconnect — detach a container from a network.
force also detaches a container that is not running.
| void testcontainers::DockerClient::remove_network | ( | const std::string & | id | ) |
DELETE /networks/{id} — remove a network (204 expected).
| std::string testcontainers::DockerClient::create_volume | ( | const VolumeCreateSpec & | spec | ) |
POST /volumes/create — create a named volume (201 expected), returning the daemon's Name for it.
spec.labels are emitted as the volume's Labels map (e.g. for Ryuk reaping). Throws DockerError otherwise.
| VolumeInspect testcontainers::DockerClient::inspect_volume | ( | const std::string & | name | ) |
GET /volumes/{name} — inspect a volume (200 expected).
Throws DockerError on any non-200 (in particular 404 when the volume does not exist).
| std::vector< VolumeInspect > testcontainers::DockerClient::list_volumes | ( | const std::vector< std::pair< std::string, std::string > > & | filters = {} | ) |
GET /volumes?filters=... — list volumes, one VolumeInspect per entry.
Each filters pair is {category, expression}, e.g. {"label", "key=value"}, {"name", "my-vol"} (a substring match daemon-side), or {"dangling", "true"}. Distinct categories AND together; repeated label expressions also AND, while repeated name expressions OR (any-match). Throws DockerError on any non-200.
| VolumePruneResult testcontainers::DockerClient::prune_volumes | ( | const std::vector< std::pair< std::string, std::string > > & | filters = {} | ) |
POST /volumes/prune?filters=... — batch-remove unused volumes, returning the daemon's report (deleted names + reclaimed bytes).
Filters as in list_volumes; {"label", "key=value"} restricts the sweep. Daemons at API 1.42+ prune only ANONYMOUS unused volumes by default — add {"all", "true"} to sweep named volumes too (pre-1.42 daemons reject that filter with a 400; their default prune already swept named volumes). A label-only filter therefore never removes named volumes on 1.42+ daemons. Throws DockerError on any non-200 (e.g. 409 while another prune runs).
| void testcontainers::DockerClient::remove_volume | ( | const std::string & | name, |
| bool | force = false ) |
DELETE /volumes/{name}?force=<bool> — remove a volume (204 expected).
Throws DockerError on any non-204 (404 if absent, 409 if still in use).