rustainers 0.15.1

A simple, opinionated way to run containers for tests.
Documentation
# Runnable images

This module contains runnable images that can be started by a [`Runner`](crate::runner::Runner).

These images implements the [`ToRunnableContainer`](crate::ToRunnableContainer) trait.

## Create a custom runnable image

A runnable image should implement the [`ToRunnableContainer`](crate::ToRunnableContainer) trait.

```rust, no_run
use std::fmt::Display;

use rustainers::runner::{RunOption, Runner};
use rustainers::{
    ExposedPort, HealthCheck, RunnableContainer, RunnableContainerBuilder, Port, ToRunnableContainer,
    ImageName,
};

// Declare the image as a constant.
// You can provide a tag or a digest if you want.
const NGINX_IMAGE: &ImageName = &ImageName::new("docker.io/nginx");

const PORT: u16 = 80;

/// The NGinx image
#[derive(Debug)]
struct Nginx {
    /// The image name
    image: ImageName,
    /// The exposed port
    port: ExposedPort,
}

// Provide an easy way to create the image instance
impl Default for Nginx {
    fn default() -> Self {
        Self {
            image: NGINX_IMAGE.clone(),
            port: ExposedPort::new(PORT), // the container port
        }
    }
}

// You had to implement the `ToRunnableContainer` trait
impl ToRunnableContainer for Nginx {

    fn to_runnable(&self, builder: RunnableContainerBuilder) -> RunnableContainer {
        builder
            // provide the image
            .with_image(self.image.clone())
            // strategy to check when container is ready
            .with_wait_strategy(
                // here a `curl` is enough
                // Note that this command is executed in the container
                // therefore you need to have the `curl` command available in the container
                HealthCheck::builder()
                    .with_command("curl -sf http://127.0.0.1") //DevSkim: ignore DS137138
                    .build(),
            )
            // ports mapping
            // bound a random port available port of the host to the container `80` port
            .with_port_mappings([self.port.clone()])
            .build()
    }
}
```

NOTE that you can also use another waiting strategy here: `.with_wait_strategy(WaitStrategy::http("/"))`

⚠️ WARNING: when you use an `ExposedPort`, do not make your image clonable.
The `ExposedPort` use [__Interior mutability__](https://doc.rust-lang.org/reference/interior-mutability.html).
If you clone this exposed port, it will not create a new unassign port, but share the same one.
If you really need the `Clone`, implement the trait manually with creating new `ExposedPort` instead of clone it.