Small experiments in writing Rust programs that work in a "Cloud Native" way, mainly containers, Kubernetes, Docker, and serverless (AWS Lambda).
- Basic Container
- Basic Container Alpine
- Basic Container Scratch
- Workspace Multiple Containers
- Workspace Cargo Make
- Workspace Cargo Chef
- Cargo Chef Scratch
Simple multi-stage build to create a small (79Mb!) container with a "Hello, World" application. Uses Debian Bookworm slim for both building and running.
To build:
cd basic-container
docker build --rm -t keithsharp/basic-container .
To run:
docker run -ti --rm keithsharp/basic-container
Simple multi-stage build to create a smaller (12Mb) container with a "Hello, World" application. Uses Alpine 3.18 for both building and running.
To build:
cd basic-container-alpine
docker build --rm -t keithsharp/basic-container-alpine .
To run:
docker run -ti --rm keithsharp/basic-container-alpine
Simple multi-stage build to create a tiny (4.5Mb) container with a "Hello, World" application. Uses Alpine 3.18 for building and Scratch for running.
To build:
cd basic-container-scratch
docker build --rm -t keithsharp/basic-container-scratch .
To run:
docker run -ti --rm keithsharp/basic-container-scratch
A cargo workspace containing two binary crates (one
and two
). The Dockerfile builds both crates as static binaries with each binary being copied into a separate from Scratch container. The code is based on this Stack Overflow answer.
To build:
cd workspace-multiple-containers
docker build --rm --target one .
docker build --rm --target two .
If you do a docker image ls
you'll see that you have two new containers that are untagged. What we now need to do is tag the containers by filtering on the labels we assigned in the Dockerfile:
docker tag $(docker image ls -q --filter=dangling=true --filter=label=service=one) keithsharp/workspace-one
docker tag $(docker image ls -q --filter=dangling=true --filter=label=service=two) keithsharp/workspace-two
You can then run each container separately:
docker run -ti --rm keithsharp/workspace-one
docker run -ti --rm keithsharp/workspace-two
Builds on the Workspace Multiple Containers example to use Cargo Make to automate the building and tagging of the containers.
To install Cargo Make:
cargo install --force cargo-make
To build and tag a single container:
cargo make build-one
Because I've configured [tasks.default]
alias, you can build and tag both containers:
cargo make
Or, more explicitly relying on the [tasks.build]
alias:
cargo make build
Run the containers as previously (or you could add another task):
docker run -ti --rm keithsharp/workspace-one
docker run -ti --rm keithsharp/workspace-two
Note Each of the tasks has
workspace = false
set so that the tasks only run at the workspace level and not for each member. This is necessary because you might be defining things like dependencies in the workspaceCargo.toml
which are referenced from the memberCargo.toml
, so build at the member level without the workspace will fail. See the documentation for more details.
Builds on the Workspace Cargo Make example to use Cargo Chef to create a cached layer of the compiled version of all of the projects dependencies, speeding up repeated builds.
The magic is in the invocations of cargo chef planner ...
and cargo chef cook ...
in the Dockerfile.
Building is exactly the same:
cargo make build
To run the containers:
docker run -ti --rm keithsharp/chef-one
docker run -ti --rm keithsharp/chef-two
Note I've switched back to using
rust:slim-bookworm
to build anddebian:bookworm-slim
to run, this is to avoid having to complicate theDockerfile
with building and linking a static versions of OpenSSL which is a requirement of reqwest.
This workspace is an update to Workspace Cargo Chef where the final containers are based on Scratch
and are only 11.3Mb and 7.7Mb in size. To make this work I changed the Cargo.toml
file for crate two
so that Reqwest now uses rustls
rather than native TLS (usually OpenSSL).
I then needed to add a couple of lines to the top of the Dockerfile to get cross-compilation from Debian to MUSL/Alpine working:
RUN apt-get update && apt-get install -y musl-tools
RUN rustup target add x86_64-unknown-linux-musl
With these lines in place I could add --target=x86_64-unknown-linux-musl
to cargo chef cook ...
and cargo build ...
. I think that you could also use rust:alpine3.18
as the base build container, but you would need to use RUN apk add musl-dev
to install the MUSL tools.
Building and running remains the same as before:
cargo make build
To run the containers:
docker run -ti --rm keithsharp/chef-one
docker run -ti --rm keithsharp/chef-two
Copyright 2023, Keith Sharp, kms@passback.co.uk.
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.