Demo multi-stage Docker containers

This commit is contained in:
Eric Kidd 2017-10-13 07:13:10 -04:00
parent 372d547138
commit ac72ab16ab
3 changed files with 65 additions and 31 deletions

View file

@ -0,0 +1,24 @@
# -*- mode: dockerfile -*-
#
# An example Dockerfile showing how to build a Rust executable using this
# image, and deploy it with a tiny Alpine Linux container.
# Our first FROM statement declares the build environment.
FROM ekidd/rust-musl-builder AS builder
# You would normally add your source code to /home/rust/src like this.
# ADD . ./
# ...but we're going to just create a new app instead for demo purposes.
RUN cd .. && rm -r src && USER=rust cargo new --vcs none --bin --name hello src
# Build our application.
RUN cargo build --release
# Now, we need to build our _real_ Docker container, copying in `hello`.
FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY --from=builder \
/home/rust/src/target/x86_64-unknown-linux-musl/release/hello \
/usr/local/bin/
CMD /usr/local/bin/hello

View file

@ -18,11 +18,7 @@ making final release builds.
## Deploying your Rust application
With a bit of luck, you should be able to just copy your application binary
from `target/x86_64-unknown-linux-musl/release`, and install it directly on
any reasonably modern x86_64 Linux machine. In particular, you should be
able to copy your Rust application into an
[Alpine Linux container][].
With a bit of luck, you should be able to just copy your application binary from `target/x86_64-unknown-linux-musl/release`, and install it directly on any reasonably modern x86_64 Linux machine. In particular, you should be able make static release binaries using TravisCI and GitHub, or you can copy your Rust application into an [Alpine Linux container][]. See below for details!
## How it works
@ -50,32 +46,6 @@ fn main() {
}
```
## Adding more C libraries
If you're using Docker crates which require specific C libraries to be
installed, you can create a Dockerfile based on this one, and use
`musl-gcc` to compile the libraries you need. For example:
```Dockerfile
FROM ekidd/rust-musl-builder
# EXAMPLE ONLY! libz is already included.
RUN VERS=1.2.11 && \
cd /home/rust/libs && \
curl -LO http://zlib.net/zlib-$VERS.tar.gz && \
tar xzf zlib-$VERS.tar.gz && cd zlib-$VERS && \
CC=musl-gcc ./configure --static --prefix=/usr/local/musl && \
make && sudo make install && \
cd .. && rm -rf zlib-$VERS.tar.gz zlib-$VERS
```
This usually involves a bit of experimentation for each new library, but it
seems to work well for most simple, standalone libraries.
If you need an especially common library, please feel free to submit a pull
request adding it to the main `Dockerfile`! We'd like to support popular
Rust crates out of the box.
## Making static releases with Travis CI and GitHub
These instructions are inspired by [rust-cross][].
@ -122,6 +92,42 @@ For a working example, see [faradayio/cage][cage].
[uploading]: https://docs.travis-ci.com/user/deployment/releases
[cage]: https://github.com/faradayio/cage
## Making tiny Docker images with Alpine Linux and Rust binaries
Docker now supports [multistage builds][multistage], which make it easy to
build your Rust application with `rust-musl-builder` and deploy it using
[Alpine Linux][]. For a working example, see
[`Dockerfile.multistage-example`](./Dockerfile.multistage-example).
[multistage]: https://docs.docker.com/engine/userguide/eng-image/multistage-build/
[Alpine Linux]: https://alpinelinux.org/
## Adding more C libraries
If you're using Docker crates which require specific C libraries to be
installed, you can create a `Dockerfile` based on this one, and use
`musl-gcc` to compile the libraries you need. For example:
```Dockerfile
FROM ekidd/rust-musl-builder
# EXAMPLE ONLY! libz is already included.
RUN VERS=1.2.11 && \
cd /home/rust/libs && \
curl -LO http://zlib.net/zlib-$VERS.tar.gz && \
tar xzf zlib-$VERS.tar.gz && cd zlib-$VERS && \
CC=musl-gcc ./configure --static --prefix=/usr/local/musl && \
make && sudo make install && \
cd .. && rm -rf zlib-$VERS.tar.gz zlib-$VERS
```
This usually involves a bit of experimentation for each new library, but it
seems to work well for most simple, standalone libraries.
If you need an especially common library, please feel free to submit a pull
request adding it to the main `Dockerfile`! We'd like to support popular
Rust crates out of the box.
## Development notes
After modifying the image, run `./test-image` to make sure that everything

View file

@ -9,6 +9,10 @@ docker build -t ekidd/rust-musl-builder .
# Make sure we can build our example derived container.
docker build -t rust-musl-zlib -f Dockerfile.example .
# Make sure we can build a multi-stage container.
docker build -t rust-multistage-example -f Dockerfile.multistage-example .
docker run --rm rust-multistage-example
# Make sure we can build a static executable.
docker run --rm ekidd/rust-musl-builder bash -c "
set -euo pipefail