bollard_next/container.rs
1//! Container API: run docker containers and manage their lifecycle
2
3use futures_core::Stream;
4use futures_util::{StreamExt, TryStreamExt};
5use http::header::{CONNECTION, CONTENT_TYPE, UPGRADE};
6use http::request::Builder;
7use http_body_util::Full;
8use hyper::{body::Bytes, Method};
9use serde::Serialize;
10use serde_derive::Deserialize;
11use tokio::io::AsyncWrite;
12use tokio_util::codec::FramedRead;
13
14use std::cmp::Eq;
15use std::collections::HashMap;
16use std::fmt;
17use std::hash::Hash;
18use std::pin::Pin;
19
20use super::Docker;
21use crate::docker::{body_stream, BodyType};
22use crate::errors::Error;
23use crate::models::*;
24use crate::read::NewlineLogOutputDecoder;
25
26/// Parameters used in the [List Container API](Docker::list_containers())
27///
28/// ## Examples
29///
30/// ```rust
31/// use bollard_next::container::ListContainersOptions;
32///
33/// use std::collections::HashMap;
34/// use std::default::Default;
35///
36/// let mut filters = HashMap::new();
37/// filters.insert("health", vec!["unhealthy"]);
38///
39/// ListContainersOptions{
40/// all: true,
41/// filters,
42/// ..Default::default()
43/// };
44/// ```
45///
46/// ```rust
47/// # use bollard_next::container::ListContainersOptions;
48/// # use std::default::Default;
49/// ListContainersOptions::<String>{
50/// ..Default::default()
51/// };
52/// ```
53#[derive(Debug, Clone, Default, PartialEq, Serialize)]
54pub struct ListContainersOptions<T>
55where
56 T: Into<String> + Eq + Hash + Serialize,
57{
58 /// Return all containers. By default, only running containers are shown
59 pub all: bool,
60 /// Return this number of most recently created containers, including non-running ones
61 pub limit: Option<isize>,
62 /// Return the size of container as fields `SizeRw` and `SizeRootFs`
63 pub size: bool,
64 /// Filters to process on the container list, encoded as JSON. Available filters:
65 /// - `ancestor`=`(<image-name>[:<tag>]`, `<image id>`, or `<image@digest>`)
66 /// - `before`=(`<container id>` or `<container name>`)
67 /// - `expose`=(`<port>[/<proto>]`|`<startport-endport>`/`[<proto>]`)
68 /// - `exited`=`<int>` containers with exit code of `<int>`
69 /// - `health`=(`starting`|`healthy`|`unhealthy`|`none`)
70 /// - `id`=`<ID>` a container's ID
71 /// - `isolation`=(`default`|`process`|`hyperv`) (Windows daemon only)
72 /// - `is-task`=`(true`|`false`)
73 /// - `label`=`key` or `label`=`"key=value"` of a container label
74 /// - `name`=`<name>` a container's name
75 /// - `network`=(`<network id>` or `<network name>`)
76 /// - `publish`=(`<port>[/<proto>]`|`<startport-endport>`/`[<proto>]`)
77 /// - `since`=(`<container id>` or `<container name>`)
78 /// - `status`=(`created`|`restarting`|`running`|`removing`|`paused`|`exited`|`dead`)
79 /// - `volume`=(`<volume name>` or `<mount point destination>`)
80 #[serde(serialize_with = "crate::docker::serialize_as_json")]
81 pub filters: HashMap<T, Vec<T>>,
82}
83
84/// Parameters used in the [Create Container API](Docker::create_container())
85///
86/// ## Examples
87///
88/// ```rust
89/// use bollard_next::container::CreateContainerOptions;
90///
91/// CreateContainerOptions{
92/// name: "my-new-container",
93/// platform: Some("linux/amd64"),
94/// };
95/// ```
96#[derive(Debug, Clone, Default, PartialEq, Serialize)]
97#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
98#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
99pub struct CreateContainerOptions<T>
100where
101 T: Into<String> + Serialize,
102{
103 /// Assign the specified name to the container.
104 pub name: T,
105
106 /// The platform to use for the container.
107 /// Added in API v1.41.
108 #[serde(skip_serializing_if = "Option::is_none")]
109 pub platform: Option<T>,
110}
111
112/// This container's networking configuration.
113#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
114#[serde(rename_all = "PascalCase")]
115#[allow(missing_docs)]
116#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
117#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
118pub struct NetworkingConfig<T: Into<String> + Hash + Eq> {
119 pub endpoints_config: HashMap<T, EndpointSettings>,
120}
121
122/// Container to create.
123#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
124#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
125#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
126pub struct Config {
127 /// The hostname to use for the container, as a valid RFC 1123 hostname.
128 #[serde(rename = "Hostname")]
129 #[serde(skip_serializing_if = "Option::is_none")]
130 pub hostname: Option<String>,
131
132 /// The domain name to use for the container.
133 #[serde(rename = "Domainname")]
134 #[serde(skip_serializing_if = "Option::is_none")]
135 pub domainname: Option<String>,
136
137 /// The user that commands are run as inside the container.
138 #[serde(rename = "User")]
139 #[serde(skip_serializing_if = "Option::is_none")]
140 pub user: Option<String>,
141
142 /// Whether to attach to `stdin`.
143 #[serde(rename = "AttachStdin")]
144 #[serde(skip_serializing_if = "Option::is_none")]
145 pub attach_stdin: Option<bool>,
146
147 /// Whether to attach to `stdout`.
148 #[serde(rename = "AttachStdout")]
149 #[serde(skip_serializing_if = "Option::is_none")]
150 pub attach_stdout: Option<bool>,
151
152 /// Whether to attach to `stderr`.
153 #[serde(rename = "AttachStderr")]
154 #[serde(skip_serializing_if = "Option::is_none")]
155 pub attach_stderr: Option<bool>,
156
157 /// An object mapping ports to an empty object in the form: `{\"<port>/<tcp|udp|sctp>\": {}}`
158 #[serde(rename = "ExposedPorts")]
159 #[serde(skip_serializing_if = "Option::is_none")]
160 #[cfg_attr(feature = "utoipa", schema(value_type = Option<HashMap<String, HashMap<(), ()>>>))]
161 pub exposed_ports: Option<HashMap<String, EmptyObject>>,
162
163 /// Attach standard streams to a TTY, including `stdin` if it is not closed.
164 #[serde(rename = "Tty")]
165 #[serde(skip_serializing_if = "Option::is_none")]
166 pub tty: Option<bool>,
167
168 /// Open `stdin`
169 #[serde(rename = "OpenStdin")]
170 #[serde(skip_serializing_if = "Option::is_none")]
171 pub open_stdin: Option<bool>,
172
173 /// Close `stdin` after one attached client disconnects
174 #[serde(rename = "StdinOnce")]
175 #[serde(skip_serializing_if = "Option::is_none")]
176 pub stdin_once: Option<bool>,
177
178 /// A list of environment variables to set inside the container in the form `[\"VAR=value\", ...]`. A variable without `=` is removed from the environment, rather than to have an empty value.
179 #[serde(rename = "Env")]
180 #[serde(skip_serializing_if = "Option::is_none")]
181 pub env: Option<Vec<String>>,
182
183 /// Command to run specified as a string or an array of strings.
184 #[serde(rename = "Cmd")]
185 #[serde(skip_serializing_if = "Option::is_none")]
186 pub cmd: Option<Vec<String>>,
187
188 /// A TEST to perform TO Check that the container is healthy.
189 #[serde(rename = "Healthcheck")]
190 #[serde(skip_serializing_if = "Option::is_none")]
191 pub healthcheck: Option<HealthConfig>,
192
193 /// Command is already escaped (Windows only)
194 #[serde(rename = "ArgsEscaped")]
195 #[serde(skip_serializing_if = "Option::is_none")]
196 pub args_escaped: Option<bool>,
197
198 /// The name of the image to use when creating the container
199 #[serde(rename = "Image")]
200 #[serde(skip_serializing_if = "Option::is_none")]
201 pub image: Option<String>,
202
203 /// An object mapping mount point paths inside the container to empty objects.
204 #[serde(rename = "Volumes")]
205 #[serde(skip_serializing_if = "Option::is_none")]
206 #[cfg_attr(feature = "utoipa", schema(value_type = Option<HashMap<String, HashMap<(), ()>>>))]
207 pub volumes: Option<HashMap<String, EmptyObject>>,
208
209 /// The working directory for commands to run in.
210 #[serde(rename = "WorkingDir")]
211 #[serde(skip_serializing_if = "Option::is_none")]
212 pub working_dir: Option<String>,
213
214 /// The entry point for the container as a string or an array of strings. If the array consists of exactly one empty string (`[\"\"]`) then the entry point is reset to system default (i.e., the entry point used by docker when there is no `ENTRYPOINT` instruction in the `Dockerfile`).
215 #[serde(rename = "Entrypoint")]
216 #[serde(skip_serializing_if = "Option::is_none")]
217 pub entrypoint: Option<Vec<String>>,
218
219 /// Disable networking for the container.
220 #[serde(rename = "NetworkDisabled")]
221 #[serde(skip_serializing_if = "Option::is_none")]
222 pub network_disabled: Option<bool>,
223
224 /// MAC address of the container.
225 #[serde(rename = "MacAddress")]
226 #[serde(skip_serializing_if = "Option::is_none")]
227 pub mac_address: Option<String>,
228
229 /// `ONBUILD` metadata that were defined in the image's `Dockerfile`.
230 #[serde(rename = "OnBuild")]
231 #[serde(skip_serializing_if = "Option::is_none")]
232 pub on_build: Option<Vec<String>>,
233
234 /// User-defined key/value metadata.
235 #[serde(rename = "Labels")]
236 #[serde(skip_serializing_if = "Option::is_none")]
237 pub labels: Option<HashMap<String, String>>,
238
239 /// Signal to stop a container as a string or unsigned integer.
240 #[serde(rename = "StopSignal")]
241 #[serde(skip_serializing_if = "Option::is_none")]
242 pub stop_signal: Option<String>,
243
244 /// Timeout to stop a container in seconds.
245 #[serde(rename = "StopTimeout")]
246 #[serde(skip_serializing_if = "Option::is_none")]
247 pub stop_timeout: Option<i64>,
248
249 /// Shell for when `RUN`, `CMD`, and `ENTRYPOINT` uses a shell.
250 #[serde(rename = "Shell")]
251 #[serde(skip_serializing_if = "Option::is_none")]
252 pub shell: Option<Vec<String>>,
253
254 /// Container configuration that depends on the host we are running on.
255 /// Shell for when `RUN`, `CMD`, and `ENTRYPOINT` uses a shell.
256 #[serde(rename = "HostConfig")]
257 #[serde(skip_serializing_if = "Option::is_none")]
258 pub host_config: Option<HostConfig>,
259
260 /// This container's networking configuration.
261 #[serde(rename = "NetworkingConfig")]
262 #[serde(skip_serializing_if = "Option::is_none")]
263 pub networking_config: Option<NetworkingConfig<String>>,
264}
265
266impl From<ContainerConfig> for Config {
267 fn from(container: ContainerConfig) -> Self {
268 Config {
269 hostname: container.hostname,
270 domainname: container.domainname,
271 user: container.user,
272 attach_stdin: container.attach_stdin,
273 attach_stdout: container.attach_stdout,
274 attach_stderr: container.attach_stderr,
275 exposed_ports: container.exposed_ports,
276 tty: container.tty,
277 open_stdin: container.open_stdin,
278 stdin_once: container.stdin_once,
279 env: container.env,
280 cmd: container.cmd,
281 healthcheck: container.healthcheck,
282 args_escaped: container.args_escaped,
283 image: container.image,
284 volumes: container.volumes,
285 working_dir: container.working_dir,
286 entrypoint: container.entrypoint,
287 network_disabled: container.network_disabled,
288 mac_address: container.mac_address,
289 on_build: container.on_build,
290 labels: container.labels,
291 stop_signal: container.stop_signal,
292 stop_timeout: container.stop_timeout,
293 shell: container.shell,
294 host_config: None,
295 networking_config: None,
296 }
297 }
298}
299
300/// Parameters used in the [Stop Container API](Docker::stop_container())
301///
302/// ## Examples
303///
304/// use bollard_next::container::StopContainerOptions;
305///
306/// StopContainerOptions{
307/// t: 30,
308/// };
309#[derive(Debug, Copy, Clone, Default, PartialEq, Serialize)]
310#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
311#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
312pub struct StopContainerOptions {
313 /// Number of seconds to wait before killing the container
314 pub t: i64,
315}
316
317/// Parameters used in the [Start Container API](Docker::start_container())
318///
319/// ## Examples
320///
321/// ```rust
322/// use bollard_next::container::StartContainerOptions;
323///
324/// StartContainerOptions{
325/// detach_keys: "ctrl-^"
326/// };
327/// ```
328#[derive(Debug, Clone, Default, PartialEq, Serialize)]
329#[serde(rename_all = "camelCase")]
330#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
331#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
332pub struct StartContainerOptions<T>
333where
334 T: Into<String> + Serialize,
335{
336 /// Override the key sequence for detaching a container. Format is a single character `[a-Z]` or
337 /// `ctrl-<value>` where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`.
338 pub detach_keys: T,
339}
340
341/// Parameters used in the [Remove Container API](Docker::remove_container())
342///
343/// ## Examples
344///
345/// ```rust
346/// use bollard_next::container::RemoveContainerOptions;
347///
348/// use std::default::Default;
349///
350/// RemoveContainerOptions{
351/// force: true,
352/// ..Default::default()
353/// };
354/// ```
355#[derive(Debug, Copy, Clone, Default, PartialEq, Serialize)]
356#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
357#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
358pub struct RemoveContainerOptions {
359 /// Remove the volumes associated with the container.
360 pub v: bool,
361 /// If the container is running, kill it before removing it.
362 pub force: bool,
363 /// Remove the specified link associated with the container.
364 pub link: bool,
365}
366
367/// Parameters used in the [Wait Container API](Docker::wait_container())
368///
369/// ## Examples
370///
371/// ```rust
372/// use bollard_next::container::WaitContainerOptions;
373///
374/// WaitContainerOptions{
375/// condition: "not-running",
376/// };
377/// ```
378#[derive(Debug, Clone, Default, PartialEq, Serialize)]
379#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
380#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
381pub struct WaitContainerOptions<T>
382where
383 T: Into<String> + Serialize,
384{
385 /// Wait until a container state reaches the given condition, either 'not-running' (default),
386 /// 'next-exit', or 'removed'.
387 pub condition: T,
388}
389
390/// Results type for the [Attach Container API](Docker::attach_container())
391pub struct AttachContainerResults {
392 /// [Log Output](LogOutput) enum, wrapped in a Stream.
393 pub output: Pin<Box<dyn Stream<Item = Result<LogOutput, Error>> + Send>>,
394 /// Byte writer to container
395 pub input: Pin<Box<dyn AsyncWrite + Send>>,
396}
397
398impl fmt::Debug for AttachContainerResults {
399 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
400 write!(f, "AttachContainerResults")
401 }
402}
403
404/// Parameters used in the [Attach Container API](Docker::attach_container())
405///
406/// ## Examples
407///
408/// ```rust
409/// use bollard_next::container::AttachContainerOptions;
410///
411/// AttachContainerOptions::<String>{
412/// stdin: Some(true),
413/// stdout: Some(true),
414/// stderr: Some(true),
415/// stream: Some(true),
416/// logs: Some(true),
417/// detach_keys: Some("ctrl-c".to_string()),
418/// };
419/// ```
420#[derive(Debug, Copy, Clone, Default, PartialEq, Serialize)]
421#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
422#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
423pub struct AttachContainerOptions<T>
424where
425 T: Into<String> + Serialize + Default,
426{
427 /// Attach to `stdin`
428 pub stdin: Option<bool>,
429 /// Attach to `stdout`
430 pub stdout: Option<bool>,
431 /// Attach to `stderr`
432 pub stderr: Option<bool>,
433 /// Stream attached streams from the time the request was made onwards.
434 pub stream: Option<bool>,
435 /// Replay previous logs from the container.
436 /// This is useful for attaching to a container that has started and you want to output everything since the container started.
437 /// If stream is also enabled, once all the previous output has been returned, it will seamlessly transition into streaming current output.
438 pub logs: Option<bool>,
439 /// Override the key sequence for detaching a container.
440 /// Format is a single character [a-Z] or ctrl-\<value\> where \<value\> is one of: a-z, @, ^, [, , or _.
441 #[serde(rename = "detachKeys")]
442 pub detach_keys: Option<T>,
443}
444
445/// Parameters used in the [Resize Container Tty API](Docker::resize_container_tty())
446///
447/// ## Examples
448///
449/// ```rust
450/// use bollard_next::container::ResizeContainerTtyOptions;
451///
452/// ResizeContainerTtyOptions {
453/// width: 50,
454/// height: 10,
455/// };
456/// ```
457#[derive(Debug, Copy, Clone, Default, PartialEq, Serialize)]
458#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
459#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
460pub struct ResizeContainerTtyOptions {
461 /// Width of the TTY session in characters
462 #[serde(rename = "w")]
463 pub width: u16,
464 /// Height of the TTY session in characters
465 #[serde(rename = "h")]
466 pub height: u16,
467}
468
469/// Parameters used in the [Restart Container API](Docker::restart_container())
470///
471/// ## Example
472///
473/// ```rust
474/// use bollard_next::container::RestartContainerOptions;
475///
476/// RestartContainerOptions{
477/// t: 30,
478/// };
479/// ```
480#[derive(Debug, Copy, Clone, Default, PartialEq, Serialize)]
481#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
482#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
483pub struct RestartContainerOptions {
484 /// Number of seconds to wait before killing the container.
485 pub t: isize,
486}
487
488/// Parameters used in the [Inspect Container API](Docker::inspect_container())
489///
490/// ## Examples
491///
492/// ```rust
493/// use bollard_next::container::InspectContainerOptions;
494///
495/// InspectContainerOptions{
496/// size: false,
497/// };
498/// ```
499#[derive(Debug, Copy, Clone, Default, PartialEq, Serialize)]
500#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
501#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
502pub struct InspectContainerOptions {
503 /// Return the size of container as fields `SizeRw` and `SizeRootFs`
504 pub size: bool,
505}
506
507/// Parameters used in the [Top Processes API](Docker::top_processes())
508///
509/// ## Examples
510///
511/// ```rust
512/// use bollard_next::container::TopOptions;
513///
514/// TopOptions{
515/// ps_args: "aux",
516/// };
517/// ```
518#[derive(Debug, Clone, Default, PartialEq, Serialize)]
519#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
520#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
521pub struct TopOptions<T>
522where
523 T: Into<String> + Serialize,
524{
525 /// The arguments to pass to `ps`. For example, `aux`
526 pub ps_args: T,
527}
528
529fn is_zero(val: &i64) -> bool {
530 val == &0i64
531}
532
533/// Parameters used in the [Logs API](Docker::logs())
534///
535/// ## Examples
536///
537/// ```rust
538/// use bollard_next::container::LogsOptions;
539///
540/// use std::default::Default;
541///
542/// LogsOptions::<String>{
543/// stdout: true,
544/// ..Default::default()
545/// };
546/// ```
547#[derive(Debug, Clone, Default, PartialEq, Serialize)]
548#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
549#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
550pub struct LogsOptions<T>
551where
552 T: Into<String> + Serialize,
553{
554 /// Return the logs as a finite stream.
555 pub follow: bool,
556 /// Return logs from `stdout`.
557 pub stdout: bool,
558 /// Return logs from `stderr`.
559 pub stderr: bool,
560 /// Only return logs since this time, as a UNIX timestamp.
561 pub since: i64,
562 /// Only return logs before this time, as a UNIX timestamp.
563 #[serde(skip_serializing_if = "is_zero")]
564 // workaround for https://github.com/containers/podman/issues/10859
565 pub until: i64,
566 /// Add timestamps to every log line.
567 pub timestamps: bool,
568 /// Only return this number of log lines from the end of the logs. Specify as an integer or all
569 /// to output `all` log lines.
570 pub tail: T,
571}
572
573/// Result type for the [Logs API](Docker::logs())
574#[derive(Debug, Clone, PartialEq)]
575#[allow(missing_docs)]
576pub enum LogOutput {
577 StdErr { message: Bytes },
578 StdOut { message: Bytes },
579 StdIn { message: Bytes },
580 Console { message: Bytes },
581}
582
583impl fmt::Display for LogOutput {
584 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
585 let message = match &self {
586 LogOutput::StdErr { message } => message,
587 LogOutput::StdOut { message } => message,
588 LogOutput::StdIn { message } => message,
589 LogOutput::Console { message } => message,
590 };
591 write!(f, "{}", String::from_utf8_lossy(message))
592 }
593}
594
595impl AsRef<[u8]> for LogOutput {
596 fn as_ref(&self) -> &[u8] {
597 match self {
598 LogOutput::StdErr { message } => message.as_ref(),
599 LogOutput::StdOut { message } => message.as_ref(),
600 LogOutput::StdIn { message } => message.as_ref(),
601 LogOutput::Console { message } => message.as_ref(),
602 }
603 }
604}
605
606impl LogOutput {
607 /// Get the raw bytes of the output
608 pub fn into_bytes(self) -> Bytes {
609 match self {
610 LogOutput::StdErr { message } => message,
611 LogOutput::StdOut { message } => message,
612 LogOutput::StdIn { message } => message,
613 LogOutput::Console { message } => message,
614 }
615 }
616}
617
618/// Parameters used in the [Stats API](super::Docker::stats())
619///
620/// ## Examples
621///
622/// ```rust
623/// use bollard_next::container::StatsOptions;
624///
625/// StatsOptions{
626/// stream: false,
627/// one_shot: false,
628/// };
629/// ```
630#[derive(Debug, Copy, Clone, Default, PartialEq, Serialize)]
631#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
632#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
633pub struct StatsOptions {
634 /// Stream the output. If false, the stats will be output once and then it will disconnect.
635 pub stream: bool,
636 /// Only get a single stat instead of waiting for 2 cycles. Must be used with `stream = false`.
637 #[serde(rename = "one-shot")]
638 pub one_shot: bool,
639}
640
641/// Granular memory statistics for the container.
642#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
643#[allow(missing_docs)]
644#[serde(untagged)]
645#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
646#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
647pub enum MemoryStatsStats {
648 V1(MemoryStatsStatsV1),
649 V2(MemoryStatsStatsV2),
650}
651
652/// Granular memory statistics for the container, v1 cgroups.
653///
654/// Exposed in the docker library [here](https://github.com/moby/moby/blob/40d9e2aff130b42ba0f83d5238b9b53184c8ab3b/daemon/daemon_unix.go#L1436).
655#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
656#[allow(missing_docs)]
657#[serde(deny_unknown_fields)]
658#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
659#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
660pub struct MemoryStatsStatsV1 {
661 pub cache: u64,
662 pub dirty: u64,
663 pub mapped_file: u64,
664 pub total_inactive_file: u64,
665 pub pgpgout: u64,
666 pub rss: u64,
667 pub total_mapped_file: u64,
668 pub writeback: u64,
669 pub unevictable: u64,
670 pub pgpgin: u64,
671 pub total_unevictable: u64,
672 pub pgmajfault: u64,
673 pub total_rss: u64,
674 pub total_rss_huge: u64,
675 pub total_writeback: u64,
676 pub total_inactive_anon: u64,
677 pub rss_huge: u64,
678 pub hierarchical_memory_limit: u64,
679 pub total_pgfault: u64,
680 pub total_active_file: u64,
681 pub active_anon: u64,
682 pub total_active_anon: u64,
683 pub total_pgpgout: u64,
684 pub total_cache: u64,
685 pub total_dirty: u64,
686 pub inactive_anon: u64,
687 pub active_file: u64,
688 pub pgfault: u64,
689 pub inactive_file: u64,
690 pub total_pgmajfault: u64,
691 pub total_pgpgin: u64,
692 pub hierarchical_memsw_limit: Option<u64>, // only on OSX
693 pub shmem: Option<u64>, // only on linux kernel > 4.15.0-1106
694 pub total_shmem: Option<u64>, // only on linux kernel > 4.15.0-1106
695}
696
697/// Granular memory statistics for the container, v2 cgroups.
698///
699/// Exposed in the docker library [here](https://github.com/moby/moby/blob/40d9e2aff130b42ba0f83d5238b9b53184c8ab3b/daemon/daemon_unix.go#L1542).
700#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
701#[allow(missing_docs)]
702#[serde(deny_unknown_fields)]
703#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
704#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
705pub struct MemoryStatsStatsV2 {
706 pub anon: u64,
707 pub file: u64,
708 pub kernel_stack: u64,
709 pub slab: u64,
710 pub sock: u64,
711 pub shmem: u64,
712 pub file_mapped: u64,
713 pub file_dirty: u64,
714 pub file_writeback: u64,
715 pub anon_thp: u64,
716 pub inactive_anon: u64,
717 pub active_anon: u64,
718 pub inactive_file: u64,
719 pub active_file: u64,
720 pub unevictable: u64,
721 pub slab_reclaimable: u64,
722 pub slab_unreclaimable: u64,
723 pub pgfault: u64,
724 pub pgmajfault: u64,
725 pub workingset_refault: u64,
726 pub workingset_activate: u64,
727 pub workingset_nodereclaim: u64,
728 pub pgrefill: u64,
729 pub pgscan: u64,
730 pub pgsteal: u64,
731 pub pgactivate: u64,
732 pub pgdeactivate: u64,
733 pub pglazyfree: u64,
734 pub pglazyfreed: u64,
735 pub thp_fault_alloc: u64,
736 pub thp_collapse_alloc: u64,
737}
738
739/// General memory statistics for the container.
740#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
741#[allow(missing_docs)]
742#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
743#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
744pub struct MemoryStats {
745 pub stats: Option<MemoryStatsStats>,
746 pub max_usage: Option<u64>,
747 pub usage: Option<u64>,
748 pub failcnt: Option<u64>,
749 pub limit: Option<u64>,
750 pub commit: Option<u64>,
751 pub commit_peak: Option<u64>,
752 pub commitbytes: Option<u64>,
753 pub commitpeakbytes: Option<u64>,
754 pub privateworkingset: Option<u64>,
755}
756
757/// Process ID statistics for the container.
758#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
759#[allow(missing_docs)]
760#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
761#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
762pub struct PidsStats {
763 pub current: Option<u64>,
764 pub limit: Option<u64>,
765}
766
767/// I/O statistics for the container.
768#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
769#[allow(missing_docs)]
770#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
771#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
772pub struct BlkioStats {
773 pub io_service_bytes_recursive: Option<Vec<BlkioStatsEntry>>,
774 pub io_serviced_recursive: Option<Vec<BlkioStatsEntry>>,
775 pub io_queue_recursive: Option<Vec<BlkioStatsEntry>>,
776 pub io_service_time_recursive: Option<Vec<BlkioStatsEntry>>,
777 pub io_wait_time_recursive: Option<Vec<BlkioStatsEntry>>,
778 pub io_merged_recursive: Option<Vec<BlkioStatsEntry>>,
779 pub io_time_recursive: Option<Vec<BlkioStatsEntry>>,
780 pub sectors_recursive: Option<Vec<BlkioStatsEntry>>,
781}
782
783/// File I/O statistics for the container.
784#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
785#[allow(missing_docs)]
786#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
787#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
788pub struct StorageStats {
789 pub read_count_normalized: Option<u64>,
790 pub read_size_bytes: Option<u64>,
791 pub write_count_normalized: Option<u64>,
792 pub write_size_bytes: Option<u64>,
793}
794
795fn empty_string() -> String {
796 "".to_string()
797}
798
799/// Statistics for the container.
800#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
801#[allow(missing_docs)]
802#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
803#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
804pub struct Stats {
805 #[cfg(feature = "time")]
806 #[serde(
807 deserialize_with = "crate::docker::deserialize_rfc3339",
808 serialize_with = "crate::docker::serialize_rfc3339"
809 )]
810 pub read: time::OffsetDateTime,
811 #[cfg(feature = "time")]
812 #[serde(
813 deserialize_with = "crate::docker::deserialize_rfc3339",
814 serialize_with = "crate::docker::serialize_rfc3339"
815 )]
816 pub preread: time::OffsetDateTime,
817 #[cfg(all(feature = "chrono", not(feature = "time")))]
818 pub read: chrono::DateTime<chrono::Utc>,
819 #[cfg(all(feature = "chrono", not(feature = "time")))]
820 pub preread: chrono::DateTime<chrono::Utc>,
821 #[cfg(not(any(feature = "chrono", feature = "time")))]
822 pub read: String,
823 #[cfg(not(any(feature = "chrono", feature = "time")))]
824 pub preread: String,
825 pub num_procs: u32,
826 pub pids_stats: PidsStats,
827 pub network: Option<NetworkStats>,
828 pub networks: Option<HashMap<String, NetworkStats>>,
829 pub memory_stats: MemoryStats,
830 pub blkio_stats: BlkioStats,
831 pub cpu_stats: CPUStats,
832 pub precpu_stats: CPUStats,
833 pub storage_stats: StorageStats,
834 #[serde(default = "empty_string")]
835 pub name: String,
836
837 // Podman incorrectly capitalises the "id" field. See https://github.com/containers/podman/issues/17869
838 #[serde(alias = "Id", default = "empty_string")]
839 pub id: String,
840}
841
842/// Network statistics for the container.
843#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
844#[allow(missing_docs)]
845#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
846#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
847pub struct NetworkStats {
848 pub rx_dropped: u64,
849 pub rx_bytes: u64,
850 pub rx_errors: u64,
851 pub tx_packets: u64,
852 pub tx_dropped: u64,
853 pub rx_packets: u64,
854 pub tx_errors: u64,
855 pub tx_bytes: u64,
856}
857
858/// CPU usage statistics for the container.
859#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
860#[allow(missing_docs)]
861#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
862#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
863pub struct CPUUsage {
864 pub percpu_usage: Option<Vec<u64>>,
865 pub usage_in_usermode: u64,
866 pub total_usage: u64,
867 pub usage_in_kernelmode: u64,
868}
869
870/// CPU throttling statistics.
871#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
872#[allow(missing_docs)]
873#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
874#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
875pub struct ThrottlingData {
876 pub periods: u64,
877 pub throttled_periods: u64,
878 pub throttled_time: u64,
879}
880
881/// General CPU statistics for the container.
882#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
883#[allow(missing_docs)]
884#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
885#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
886pub struct CPUStats {
887 pub cpu_usage: CPUUsage,
888 pub system_cpu_usage: Option<u64>,
889 pub online_cpus: Option<u64>,
890 pub throttling_data: ThrottlingData,
891}
892
893#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
894#[allow(missing_docs)]
895#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
896#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
897pub struct BlkioStatsEntry {
898 pub major: u64,
899 pub minor: u64,
900 pub op: String,
901 pub value: u64,
902}
903
904/// Parameters used in the [Kill Container API](Docker::kill_container())
905///
906/// ## Examples
907///
908/// ```rust
909/// use bollard_next::container::KillContainerOptions;
910///
911/// KillContainerOptions{
912/// signal: "SIGINT",
913/// };
914/// ```
915#[derive(Debug, Clone, Default, PartialEq, Serialize)]
916#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
917#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
918pub struct KillContainerOptions<T>
919where
920 T: Into<String> + Serialize,
921{
922 /// Signal to send to the container as an integer or string (e.g. `SIGINT`)
923 pub signal: T,
924}
925
926/// Configuration for the [Update Container API](Docker::update_container())
927///
928/// ## Examples
929///
930/// ```rust
931/// use bollard_next::container::UpdateContainerOptions;
932/// use std::default::Default;
933///
934/// UpdateContainerOptions::<String> {
935/// memory: Some(314572800),
936/// memory_swap: Some(314572800),
937/// ..Default::default()
938/// };
939/// ```
940#[derive(Debug, Clone, Default, PartialEq, Serialize)]
941#[serde(rename_all = "PascalCase")]
942#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
943#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
944pub struct UpdateContainerOptions<T>
945where
946 T: Into<String> + Eq + Hash,
947{
948 /// An integer value representing this container's relative CPU weight versus other containers.
949 #[serde(rename = "CpuShares")]
950 #[serde(skip_serializing_if = "Option::is_none")]
951 pub cpu_shares: Option<isize>,
952
953 /// Memory limit in bytes.
954 #[serde(rename = "Memory")]
955 #[serde(skip_serializing_if = "Option::is_none")]
956 pub memory: Option<i64>,
957
958 /// Path to `cgroups` under which the container's `cgroup` is created. If the path is not absolute, the path is considered to be relative to the `cgroups` path of the init process. Cgroups are created if they do not already exist.
959 #[serde(rename = "CgroupParent")]
960 #[serde(skip_serializing_if = "Option::is_none")]
961 pub cgroup_parent: Option<T>,
962
963 /// Block IO weight (relative weight).
964 #[serde(rename = "BlkioWeight")]
965 #[serde(skip_serializing_if = "Option::is_none")]
966 pub blkio_weight: Option<u16>,
967
968 /// Block IO weight (relative device weight) in the form `[{\"Path\": \"device_path\", \"Weight\": weight}]`.
969 #[serde(rename = "BlkioWeightDevice")]
970 #[serde(skip_serializing_if = "Option::is_none")]
971 pub blkio_weight_device: Option<Vec<ResourcesBlkioWeightDevice>>,
972
973 /// Limit read rate (bytes per second) from a device, in the form `[{\"Path\": \"device_path\", \"Rate\": rate}]`.
974 #[serde(rename = "BlkioDeviceReadBps")]
975 #[serde(skip_serializing_if = "Option::is_none")]
976 pub blkio_device_read_bps: Option<Vec<ThrottleDevice>>,
977
978 /// Limit write rate (bytes per second) to a device, in the form `[{\"Path\": \"device_path\", \"Rate\": rate}]`.
979 #[serde(rename = "BlkioDeviceWriteBps")]
980 #[serde(skip_serializing_if = "Option::is_none")]
981 pub blkio_device_write_bps: Option<Vec<ThrottleDevice>>,
982
983 /// Limit read rate (IO per second) from a device, in the form `[{\"Path\": \"device_path\", \"Rate\": rate}]`.
984 #[serde(rename = "BlkioDeviceReadIOps")]
985 #[serde(skip_serializing_if = "Option::is_none")]
986 pub blkio_device_read_i_ops: Option<Vec<ThrottleDevice>>,
987
988 /// Limit write rate (IO per second) to a device, in the form `[{\"Path\": \"device_path\", \"Rate\": rate}]`.
989 #[serde(rename = "BlkioDeviceWriteIOps")]
990 #[serde(skip_serializing_if = "Option::is_none")]
991 pub blkio_device_write_i_ops: Option<Vec<ThrottleDevice>>,
992
993 /// The length of a CPU period in microseconds.
994 #[serde(rename = "CpuPeriod")]
995 #[serde(skip_serializing_if = "Option::is_none")]
996 pub cpu_period: Option<i64>,
997
998 /// Microseconds of CPU time that the container can get in a CPU period.
999 #[serde(rename = "CpuQuota")]
1000 #[serde(skip_serializing_if = "Option::is_none")]
1001 pub cpu_quota: Option<i64>,
1002
1003 /// The length of a CPU real-time period in microseconds. Set to 0 to allocate no time allocated to real-time tasks.
1004 #[serde(rename = "CpuRealtimePeriod")]
1005 #[serde(skip_serializing_if = "Option::is_none")]
1006 pub cpu_realtime_period: Option<i64>,
1007
1008 /// The length of a CPU real-time runtime in microseconds. Set to 0 to allocate no time allocated to real-time tasks.
1009 #[serde(rename = "CpuRealtimeRuntime")]
1010 #[serde(skip_serializing_if = "Option::is_none")]
1011 pub cpu_realtime_runtime: Option<i64>,
1012
1013 /// CPUs in which to allow execution (e.g., `0-3`, `0,1`)
1014 #[serde(rename = "CpusetCpus")]
1015 #[serde(skip_serializing_if = "Option::is_none")]
1016 pub cpuset_cpus: Option<T>,
1017
1018 /// Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.
1019 #[serde(rename = "CpusetMems")]
1020 #[serde(skip_serializing_if = "Option::is_none")]
1021 pub cpuset_mems: Option<T>,
1022
1023 /// A list of devices to add to the container.
1024 #[serde(rename = "Devices")]
1025 #[serde(skip_serializing_if = "Option::is_none")]
1026 pub devices: Option<Vec<DeviceMapping>>,
1027
1028 /// a list of cgroup rules to apply to the container
1029 #[serde(rename = "DeviceCgroupRules")]
1030 #[serde(skip_serializing_if = "Option::is_none")]
1031 pub device_cgroup_rules: Option<Vec<T>>,
1032
1033 /// a list of requests for devices to be sent to device drivers
1034 #[serde(rename = "DeviceRequests")]
1035 #[serde(skip_serializing_if = "Option::is_none")]
1036 pub device_requests: Option<Vec<DeviceRequest>>,
1037
1038 /// Hard limit for kernel TCP buffer memory (in bytes).
1039 #[serde(rename = "KernelMemoryTCP")]
1040 #[serde(skip_serializing_if = "Option::is_none")]
1041 pub kernel_memory_tcp: Option<i64>,
1042
1043 /// Memory soft limit in bytes.
1044 #[serde(rename = "MemoryReservation")]
1045 #[serde(skip_serializing_if = "Option::is_none")]
1046 pub memory_reservation: Option<i64>,
1047
1048 /// Total memory limit (memory + swap). Set as `-1` to enable unlimited swap.
1049 #[serde(rename = "MemorySwap")]
1050 #[serde(skip_serializing_if = "Option::is_none")]
1051 pub memory_swap: Option<i64>,
1052
1053 /// Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100.
1054 #[serde(rename = "MemorySwappiness")]
1055 #[serde(skip_serializing_if = "Option::is_none")]
1056 pub memory_swappiness: Option<i64>,
1057
1058 /// CPU quota in units of 10<sup>-9</sup> CPUs.
1059 #[serde(rename = "NanoCpus")]
1060 #[serde(skip_serializing_if = "Option::is_none")]
1061 pub nano_cpus: Option<i64>,
1062
1063 /// Disable OOM Killer for the container.
1064 #[serde(rename = "OomKillDisable")]
1065 #[serde(skip_serializing_if = "Option::is_none")]
1066 pub oom_kill_disable: Option<bool>,
1067
1068 /// Run an init inside the container that forwards signals and reaps processes. This field is omitted if empty, and the default (as configured on the daemon) is used.
1069 #[serde(rename = "Init")]
1070 #[serde(skip_serializing_if = "Option::is_none")]
1071 pub init: Option<bool>,
1072
1073 /// Tune a container's PIDs limit. Set `0` or `-1` for unlimited, or `null` to not change.
1074 #[serde(rename = "PidsLimit")]
1075 #[serde(skip_serializing_if = "Option::is_none")]
1076 pub pids_limit: Option<i64>,
1077
1078 /// A list of resource limits to set in the container. For example: `{\"Name\": \"nofile\", \"Soft\": 1024, \"Hard\": 2048}`\"
1079 #[serde(rename = "Ulimits")]
1080 #[serde(skip_serializing_if = "Option::is_none")]
1081 pub ulimits: Option<Vec<ResourcesUlimits>>,
1082
1083 /// The number of usable CPUs (Windows only). On Windows Server containers, the processor resource controls are mutually exclusive. The order of precedence is `CPUCount` first, then `CPUShares`, and `CPUPercent` last.
1084 #[serde(rename = "CpuCount")]
1085 #[serde(skip_serializing_if = "Option::is_none")]
1086 pub cpu_count: Option<i64>,
1087
1088 /// The usable percentage of the available CPUs (Windows only). On Windows Server containers, the processor resource controls are mutually exclusive. The order of precedence is `CPUCount` first, then `CPUShares`, and `CPUPercent` last.
1089 #[serde(rename = "CpuPercent")]
1090 #[serde(skip_serializing_if = "Option::is_none")]
1091 pub cpu_percent: Option<i64>,
1092
1093 /// Maximum IOps for the container system drive (Windows only)
1094 #[serde(rename = "IOMaximumIOps")]
1095 #[serde(skip_serializing_if = "Option::is_none")]
1096 pub io_maximum_iops: Option<i64>,
1097
1098 /// Maximum IO in bytes per second for the container system drive (Windows only)
1099 #[serde(rename = "IOMaximumBandwidth")]
1100 #[serde(skip_serializing_if = "Option::is_none")]
1101 pub io_maximum_bandwidth: Option<i64>,
1102
1103 /// The behavior to apply when the container exits. The default is not to restart.
1104 ///
1105 /// An ever increasing delay (double the previous delay, starting at 100ms) is added before
1106 /// each restart to prevent flooding the server.
1107 pub restart_policy: Option<RestartPolicy>,
1108}
1109
1110/// Parameters used in the [Rename Container API](Docker::rename_container())
1111///
1112/// ## Examples
1113///
1114/// ```rust
1115/// use bollard_next::container::RenameContainerOptions;
1116///
1117/// RenameContainerOptions {
1118/// name: "my_new_container_name"
1119/// };
1120/// ```
1121#[derive(Debug, Clone, Default, PartialEq, Serialize)]
1122#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
1123#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1124pub struct RenameContainerOptions<T>
1125where
1126 T: Into<String> + Serialize,
1127{
1128 /// New name for the container.
1129 pub name: T,
1130}
1131
1132/// Parameters used in the [Prune Containers API](Docker::prune_containers())
1133///
1134/// ## Examples
1135///
1136/// ```rust
1137/// use bollard_next::container::PruneContainersOptions;
1138///
1139/// use std::collections::HashMap;
1140///
1141/// let mut filters = HashMap::new();
1142/// filters.insert("until", vec!["10m"]);
1143///
1144/// PruneContainersOptions{
1145/// filters
1146/// };
1147/// ```
1148#[derive(Debug, Clone, Default, PartialEq, Serialize)]
1149pub struct PruneContainersOptions<T>
1150where
1151 T: Into<String> + Eq + Hash + Serialize,
1152{
1153 /// Filters to process on the prune list, encoded as JSON.
1154 ///
1155 /// Available filters:
1156 /// - `until=<timestamp>` Prune containers created before this timestamp. The `<timestamp>` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon machine's time.
1157 /// - label (`label=<key>`, `label=<key>=<value>`, `label!=<key>`, or `label!=<key>=<value>`) Prune containers with (or without, in case `label!=...` is used) the specified labels.
1158 #[serde(serialize_with = "crate::docker::serialize_as_json")]
1159 pub filters: HashMap<T, Vec<T>>,
1160}
1161
1162/// Parameters used in the [Upload To Container
1163/// API](Docker::upload_to_container)
1164///
1165/// ## Examples
1166///
1167/// ```rust
1168/// use bollard_next::container::UploadToContainerOptions;
1169///
1170/// use std::default::Default;
1171///
1172/// UploadToContainerOptions{
1173/// path: "/opt",
1174/// ..Default::default()
1175/// };
1176/// ```
1177#[derive(Debug, Clone, Default, PartialEq, Serialize)]
1178#[serde(rename_all = "camelCase")]
1179#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
1180#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1181pub struct UploadToContainerOptions<T>
1182where
1183 T: Into<String> + Serialize,
1184{
1185 /// Path to a directory in the container to extract the archive’s contents into.
1186 pub path: T,
1187 /// If “1”, “true”, or “True” then it will be an error if unpacking the given content would
1188 /// cause an existing directory to be replaced with a non-directory and vice versa.
1189 pub no_overwrite_dir_non_dir: T,
1190}
1191
1192/// Parameters used in the [Download From Container
1193/// API](Docker::download_from_container())
1194///
1195/// ## Examples
1196///
1197/// ```rust
1198/// use bollard_next::container::DownloadFromContainerOptions;
1199///
1200/// DownloadFromContainerOptions{
1201/// path: "/opt",
1202/// };
1203/// ```
1204#[derive(Debug, Clone, Default, PartialEq, Serialize)]
1205pub struct DownloadFromContainerOptions<T>
1206where
1207 T: Into<String> + Serialize,
1208{
1209 /// Resource in the container’s filesystem to archive.
1210 pub path: T,
1211}
1212
1213impl Docker {
1214 /// ---
1215 ///
1216 /// # List Containers
1217 ///
1218 /// Returns a list of containers.
1219 ///
1220 /// # Arguments
1221 ///
1222 /// - Optional [ListContainersOptions](ListContainersOptions) struct.
1223 ///
1224 /// # Returns
1225 ///
1226 /// - Vector of [ContainerSummary](ContainerSummary), wrapped in a Future.
1227 ///
1228 /// # Examples
1229 ///
1230 /// ```rust
1231 /// # use bollard_next::Docker;
1232 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1233 /// use bollard_next::container::ListContainersOptions;
1234 ///
1235 /// use std::collections::HashMap;
1236 /// use std::default::Default;
1237 ///
1238 /// let mut filters = HashMap::new();
1239 /// filters.insert("health", vec!["unhealthy"]);
1240 ///
1241 /// let options = Some(ListContainersOptions{
1242 /// all: true,
1243 /// filters,
1244 /// ..Default::default()
1245 /// });
1246 ///
1247 /// docker.list_containers(options);
1248 /// ```
1249 pub async fn list_containers<'de, T>(
1250 &self,
1251 options: Option<ListContainersOptions<T>>,
1252 ) -> Result<Vec<ContainerSummary>, Error>
1253 where
1254 T: Into<String> + Eq + Hash + Serialize,
1255 {
1256 let url = "/containers/json";
1257
1258 let req = self.build_request(
1259 url,
1260 Builder::new().method(Method::GET),
1261 options,
1262 Ok(BodyType::Left(Full::new(Bytes::new()))),
1263 );
1264
1265 self.process_into_value(req).await
1266 }
1267
1268 /// ---
1269 ///
1270 /// # Create Container
1271 ///
1272 /// Prepares a container for a subsequent start operation.
1273 ///
1274 /// # Arguments
1275 ///
1276 /// - Optional [Create Container Options](CreateContainerOptions) struct.
1277 /// - Container [Config](Config) struct.
1278 ///
1279 /// # Returns
1280 ///
1281 /// - [ContainerCreateResponse](ContainerCreateResponse), wrapped in a Future.
1282 ///
1283 /// # Examples
1284 ///
1285 /// ```rust
1286 /// # use bollard_next::Docker;
1287 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1288 /// use bollard_next::container::{CreateContainerOptions, Config};
1289 ///
1290 /// use std::default::Default;
1291 ///
1292 /// let options = Some(CreateContainerOptions{
1293 /// name: "my-new-container",
1294 /// platform: None,
1295 /// });
1296 ///
1297 /// let config = Config {
1298 /// image: Some("hello-world"),
1299 /// cmd: Some(vec!["/hello"]),
1300 /// ..Default::default()
1301 /// };
1302 ///
1303 /// docker.create_container(options, config);
1304 /// ```
1305 pub async fn create_container<T>(
1306 &self,
1307 options: Option<CreateContainerOptions<T>>,
1308 config: Config,
1309 ) -> Result<ContainerCreateResponse, Error>
1310 where
1311 T: Into<String> + Serialize,
1312 {
1313 let url = "/containers/create";
1314 let req = self.build_request(
1315 url,
1316 Builder::new().method(Method::POST),
1317 options,
1318 Docker::serialize_payload(Some(config)),
1319 );
1320
1321 self.process_into_value(req).await
1322 }
1323
1324 /// ---
1325 ///
1326 /// # Start Container
1327 ///
1328 /// Starts a container, after preparing it with the [Create Container
1329 /// API](struct.Docker.html#method.create_container).
1330 ///
1331 /// # Arguments
1332 ///
1333 /// - Container name as a string slice.
1334 /// - Optional [Start Container Options](StartContainerOptions) struct.
1335 ///
1336 /// # Returns
1337 ///
1338 /// - unit type `()`, wrapped in a Future.
1339 ///
1340 /// # Examples
1341 ///
1342 /// ```rust
1343 /// # use bollard_next::Docker;
1344 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1345 /// use bollard_next::container::StartContainerOptions;
1346 ///
1347 /// docker.start_container("hello-world", None::<StartContainerOptions<String>>);
1348 /// ```
1349 pub async fn start_container<T>(
1350 &self,
1351 container_name: &str,
1352 options: Option<StartContainerOptions<T>>,
1353 ) -> Result<(), Error>
1354 where
1355 T: Into<String> + Serialize,
1356 {
1357 let url = format!("/containers/{container_name}/start");
1358
1359 let req = self.build_request(
1360 &url,
1361 Builder::new().method(Method::POST),
1362 options,
1363 Ok(BodyType::Left(Full::new(Bytes::new()))),
1364 );
1365
1366 self.process_into_unit(req).await
1367 }
1368
1369 /// ---
1370 ///
1371 /// # Stop Container
1372 ///
1373 /// Stops a container.
1374 ///
1375 /// # Arguments
1376 ///
1377 /// - Container name as string slice.
1378 /// - Optional [Stop Container Options](StopContainerOptions) struct.
1379 ///
1380 /// # Returns
1381 ///
1382 /// - unit type `()`, wrapped in a Future.
1383 ///
1384 /// # Examples
1385 ///
1386 /// ```rust
1387 /// # use bollard_next::Docker;
1388 /// use bollard_next::container::StopContainerOptions;
1389 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1390 ///
1391 /// let options = Some(StopContainerOptions{
1392 /// t: 30,
1393 /// });
1394 ///
1395 /// docker.stop_container("hello-world", options);
1396 /// ```
1397 pub async fn stop_container(
1398 &self,
1399 container_name: &str,
1400 options: Option<StopContainerOptions>,
1401 ) -> Result<(), Error> {
1402 let url = format!("/containers/{container_name}/stop");
1403
1404 let req = self.build_request(
1405 &url,
1406 Builder::new().method(Method::POST),
1407 options,
1408 Ok(BodyType::Left(Full::new(Bytes::new()))),
1409 );
1410
1411 self.process_into_unit(req).await
1412 }
1413
1414 /// ---
1415 ///
1416 /// # Remove Container
1417 ///
1418 /// Remove a container.
1419 ///
1420 /// # Arguments
1421 ///
1422 /// - Container name as a string slice.
1423 /// - Optional [Remove Container Options](RemoveContainerOptions) struct.
1424 ///
1425 /// # Returns
1426 ///
1427 /// - unit type `()`, wrapped in a Future.
1428 ///
1429 /// # Examples
1430 ///
1431 /// ```rust
1432 /// # use bollard_next::Docker;
1433 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1434 ///
1435 /// use bollard_next::container::RemoveContainerOptions;
1436 ///
1437 /// use std::default::Default;
1438 ///
1439 /// let options = Some(RemoveContainerOptions{
1440 /// force: true,
1441 /// ..Default::default()
1442 /// });
1443 ///
1444 /// docker.remove_container("hello-world", options);
1445 /// ```
1446 pub async fn remove_container(
1447 &self,
1448 container_name: &str,
1449 options: Option<RemoveContainerOptions>,
1450 ) -> Result<(), Error> {
1451 let url = format!("/containers/{container_name}");
1452
1453 let req = self.build_request(
1454 &url,
1455 Builder::new().method(Method::DELETE),
1456 options,
1457 Ok(BodyType::Left(Full::new(Bytes::new()))),
1458 );
1459
1460 self.process_into_unit(req).await
1461 }
1462
1463 /// ---
1464 ///
1465 /// # Wait Container
1466 ///
1467 /// Wait for a container to stop. This is a non-blocking operation, the resulting stream will
1468 /// end when the container stops.
1469 ///
1470 /// # Arguments
1471 ///
1472 /// - Container name as string slice.
1473 /// - Optional [Wait Container Options](WaitContainerOptions) struct.
1474 ///
1475 /// # Returns
1476 ///
1477 /// - [ContainerWaitResponse](ContainerWaitResponse), wrapped in a
1478 /// Stream.
1479 ///
1480 /// # Examples
1481 ///
1482 /// ```rust
1483 /// # use bollard_next::Docker;
1484 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1485 ///
1486 /// use bollard_next::container::WaitContainerOptions;
1487 ///
1488 /// let options = Some(WaitContainerOptions{
1489 /// condition: "not-running",
1490 /// });
1491 ///
1492 /// docker.wait_container("hello-world", options);
1493 /// ```
1494 pub fn wait_container<T>(
1495 &self,
1496 container_name: &str,
1497 options: Option<WaitContainerOptions<T>>,
1498 ) -> impl Stream<Item = Result<ContainerWaitResponse, Error>>
1499 where
1500 T: Into<String> + Serialize,
1501 {
1502 let url = format!("/containers/{container_name}/wait");
1503
1504 let req = self.build_request(
1505 &url,
1506 Builder::new().method(Method::POST),
1507 options,
1508 Ok(BodyType::Left(Full::new(Bytes::new()))),
1509 );
1510
1511 self.process_into_stream(req).map(|res| match res {
1512 Ok(ContainerWaitResponse {
1513 status_code: code,
1514 error:
1515 Some(ContainerWaitExitError {
1516 message: Some(error),
1517 }),
1518 }) if code > 0 => Err(Error::DockerContainerWaitError { error, code }),
1519 Ok(ContainerWaitResponse {
1520 status_code: code,
1521 error: None,
1522 }) if code > 0 => Err(Error::DockerContainerWaitError {
1523 error: String::new(),
1524 code,
1525 }),
1526 v => v,
1527 })
1528 }
1529
1530 /// ---
1531 ///
1532 /// # Attach Container
1533 ///
1534 /// Attach to a container to read its output or send it input. You can attach to the
1535 /// same container multiple times and you can reattach to containers that have been detached.
1536 ///
1537 /// # Arguments
1538 ///
1539 /// - Container name as string slice.
1540 /// - Optional [Attach Container Options](AttachContainerOptions) struct.
1541 ///
1542 /// # Returns
1543 ///
1544 /// - [AttachContainerResults](AttachContainerResults) wrapped in a Future.
1545 ///
1546 /// # Examples
1547 ///
1548 /// ```rust
1549 /// # use bollard_next::Docker;
1550 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1551 ///
1552 /// use bollard_next::container::AttachContainerOptions;
1553 ///
1554 /// let options = Some(AttachContainerOptions::<String>{
1555 /// stdin: Some(true),
1556 /// stdout: Some(true),
1557 /// stderr: Some(true),
1558 /// stream: Some(true),
1559 /// logs: Some(true),
1560 /// detach_keys: Some("ctrl-c".to_string()),
1561 /// });
1562 ///
1563 /// docker.attach_container("hello-world", options);
1564 /// ```
1565 pub async fn attach_container<T>(
1566 &self,
1567 container_name: &str,
1568 options: Option<AttachContainerOptions<T>>,
1569 ) -> Result<AttachContainerResults, Error>
1570 where
1571 T: Into<String> + Serialize + Default,
1572 {
1573 let url = format!("/containers/{container_name}/attach");
1574
1575 let req = self.build_request(
1576 &url,
1577 Builder::new()
1578 .method(Method::POST)
1579 .header(CONNECTION, "Upgrade")
1580 .header(UPGRADE, "tcp"),
1581 options,
1582 Ok(BodyType::Left(Full::new(Bytes::new()))),
1583 );
1584
1585 let (read, write) = self.process_upgraded(req).await?;
1586 let log = FramedRead::new(read, NewlineLogOutputDecoder::new(true)).map_err(|e| e.into());
1587
1588 Ok(AttachContainerResults {
1589 output: Box::pin(log),
1590 input: Box::pin(write),
1591 })
1592 }
1593
1594 /// ---
1595 ///
1596 /// # Resize container tty
1597 ///
1598 /// Resize the container's TTY.
1599 ///
1600 /// # Arguments
1601 ///
1602 /// - Container name as string slice.
1603 /// - [Resize Container Tty Options](ResizeContainerTtyOptions) struct.
1604 ///
1605 /// # Examples
1606 ///
1607 /// ```rust
1608 /// # use bollard_next::Docker;
1609 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1610 ///
1611 /// use bollard_next::container::ResizeContainerTtyOptions;
1612 ///
1613 /// let options = ResizeContainerTtyOptions {
1614 /// width: 50,
1615 /// height: 20,
1616 /// };
1617 ///
1618 /// docker.resize_container_tty("hello-world", options);
1619 /// ```
1620 pub async fn resize_container_tty(
1621 &self,
1622 container_name: &str,
1623 options: ResizeContainerTtyOptions,
1624 ) -> Result<(), Error> {
1625 let url = format!("/containers/{container_name}/resize");
1626
1627 let req = self.build_request(
1628 &url,
1629 Builder::new().method(Method::POST),
1630 Some(options),
1631 Ok(BodyType::Left(Full::new(Bytes::new()))),
1632 );
1633
1634 self.process_into_unit(req).await
1635 }
1636
1637 /// ---
1638 ///
1639 /// # Restart Container
1640 ///
1641 /// Restart a container.
1642 ///
1643 /// # Arguments
1644 ///
1645 /// - Container name as string slice.
1646 /// - Optional [Restart Container Options](RestartContainerOptions) struct.
1647 ///
1648 /// # Returns
1649 ///
1650 /// - unit type `()`, wrapped in a Future.
1651 ///
1652 /// # Examples
1653 ///
1654 /// ```rust
1655 /// # use bollard_next::Docker;
1656 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1657 ///
1658 /// use bollard_next::container::RestartContainerOptions;
1659 ///
1660 /// let options = Some(RestartContainerOptions{
1661 /// t: 30,
1662 /// });
1663 ///
1664 /// docker.restart_container("postgres", options);
1665 /// ```
1666 pub async fn restart_container(
1667 &self,
1668 container_name: &str,
1669 options: Option<RestartContainerOptions>,
1670 ) -> Result<(), Error> {
1671 let url = format!("/containers/{container_name}/restart");
1672
1673 let req = self.build_request(
1674 &url,
1675 Builder::new().method(Method::POST),
1676 options,
1677 Ok(BodyType::Left(Full::new(Bytes::new()))),
1678 );
1679
1680 self.process_into_unit(req).await
1681 }
1682
1683 /// ---
1684 ///
1685 /// # Inspect Container
1686 ///
1687 /// Inspect a container.
1688 ///
1689 /// # Arguments
1690 ///
1691 /// - Container name as a string slice.
1692 /// - Optional [Inspect Container Options](InspectContainerOptions) struct.
1693 ///
1694 /// # Returns
1695 ///
1696 /// - [ContainerInspectResponse](ContainerInspectResponse), wrapped in a Future.
1697 ///
1698 /// # Examples
1699 ///
1700 /// ```rust
1701 /// # use bollard_next::Docker;
1702 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1703 /// use bollard_next::container::InspectContainerOptions;
1704 ///
1705 /// let options = Some(InspectContainerOptions{
1706 /// size: false,
1707 /// });
1708 ///
1709 /// docker.inspect_container("hello-world", options);
1710 /// ```
1711 pub async fn inspect_container(
1712 &self,
1713 container_name: &str,
1714 options: Option<InspectContainerOptions>,
1715 ) -> Result<ContainerInspectResponse, Error> {
1716 let url = format!("/containers/{container_name}/json");
1717
1718 let req = self.build_request(
1719 &url,
1720 Builder::new().method(Method::GET),
1721 options,
1722 Ok(BodyType::Left(Full::new(Bytes::new()))),
1723 );
1724
1725 self.process_into_value(req).await
1726 }
1727
1728 /// ---
1729 ///
1730 /// # Top Processes
1731 ///
1732 /// List processes running inside a container.
1733 ///
1734 /// # Arguments
1735 ///
1736 /// - Container name as string slice.
1737 /// - Optional [Top Options](TopOptions) struct.
1738 ///
1739 /// # Returns
1740 ///
1741 /// - [ContainerTopResponse](ContainerTopResponse), wrapped in a Future.
1742 ///
1743 /// # Examples
1744 ///
1745 /// ```rust
1746 /// # use bollard_next::Docker;
1747 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1748 /// use bollard_next::container::TopOptions;
1749 ///
1750 /// let options = Some(TopOptions{
1751 /// ps_args: "aux",
1752 /// });
1753 ///
1754 /// docker.top_processes("fussybeaver/uhttpd", options);
1755 /// ```
1756 pub async fn top_processes<T>(
1757 &self,
1758 container_name: &str,
1759 options: Option<TopOptions<T>>,
1760 ) -> Result<ContainerTopResponse, Error>
1761 where
1762 T: Into<String> + Serialize,
1763 {
1764 let url = format!("/containers/{container_name}/top");
1765
1766 let req = self.build_request(
1767 &url,
1768 Builder::new().method(Method::GET),
1769 options,
1770 Ok(BodyType::Left(Full::new(Bytes::new()))),
1771 );
1772
1773 self.process_into_value(req).await
1774 }
1775
1776 /// ---
1777 ///
1778 /// # Logs
1779 ///
1780 /// Get container logs.
1781 ///
1782 /// # Arguments
1783 ///
1784 /// - Container name as string slice.
1785 /// - Optional [Logs Options](LogsOptions) struct.
1786 ///
1787 /// # Returns
1788 ///
1789 /// - [Log Output](LogOutput) enum, wrapped in a
1790 /// Stream.
1791 ///
1792 /// # Examples
1793 ///
1794 /// ```rust
1795 /// # use bollard_next::Docker;
1796 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1797 ///
1798 /// use bollard_next::container::LogsOptions;
1799 ///
1800 /// use std::default::Default;
1801 ///
1802 /// let options = Some(LogsOptions::<String>{
1803 /// stdout: true,
1804 /// ..Default::default()
1805 /// });
1806 ///
1807 /// docker.logs("hello-world", options);
1808 /// ```
1809 pub fn logs<T>(
1810 &self,
1811 container_name: &str,
1812 options: Option<LogsOptions<T>>,
1813 ) -> impl Stream<Item = Result<LogOutput, Error>>
1814 where
1815 T: Into<String> + Serialize,
1816 {
1817 let url = format!("/containers/{container_name}/logs");
1818
1819 let req = self.build_request(
1820 &url,
1821 Builder::new().method(Method::GET),
1822 options,
1823 Ok(BodyType::Left(Full::new(Bytes::new()))),
1824 );
1825
1826 self.process_into_stream_string(req)
1827 }
1828
1829 /// ---
1830 ///
1831 /// # Container Changes
1832 ///
1833 /// Get changes on a container's filesystem.
1834 ///
1835 /// # Arguments
1836 ///
1837 /// - Container name as string slice.
1838 ///
1839 /// # Returns
1840 ///
1841 /// - An Option of Vector of [File System Change](FilesystemChange) structs, wrapped in a
1842 /// Future.
1843 ///
1844 /// # Examples
1845 ///
1846 /// ```rust
1847 /// # use bollard_next::Docker;
1848 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1849 ///
1850 /// docker.container_changes("hello-world");
1851 /// ```
1852 pub async fn container_changes(
1853 &self,
1854 container_name: &str,
1855 ) -> Result<Option<Vec<FilesystemChange>>, Error> {
1856 let url = format!("/containers/{container_name}/changes");
1857
1858 let req = self.build_request(
1859 &url,
1860 Builder::new().method(Method::GET),
1861 None::<String>,
1862 Ok(BodyType::Left(Full::new(Bytes::new()))),
1863 );
1864
1865 self.process_into_value(req).await
1866 }
1867
1868 /// ---
1869 ///
1870 /// # Stats
1871 ///
1872 /// Get container stats based on resource usage.
1873 ///
1874 /// # Arguments
1875 ///
1876 /// - Container name as string slice.
1877 /// - Optional [Stats Options](StatsOptions) struct.
1878 ///
1879 /// # Returns
1880 ///
1881 /// - [Stats](Stats) struct, wrapped in a
1882 /// Stream.
1883 ///
1884 /// # Examples
1885 ///
1886 /// ```rust
1887 /// # use bollard_next::Docker;
1888 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1889 ///
1890 /// use bollard_next::container::StatsOptions;
1891 ///
1892 /// let options = Some(StatsOptions{
1893 /// stream: false,
1894 /// one_shot: true,
1895 /// });
1896 ///
1897 /// docker.stats("hello-world", options);
1898 /// ```
1899 pub fn stats(
1900 &self,
1901 container_name: &str,
1902 options: Option<StatsOptions>,
1903 ) -> impl Stream<Item = Result<Stats, Error>> {
1904 let url = format!("/containers/{container_name}/stats");
1905
1906 let req = self.build_request(
1907 &url,
1908 Builder::new().method(Method::GET),
1909 options,
1910 Ok(BodyType::Left(Full::new(Bytes::new()))),
1911 );
1912
1913 self.process_into_stream(req)
1914 }
1915
1916 /// ---
1917 ///
1918 /// # Kill Container
1919 ///
1920 /// Kill a container.
1921 ///
1922 /// # Arguments
1923 ///
1924 /// - Container name as string slice.
1925 /// - Optional [Kill Container Options](KillContainerOptions) struct.
1926 ///
1927 /// # Returns
1928 ///
1929 /// - unit type `()`, wrapped in a Future.
1930 ///
1931 /// # Examples
1932 ///
1933 /// ```rust
1934 /// # use bollard_next::Docker;
1935 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1936 ///
1937 /// use bollard_next::container::KillContainerOptions;
1938 ///
1939 /// let options = Some(KillContainerOptions{
1940 /// signal: "SIGINT",
1941 /// });
1942 ///
1943 /// docker.kill_container("postgres", options);
1944 /// ```
1945 pub async fn kill_container<T>(
1946 &self,
1947 container_name: &str,
1948 options: Option<KillContainerOptions<T>>,
1949 ) -> Result<(), Error>
1950 where
1951 T: Into<String> + Serialize,
1952 {
1953 let url = format!("/containers/{container_name}/kill");
1954
1955 let req = self.build_request(
1956 &url,
1957 Builder::new().method(Method::POST),
1958 options,
1959 Ok(BodyType::Left(Full::new(Bytes::new()))),
1960 );
1961
1962 self.process_into_unit(req).await
1963 }
1964
1965 /// ---
1966 ///
1967 /// # Update Container
1968 ///
1969 /// Update a container.
1970 ///
1971 /// # Arguments
1972 ///
1973 /// - Container name as string slice.
1974 /// - [Update Container Options](UpdateContainerOptions) struct.
1975 ///
1976 /// # Returns
1977 ///
1978 /// - unit type `()`, wrapped in a Future.
1979 ///
1980 /// # Examples
1981 ///
1982 /// ```rust
1983 /// # use bollard_next::Docker;
1984 /// # let docker = Docker::connect_with_http_defaults().unwrap();
1985 ///
1986 /// use bollard_next::container::UpdateContainerOptions;
1987 /// use std::default::Default;
1988 ///
1989 /// let config = UpdateContainerOptions::<String> {
1990 /// memory: Some(314572800),
1991 /// memory_swap: Some(314572800),
1992 /// ..Default::default()
1993 /// };
1994 ///
1995 /// docker.update_container("postgres", config);
1996 /// ```
1997 pub async fn update_container<T>(
1998 &self,
1999 container_name: &str,
2000 config: UpdateContainerOptions<T>,
2001 ) -> Result<(), Error>
2002 where
2003 T: Into<String> + Eq + Hash + Serialize,
2004 {
2005 let url = format!("/containers/{container_name}/update");
2006
2007 let req = self.build_request(
2008 &url,
2009 Builder::new().method(Method::POST),
2010 None::<String>,
2011 Docker::serialize_payload(Some(config)),
2012 );
2013
2014 self.process_into_unit(req).await
2015 }
2016
2017 /// ---
2018 ///
2019 /// # Rename Container
2020 ///
2021 /// Rename a container.
2022 ///
2023 /// # Arguments
2024 ///
2025 /// - Container name as string slice.
2026 /// - [Rename Container Options](RenameContainerOptions) struct
2027 ///
2028 /// # Returns
2029 ///
2030 /// - unit type `()`, wrapped in a Future.
2031 ///
2032 /// # Examples
2033 ///
2034 /// ```rust
2035 /// # use bollard_next::Docker;
2036 /// # let docker = Docker::connect_with_http_defaults().unwrap();
2037 ///
2038 /// use bollard_next::container::RenameContainerOptions;
2039 ///
2040 /// let required = RenameContainerOptions {
2041 /// name: "my_new_container_name"
2042 /// };
2043 ///
2044 /// docker.rename_container("hello-world", required);
2045 /// ```
2046 pub async fn rename_container<T>(
2047 &self,
2048 container_name: &str,
2049 options: RenameContainerOptions<T>,
2050 ) -> Result<(), Error>
2051 where
2052 T: Into<String> + Serialize,
2053 {
2054 let url = format!("/containers/{container_name}/rename");
2055
2056 let req = self.build_request(
2057 &url,
2058 Builder::new().method(Method::POST),
2059 Some(options),
2060 Ok(BodyType::Left(Full::new(Bytes::new()))),
2061 );
2062
2063 self.process_into_unit(req).await
2064 }
2065
2066 /// ---
2067 ///
2068 /// # Pause Container
2069 ///
2070 /// Use the cgroups freezer to suspend all processes in a container.
2071 ///
2072 /// # Arguments
2073 ///
2074 /// - Container name as a string slice.
2075 ///
2076 /// # Returns
2077 ///
2078 /// - unit type `()`, wrapped in a Future.
2079 ///
2080 /// # Examples
2081 ///
2082 /// ```rust
2083 /// # use bollard_next::Docker;
2084 /// # let docker = Docker::connect_with_http_defaults().unwrap();
2085 ///
2086 /// docker.pause_container("postgres");
2087 /// ```
2088 pub async fn pause_container(&self, container_name: &str) -> Result<(), Error> {
2089 let url = format!("/containers/{container_name}/pause");
2090
2091 let req = self.build_request(
2092 &url,
2093 Builder::new().method(Method::POST),
2094 None::<String>,
2095 Ok(BodyType::Left(Full::new(Bytes::new()))),
2096 );
2097
2098 self.process_into_unit(req).await
2099 }
2100
2101 /// ---
2102 ///
2103 /// # Unpause Container
2104 ///
2105 /// Resume a container which has been paused.
2106 ///
2107 /// # Arguments
2108 ///
2109 /// - Container name as a string slice.
2110 ///
2111 /// # Returns
2112 ///
2113 /// - unit type `()`, wrapped in a Future.
2114 ///
2115 /// # Examples
2116 ///
2117 /// ```rust
2118 /// # use bollard_next::Docker;
2119 /// # let docker = Docker::connect_with_http_defaults().unwrap();
2120 ///
2121 /// docker.unpause_container("postgres");
2122 /// ```
2123 pub async fn unpause_container(&self, container_name: &str) -> Result<(), Error> {
2124 let url = format!("/containers/{container_name}/unpause");
2125
2126 let req = self.build_request(
2127 &url,
2128 Builder::new().method(Method::POST),
2129 None::<String>,
2130 Ok(BodyType::Left(Full::new(Bytes::new()))),
2131 );
2132
2133 self.process_into_unit(req).await
2134 }
2135
2136 /// ---
2137 ///
2138 /// # Prune Containers
2139 ///
2140 /// Delete stopped containers.
2141 ///
2142 /// # Arguments
2143 ///
2144 /// - Optional [Prune Containers Options](PruneContainersOptions) struct.
2145 ///
2146 /// # Returns
2147 ///
2148 /// - [Container Prune Response](ContainerPruneResponse) struct, wrapped in a Future.
2149 ///
2150 /// # Examples
2151 ///
2152 /// ```rust
2153 /// # use bollard_next::Docker;
2154 /// # let docker = Docker::connect_with_http_defaults().unwrap();
2155 /// use bollard_next::container::PruneContainersOptions;
2156 ///
2157 /// use std::collections::HashMap;
2158 ///
2159 /// let mut filters = HashMap::new();
2160 /// filters.insert("until", vec!["10m"]);
2161 ///
2162 /// let options = Some(PruneContainersOptions{
2163 /// filters
2164 /// });
2165 ///
2166 /// docker.prune_containers(options);
2167 /// ```
2168 pub async fn prune_containers<T>(
2169 &self,
2170 options: Option<PruneContainersOptions<T>>,
2171 ) -> Result<ContainerPruneResponse, Error>
2172 where
2173 T: Into<String> + Eq + Hash + Serialize,
2174 {
2175 let url = "/containers/prune";
2176
2177 let req = self.build_request(
2178 url,
2179 Builder::new().method(Method::POST),
2180 options,
2181 Ok(BodyType::Left(Full::new(Bytes::new()))),
2182 );
2183
2184 self.process_into_value(req).await
2185 }
2186
2187 /// ---
2188 ///
2189 /// # Stream Upload To Container
2190 ///
2191 /// Stream an upload of a tar archive to be extracted to a path in the filesystem of container
2192 /// id.
2193 ///
2194 /// # Arguments
2195 ///
2196 /// - Optional [Upload To Container Options](UploadToContainerOptions) struct.
2197 ///
2198 /// # Returns
2199 ///
2200 /// - unit type `()`, wrapped in a Future.
2201 ///
2202 /// # Examples
2203 ///
2204 /// ```rust,no_run
2205 /// # use bollard::Docker;
2206 /// use bollard::container::UploadToContainerOptions;
2207 /// use futures_util::{StreamExt, TryFutureExt};
2208 /// use tokio::fs::File;
2209 /// use tokio_util::io::ReaderStream;
2210 ///
2211 /// # #[tokio::main]
2212 /// # async fn main() {
2213 /// # let docker = Docker::connect_with_http_defaults().unwrap();
2214 /// let options = Some(UploadToContainerOptions{
2215 /// path: "/opt",
2216 /// ..Default::default()
2217 /// });
2218 ///
2219 /// let file = File::open("tarball.tar.gz")
2220 /// .map_ok(ReaderStream::new)
2221 /// .try_flatten_stream()
2222 /// .map(|x|x.expect("failed to stream file"));
2223 ///
2224 /// docker
2225 /// .upload_to_container_streaming("my-container", options, file)
2226 /// .await
2227 /// .expect("upload failed");
2228 /// # }
2229 /// ```
2230 pub async fn upload_to_container_streaming<T>(
2231 &self,
2232 container_name: &str,
2233 options: Option<UploadToContainerOptions<T>>,
2234 tar: impl Stream<Item = Bytes> + Send + 'static,
2235 ) -> Result<(), Error>
2236 where
2237 T: Into<String> + Serialize,
2238 {
2239 let url = format!("/containers/{container_name}/archive");
2240
2241 let req = self.build_request(
2242 &url,
2243 Builder::new()
2244 .method(Method::PUT)
2245 .header(CONTENT_TYPE, "application/x-tar"),
2246 options,
2247 Ok(body_stream(tar)),
2248 );
2249
2250 self.process_into_unit(req).await
2251 }
2252
2253 /// ---
2254 ///
2255 /// # Upload To Container
2256 ///
2257 /// Upload a tar archive to be extracted to a path in the filesystem of container id.
2258 ///
2259 /// # Arguments
2260 ///
2261 /// - Optional [Upload To Container Options](UploadToContainerOptions) struct.
2262 ///
2263 /// # Returns
2264 ///
2265 /// - unit type `()`, wrapped in a Future.
2266 ///
2267 /// # Examples
2268 ///
2269 /// ```rust,no_run
2270 /// # use bollard::Docker;
2271 /// use bollard::container::UploadToContainerOptions;
2272 /// use std::fs::File;
2273 /// use std::io::Read;
2274 ///
2275 /// # #[tokio::main]
2276 /// # async fn main() {
2277 /// # let docker = Docker::connect_with_http_defaults().unwrap();
2278 /// let options = Some(UploadToContainerOptions{
2279 /// path: "/opt",
2280 /// ..Default::default()
2281 /// });
2282 ///
2283 /// let mut file = File::open("tarball.tar.gz").unwrap();
2284 /// let mut contents = Vec::new();
2285 /// file.read_to_end(&mut contents).unwrap();
2286 ///
2287 /// docker
2288 /// .upload_to_container("my-container", options, contents.into())
2289 /// .await
2290 /// .expect("upload failed");
2291 /// # }
2292 /// ```
2293 pub async fn upload_to_container<T>(
2294 &self,
2295 container_name: &str,
2296 options: Option<UploadToContainerOptions<T>>,
2297 tar: Bytes,
2298 ) -> Result<(), Error>
2299 where
2300 T: Into<String> + Serialize,
2301 {
2302 let url = format!("/containers/{container_name}/archive");
2303
2304 let req = self.build_request(
2305 &url,
2306 Builder::new()
2307 .method(Method::PUT)
2308 .header(CONTENT_TYPE, "application/x-tar"),
2309 options,
2310 Ok(BodyType::Left(Full::new(tar))),
2311 );
2312
2313 self.process_into_unit(req).await
2314 }
2315
2316 /// ---
2317 ///
2318 /// # Download From Container
2319 ///
2320 /// Get a tar archive of a resource in the filesystem of container id.
2321 ///
2322 /// # Arguments
2323 ///
2324 /// - [Download From Container Options](DownloadFromContainerOptions) struct.
2325 ///
2326 /// # Returns
2327 ///
2328 /// - Tar archive compressed with one of the following algorithms: identity (no compression),
2329 /// gzip, bzip2, xz. [Hyper Body](hyper::body::Body).
2330 ///
2331 /// # Examples
2332 ///
2333 /// ```rust
2334 /// # use bollard_next::Docker;
2335 /// # let docker = Docker::connect_with_http_defaults().unwrap();
2336 /// use bollard_next::container::DownloadFromContainerOptions;
2337 ///
2338 /// let options = Some(DownloadFromContainerOptions{
2339 /// path: "/opt",
2340 /// });
2341 ///
2342 /// docker.download_from_container("my-container", options);
2343 /// ```
2344 pub fn download_from_container<T>(
2345 &self,
2346 container_name: &str,
2347 options: Option<DownloadFromContainerOptions<T>>,
2348 ) -> impl Stream<Item = Result<Bytes, Error>>
2349 where
2350 T: Into<String> + Serialize,
2351 {
2352 let url = format!("/containers/{container_name}/archive");
2353
2354 let req = self.build_request(
2355 &url,
2356 Builder::new().method(Method::GET),
2357 options,
2358 Ok(BodyType::Left(Full::new(Bytes::new()))),
2359 );
2360
2361 self.process_into_body(req)
2362 }
2363
2364 /// ---
2365 ///
2366 /// # Export Container
2367 ///
2368 /// Get a tarball containing the filesystem contents of a container.
2369 ///
2370 /// See the [Docker API documentation](https://docs.docker.com/engine/api/v1.40/#operation/ContainerExport)
2371 /// for more information.
2372 /// # Arguments
2373 /// - The `container_name` string referring to an individual container
2374 ///
2375 /// # Returns
2376 /// - An uncompressed TAR archive
2377 pub fn export_container(
2378 &self,
2379 container_name: &str,
2380 ) -> impl Stream<Item = Result<Bytes, Error>> {
2381 let url = format!("/containers/{container_name}/export");
2382 let req = self.build_request(
2383 &url,
2384 Builder::new()
2385 .method(Method::GET)
2386 .header(CONTENT_TYPE, "application/json"),
2387 None::<String>,
2388 Ok(BodyType::Left(Full::new(Bytes::new()))),
2389 );
2390 self.process_into_body(req)
2391 }
2392}
2393
2394#[cfg(not(windows))]
2395#[cfg(test)]
2396mod tests {
2397
2398 use futures_util::TryStreamExt;
2399 use yup_hyper_mock::HostToReplyConnector;
2400
2401 use crate::{Docker, API_DEFAULT_VERSION};
2402
2403 use super::WaitContainerOptions;
2404
2405 #[tokio::test]
2406 async fn test_container_wait_with_error() {
2407 let mut connector = HostToReplyConnector::default();
2408 connector.m.insert(
2409 String::from("http://127.0.0.1"),
2410 "HTTP/1.1 200 OK\r\nServer:mock1\r\nContent-Type:application/json\r\n\r\n{\"Error\":null,\"StatusCode\":1}".to_string(),
2411 );
2412
2413 let docker =
2414 Docker::connect_with_mock(connector, "127.0.0.1".to_string(), 5, API_DEFAULT_VERSION)
2415 .unwrap();
2416
2417 let result = &docker
2418 .wait_container("wait_container_test", None::<WaitContainerOptions<String>>)
2419 .try_collect::<Vec<_>>()
2420 .await;
2421
2422 assert!(matches!(
2423 result,
2424 Err(crate::errors::Error::DockerContainerWaitError { code: _, error: _ })
2425 ));
2426 }
2427}