cargo-wharf-frontend
- BuildKit frontend for Rust
Almost simple as it is:
docker build -f Cargo.toml .
Although, extra one-time setup has to be made before the build.
Make sure BuildKit is enabled
Add the frontend directive
Create a builder image config
Create an output image config
Specify binaries
The possibility to build crates without Dockerfile is only possible thanks to BuildKit external frontends feature.
As for Docker v19.03.3 , BuildKit can be enabled just by setting DOCKER_BUILDKIT=1
env variable when running docker build
.
To instruct BuildKit to use the frontend, the first line of the Cargo.toml
should be:
# syntax = denzp/cargo-wharf-frontend:v0.1.0-alpha.2
The builder image is an image that contains Rust toolchain and any extra tools that might be needed to build the crate.
Configuration is made with a [package.metadata.wharf.builder]
metadata in Cargo.toml
.
The semantics of the metadata loosely tries to follow Dockerfile
directives.
Real life examples can be found here and there .
Base image
Key
package.metadata.wharf.builder.image
Data type
String
Description
Builder base image that contains Rust.
Dockerfile
counterpart
FROM
[package .metadata .wharf .builder ]
image = " rust"
Setup commands
Key
package.metadata.wharf.builder.setup-commands
Data type
Option<Vec<CustomCommand>>
Description
Execute commands to setup the builder image.
Dockerfile
counterpart
RUN
[package .metadata .wharf .builder ]
image = " rust"
setup-commands = [
{ shell = " apt-get update && apt-get install -y adb" },
{ command = [" apt-get" , " install" , " -y" , " ffmpeg" ], display = " Install ffmpeg" },
]
User
Key
package.metadata.wharf.builder.user
Data type
Option<String>
Description
User which runs rustc
and build scripts.
Dockerfile
counterpart
USER
[package .metadata .wharf .builder ]
image = " rust"
user = " root"
Environment variables
Key
package.metadata.wharf.builder.env
Data type
Option<BTreeMap<String, String>>
Description
Environment to run the rustc
and build scripts.
Dockerfile
counterpart
ENV
[package .metadata .wharf .builder ]
image = " rust"
env = { NAME_1 = " VALUE_1" }
[package .metadata .wharf .builder ]
image = " rust"
[package .metadata .wharf .builder .env ]
"NAME 1" = " VALUE 1"
Build target
Key
package.metadata.wharf.builder.target
Data type
Option<String>
Description
Output target: similar to cargo build --target <TARGET_NAME>
Dockerfile
counterpart
-
[package .metadata .wharf .builder ]
image = " clux/muslrust:nightly-2019-09-28"
target = " x86_64-unknown-linux-musl"
The output image is a base where compiled binaries will be put, and tests will run.
There are no restrictions on which image should be used.
Configuration is made with a [package.metadata.wharf.output]
metadata in Cargo.toml
.
The semantics of the metadata tries to follow Dockerfile
directives.
Real life examples can be found here and there .
Base image
Key
package.metadata.wharf.output.image
Data type
String
Description
Base for the output image.
Dockerfile
counterpart
FROM
[package .metadata .wharf .output ]
image = " debian:stable-slim"
[package .metadata .wharf .output ]
image = " scratch"
Pre-install commands
Key
package.metadata.wharf.output.pre-install-commands
Data type
Option<Vec<CustomCommand>>
Description
Execute commands in the output image before the binaries are copied.
Dockerfile
counterpart
RUN
[package .metadata .wharf .output ]
image = " debian"
pre-install-commands = [
{ shell = " apt-get update && apt-get install -y adb" , display = " My custom shell command" },
{ command = [" apt-get" , " install" , " -y" , " ffmpeg" ], display = " My custom command" },
]
Post-install commands
Key
package.metadata.wharf.output.post-install-commands
Data type
Option<Vec<CustomCommand>>
Description
Execute commands in the output image after the binaries were copied.
Dockerfile
counterpart
RUN
[package .metadata .wharf .output ]
image = " debian"
post-install-commands = [
{ shell = " ldd my-binary-1 | grep -qzv 'not found'" , display = " Check shared deps" },
]
User
Key
package.metadata.wharf.output.user
Data type
Option<String>
Description
User which runs the entrypoint.
Dockerfile
counterpart
USER
[package .metadata .wharf .output ]
image = " scratch"
user = " root"
Working directory
Key
package.metadata.wharf.output.workdir
Data type
Option<PathBuf>
Description
Working directory to run the entrypoint.
Dockerfile
counterpart
WORKDIR
[package .metadata .wharf .output ]
image = " debian:stable-slim"
workdir = " /tmp"
Entrypoint
Key
package.metadata.wharf.output.entrypoint
Data type
Option<Vec<String>>
Description
Path and arguments for the container entrypoint.
Dockerfile
counterpart
ENTRYPOINT
[package .metadata .wharf .output ]
image = " debian:stable-slim"
entrypoint = [" /bin/sh" , " -c" ]
Additional arguments
Key
package.metadata.wharf.output.args
Data type
Option<Vec<String>>
Description
Default extra arguments for the entrypoint.
Dockerfile
counterpart
CMD
[package .metadata .wharf .output ]
image = " debian:stable-slim"
entrypoint = [" /bin/echo" , " hello" ]
args = [" world" ]
Environment variables
Key
package.metadata.wharf.output.env
Data type
Option<BTreeMap<String, String>>
Description
Environment variables to run the entrypoint with.
Dockerfile
counterpart
ENV
[package .metadata .wharf .output ]
image = " scratch"
env = { NAME_1 = " VALUE_1" }
[package .metadata .wharf .output ]
image = " scratch"
[package .metadata .wharf .output .env ]
"NAME 1" = " VALUE 1"
Volumes
Key
package.metadata.wharf.output.volumes
Data type
Option<Vec<PathBuf>>
Description
Pathes to the mount points of container volumes.
Dockerfile
counterpart
VOLUME
[package .metadata .wharf .output ]
image = " scratch"
volumes = [" /local" , " /data" ]
Exposed ports
Key
package.metadata.wharf.output.expose
Data type
Option<Vec<ExposedPort>>
Description
Announce which ports will be listened.
Dockerfile
counterpart
EXPOSE
[package .metadata .wharf .output ]
image = " scratch"
expose = [" 3500/tcp" , " 3600/udp" , " 3700" ]
Labels
Key
package.metadata.wharf.output.labels
Data type
Option<BTreeMap<String, String>>
Description
Labels the output images should be annotated with.
Dockerfile
counterpart
LABEL
[package .metadata .wharf .output ]
image = " scratch"
[package .metadata .wharf .output .labels ]
"simple-label" = " simple value"
"my.awesome.label" = " another value"
Stop signal
Key
package.metadata.wharf.output.stop-signal
Data type
Option<Signal>
Description
System call signal that will be sent to the container to exit.
Dockerfile
counterpart
STOPSIGNAL
[package .metadata .wharf .output ]
image = " scratch"
stop-signal = " SIGINT"
It's also important to specify which binaries should be built and where to put them.
Each crate can use own convention about where the binaries should go.
For example, with scratch
output image, it might be usefull to put binaries directly into /
(root).
The binaries should be specified in [[package.metadata.wharf.binary]]
array in Cargo.toml
:
Key
Data type
Description
name
String
Binary name inside the crate.
destination
PathBuf
Destination path inside the output image.
[[package .metadata .wharf .binary ]]
name = " cargo-metadata-collector"
destination = " /usr/local/bin/cargo-metadata-collector"
[[package .metadata .wharf .binary ]]
name = " cargo-test-runner"
destination = " /cargo-test-runner"
There is an additional way to control the frontend: build arguments.
Profile
Name
profile
Data type
Option<Profile>
Description
Defines what will be built and copied into the output image.
Possible values
release-binaries
, release-tests
,debug-binaries
, debug-tests
Default
release-binaries
docker build -f Cargo.toml --build-arg profile=release-tests
Features
Name
features
Data type
Option<Vec<String>>
Description
Enable the crate's features.
docker build -f Cargo.toml --build-arg features=feature-1,feature-2
Default features
Name
no-default-features
Data type
Option<bool>
Description
Disable crate's default features.
Possible values
true
, false
docker build -f Cargo.toml --build-arg no-default-features=true
Manifest path
Name
manifest-path
Data type
Option<PathBuf>
Description
Override the path to a crate manifest. Please note, this will not affect configuration collecting behavior.
docker build -f Cargo.toml --build-arg manifest-path=binary-1/Cargo.toml
Debug mode
Name
debug
Data type
Vec<DebugKind>
Description
Special mode of the image - instead of building, dump various debug information.
Possible values
all
, config
, build-plan
, build-graph
, llb
docker build -f Cargo.toml --build-arg debug=build-graph,llb
docker build -f Cargo.toml --build-arg debug=all
Note about debugging the frontend
When debug=all
is used, every possible debug information will be dumped.
Otherwise, when only a partial dump is needed, several values can be specified: debug=config,build-plan
.
By default, Docker will compose an image with those debug artifacts, and it might be tedious to inspect them.
The behavior can be overridden: Docker can be instructed to put outputs into a folder:
docker build -f Cargo.toml . \
--output type=local,dest=debug-out \
--build-arg debug=all