shiplift

repository·master·Indexed 20 days ago

https://github.com/softprops/shiplift

A Rust interface for maneuvering Docker containers, providing programmatic access to Docker operations. Version 0.7.0 allows users to manage container lifecycles, stream logs, attach to TTYs, and move files between the host and container filesystem. It provides specialized interfaces for images, services, networks, and volumes, and supports connection via Unix sockets or TCP/Host URIs.

Tokens
11.7K
Snippets
45
Records
53
Agent score
21%

What's inside shiplift

  1. Explore shiplift usage examples

    master
    For practical implementations and runnable code patterns, refer to the official examples directory in the repository. These examples demonstrate how to interact with the Docker API using the shiplift crate.
  2. Understand ImageBuildChunk response types

    master

    Operations that involve long-running processes like build, pull, or import return a stream of ImageBuildChunk items. These chunks represent the progress or status of the operation.

    Variants of ImageBuildChunk:

    • Update { stream: String }: A line of text from the process output.
    • Error { error: String, error_detail: ErrorDetail }: An error occurred during the operation.
    • Digest { aux: Aux }: The operation completed successfully, providing the image ID.
    • PullStatus { status: String, id: Option<String>, progress: Option<String>, progress_detail: Option<ProgressDetail }: Status updates for pull operations.
  3. Understand container resource and host configuration

    master

    The HostConfig struct defines the resource constraints and host-level settings for a container.

    Key configuration areas:

    • Resources: cpu_shares, memory, nano_cpus, pids_limit, and memory_swappiness.
    • Networking: network_mode, port_bindings (via PortMap), and dns settings.
    • Storage: binds, mounts, volumes_from, and tmpfs.
    • Security: privileged, cap_add, cap_drop, security_opt, and user.
    • Lifecycle: restart_policy and auto_remove.
  4. Manage Docker Swarm services with the Services API

    master

    The Services struct provides an interface to interact with the collection of services on a Docker host. You can use it to list all services or retrieve a handle to a specific named service using .get(name).

    To use it, initialize it with a reference to a Docker instance.

    let services = Services::new(&docker);
    
    // List all services
    let list = services.list(&ServiceListOptions::builder().build()).await?;
    
    // Get a handle to a specific service
    let service = services.get("my-service-name");
  5. Initialize Shiplift with Docker::new()

    master

    To start using Shiplift, create a new Docker instance using Docker::new(). This instance serves as the entry point for interacting with the Docker daemon via various sub-modules like images(), containers(), networks(), etc. Most operations are asynchronous and return a Result.

    # async {
    let docker = shiplift::Docker::new();
    
    match docker.images().list(&Default::default()).await {
        Ok(images) => {
            for image in images {
                println!("{:?}", image.repo_tags);
            }
        },
        Err(e) => eprintln!("Something bad happened! {}", e),
    }
    # };
  6. Initialize a Docker client

    master

    You can create a Docker client instance using several methods depending on your connection requirements:

    1. Automatic detection: Docker::new() looks for the DOCKER_HOST environment variable. If not set, it defaults to the Unix socket at /var/run/docker.sock (requires the unix-socket feature).
    2. Unix Socket: Use Docker::unix(path) to connect to a specific Unix socket path.
    3. TCP/Host URL: Use Docker::host(uri) to connect to a specific host via a Uri object.

    If the tls feature is enabled, Docker will automatically attempt to use TLS certificates if the DOCKER_CERT_PATH environment variable is set.

    ```rust
    // Using default (DOCKER_HOST or /var/run/docker.sock)
    let docker = Docker::new();
    
    // Using a specific Unix socket
    let docker = Docker::unix("/tmp/docker.sock");
    
    // Using a specific host URI
    let uri = Uri::new("tcp", "localhost", Some(2375));
    let docker = Docker::host(uri);
    ```埋
  7. Create and run commands in a container using Exec

    master

    To run a command inside an existing container, you must first create an Exec instance and then start it.

    1. Create: Use Exec::create with a container_id and ExecContainerOptions to initialize the execution context.
    2. Start: Call .start() on the returned Exec instance to receive a multiplexed TTY stream of the command's output.

    Alternatively, if you want to perform both steps in a single flow, the internal create_and_start method (not directly exposed to end-users in the public API, but following the same logic) combines these to avoid lifetime issues with the container ID and options.

    // 1. Build options
    let opts = ExecContainerOptions::builder()
        .cmd(vec!["ls", "/tmp"])
        .attach_stdout(true)
        .attach_stderr(true)
        .build();
    
    // 2. Create the exec instance
    let exec = Exec::create(&docker, "container_id_here", &opts).await?;
    
    // 3. Start and process the stream
    let mut stream = exec.start();
    while let Some(chunk) = stream.next().await {
        let chunk = chunk?;
        // handle tty::TtyChunk
    }
  8. Perform operations on a specific Network instance

    master

    Once you have a Network instance (obtained via Networks::get(id) or from NetworkCreateInfo), you can manipulate that specific network:

    • inspect(): Returns NetworkDetails for the network.
    • delete(): Removes the network.
    • connect(&ContainerConnectionOptions): Attaches a container to the network.
    • disconnect(&ContainerConnectionOptions): Detaches a container from the network.
    let network = networks.get("network-id");
    
    // Inspect details
    let details = network.inspect().await?;
    
    // Connect a container
    let conn_opts = ContainerConnectionOptions::builder("container-id")
        .aliases(vec!["web-server"])
        .build();
    network.connect(&conn_opts).await?;
    
    // Delete the network
    network.delete().await?;
  9. Configure image tagging with TagOptionsBuilder

    master

    Use TagOptions::builder() to configure how an existing image is tagged.

    Available configuration methods:

    • repo(r): The repository name to tag the image with.
    • tag(t): The tag to apply.
    let opts = TagOptions::builder()
        .repo("my-org/my-image")
        .tag("v1.2.3")
        .build();
    
    image.tag(&opts).await?;
  10. Stream Docker events with filters

    master

    The events() method returns a stream of Event objects. You can filter these events using EventsOptions constructed via the EventsOptionsBuilder.

    Filtering Options

    Use the filter() method on the builder to apply various filters:

    • EventFilter::Container(id)
    • EventFilter::Image(id)
    • EventFilter::Volume(id)
    • EventFilter::Network(id)
    • EventFilter::Daemon(id)
    • EventFilter::Label(label)
    • EventFilter::Type(type) (e.g., Container, Image, Volume, Network, Daemon)

    You can also filter by time using .since(timestamp) and .until(timestamp).

    Example

    let mut builder = EventsOptionsBuilder::default();
    builder.filter(vec![ 
        EventFilter::Type(EventFilterType::Container), 
        EventFilter::Label("status=running".to_string()) 
    ]);
    
    let opts = builder.build();
    let mut event_stream = docker.events(&opts);
    
    while let Some(event) = event_stream.next().await {
        let event = event?;
        println!("Event: {} on {}", event.action, event.actor.id);
    }
    ```rust
    let mut builder = EventsOptionsBuilder::default();
    builder.filter(vec![ 
        EventFilter::Type(EventFilterType::Container), 
        EventFilter::Label("status=running".to_string()) 
    ]);
    
    let opts = builder.build();
    let mut event_stream = docker.events(&opts);
    
    while let Some(event) = event_stream.next().await {
        let event = event?;
        println!("Event: {} on {}", event.action, event.actor.id);
    }
    ```埋
  11. Create a new network with NetworkCreateOptionsBuilder

    master

    Use NetworkCreateOptions::builder(name) to configure a new network before creation. The builder pattern allows you to specify the driver and labels.

    Available builder methods:

    • driver(name: &str): Sets the network driver (e.g., "bridge", "overlay").
    • label(labels: HashMap<String, String>): Sets metadata labels for the network.
    • build(): Finalizes the options.
    let mut labels = HashMap::new();
    labels.insert("environment".to_string(), "production".to_string());
    
    let opts = NetworkCreateOptions::builder("prod-net")
        .driver("bridge")
        .label(labels)
        .build();