Building smaller docker image
So I am currently working on one Rust server project. After I built the service, as usual, I wrote Dockerfile so that later I can deploy the application in Kubernetes (Vultr is my choice now because of the pricing).
There are 3 candidates for my final image base. These are
Initially, I wanted to use Rust official images for building. However, there are a few issues with it
- need to statically link my built to the
musl libcbecause scratch and alpine are based on
- OpenSSL issue with cross-compilation, you can read more about it here.
glibc issue can be solved by simply installing the library and adding the target for cross-compilation as below. But the tough part comes with SSL.
RUN apt-get install RUN apt-get install -y musl-tools RUN rustup target add x86_64-unknown-linux-musl RUN cargo build --target x86_64-unknown-linux-musl --release
For both issues, someone already built a base image (rust-musl-builder) just for cross-compiling rust application. Therefore, I am using it to build my application.
# ========== # Build step # ========== FROM ekidd/rust-musl-builder AS builder WORKDIR /subtext # copy files COPY ./src ./src COPY ./Cargo.toml . COPY ./Rocket.toml . # https://github.com/emk/rust-musl-builder#making-static-releases-with-travis-ci-and-github ADD --chown=rust:rust . ./ # build release RUN cargo build --release # =========== # Final image # =========== FROM scratch WORKDIR /subtext # copy build COPY --from=builder /subtext/target/x86_64-unknown-linux-musl/release/subtext_api ./ COPY --from=builder /subtext/Rocket.toml ./ CMD ["/subtext/subtext_api"]
In Final image step, I used scratch, alpine, and distroless.
- Scratch has the lowest file size because it is barebone.
- Alpine is also another lightweight image, and it is also kind of a defacto standard.
- Distroless is a security-oriented image maintained by Google, and based on Debian packages therefore using this I will not need to do static linking
scratch is the best candidate to achieve the lowest image size, however, it comes with some costs. Especially with SSL. Scratch images cannot perform SSL cert certification because it does not come with SSL certs. You can read more about it here.
You can simply fix in
scratch by installing it yourself or use
alpine instead. With only ~6mb more, alpine comes with a ton of more utility tools as well.
distroless, even though it is security oriented, there are a few issues with it. You can read the entire article from Red Hat here, but the key point is the size matters. A larger size also increases the attack surface.
Trivy for scanning vulnerability
This is shown by scanning all those 3 images using Trivy, ironically
distroless comes with quite a few CVEs from
libc. Trivy is an awesome tool to scan vulnerabilities for file systems and images.
Lower binary size (for Rust)
Until now, we are focusing on optimizing the image size. We can also optimize the Rust built as well to even lower the size. That however comes at the cost of performance. But if you are interested you can look up the following 2 links below.