I’ve been playing megabyte golf with my carbon/whisper time series database daemon and I’ve gotten it down to 2MB (4.27MB when expanded) for a fully-functioning UDP/TCP writer. I thought it’d be fun to talk about it a bit and get people’s feedback.
This uses the
Dockerfile.final build pattern I’ve written about here: http://tureus.github.io/devops/2015/08/27/container-release-workflow.html . The gist: you build the application in a heavy build env (all rustc/cargo, deps, etc). Then you copy that built artifact in to a stripped down release image. It uses a
docker.sock forwarding technique which is kinda neat.
The small size of the image is due to the busybox release image. The docker registry has the latest busybox image weighing in at 651KB. Busybox is uses uclibc which is not compatible with standard cargo-built binaries. You can make cargo compatible by using a musl-powered rustc but that’s a custom build. Fortunately Andrew Dunham has published some work on github: https://github.com/andrew-d/docker-rust-musl . This provides a suitable rust build environment targeting musl! He even published it to the docker registry so you can skip straight to a working image:
docker pull andrewd/rust-musl.
I swapped out my
debian:jessie build environment with andrewd’s rust-musl and I was off to the races.
My build environment Dockerfile:
FROM andrewd/rust-musl RUN curl -sSL https://get.docker.io/builds/Linux/x86_64/docker-1.2.0 -o /tmp/docker && \ echo "540459bc5d9f1cac17fe8654891814314db15e77 /tmp/docker" | sha1sum -c - && \ mv /tmp/docker /usr/local/bin/docker && \ chmod +x /usr/local/bin/docker ADD . /graphite-rust WORKDIR /graphite-rust RUN cargo build --release --target x86_64-unknown-linux-musl WORKDIR /graphite-rust/target/x86_64-unknown-linux-musl/release ADD docker/Dockerfile.final /graphite-rust/target/x86_64-unknown-linux-musl/release/Dockerfile CMD docker build -t xrlx/graphite .
- Install docker binary for talking to forwarded socket
- Copy my project’s code in to the build env
- Cargo fetches all the deps, does release build
- Change working directory to the cargo release folder
- Run the
Dockerfile.finalbuild to generate the release
FROM busybox ADD carbon /usr/bin/carbon ENV RUST_LOG debug VOLUME /data EXPOSE 2003 EXPOSE 2003/udp ENTRYPOINT ["/usr/bin/carbon", "--storage-path", "/data"]
Dockerfile.final has access to all the contents of the release folder from the build env. It copies the
carbon binary in to the
$PATH on the release image and sets the executable as the default entrypoint.
Hope this is useful to someone out there. Fun little hour of work to get things trimmed down. Not sure about the performance implications, haven’t really load tested it. But the application boots!