1

To reduce the docker image size, I package my rust app as an docker image like this:

# build stage
FROM rust:1.54 as builder
LABEL maintainer="jiangtingqiang@gmail.com"
ENV ROCKET_ADDRESS=0.0.0.0
ENV ROCKET_PORT=11014
WORKDIR /app
COPY . /app
RUN rustup default stable
RUN cargo build --release

# Prod stage
FROM gcr.io/distroless/cc
COPY --from=builder /app/target/release/reddwarf_music /
CMD ["./reddwarf_music"]

but when I start the docker image in kubernetes cluster, the pod log shows that:./reddwarf_music: error while loading shared libraries: libpq.so.5: cannot open shared object file: No such file or directory, To my understand the rust compiled app was independent and do not need any third party library, why would this happen? what should I do to fix this problem? I have searching from internet but no one facing this problem. My app was an web api server, and using PostgreSQL 13 as my backend database.

Dolphin
  • 29,069
  • 61
  • 260
  • 539

3 Answers3

3

I finnaly tweak the dockerfile like this:

# build stage
FROM rust:1.54-bullseye as builder
WORKDIR /app
COPY . /app
RUN rustup default stable
RUN cargo build --release

# Prod stage
FROM debian:bullseye-slim
LABEL maintainer="jiangtingqiang@gmail.com"
ENV ROCKET_ADDRESS=0.0.0.0
ENV ROCKET_PORT=11014
RUN apt-get update && apt-get install postgresql -y
COPY --from=builder /app/target/release/reddwarf_music /
CMD ["./reddwarf_music"]

the image size from 1GB+ to 100MB+, the max layer was RUN apt-get update && apt-get install postgresql -y, it take more than 100MB, I have to install the postgresql because the rust diesel need using the lib libpq.so.5 from postgresql. The key to fix the error was install postgresql. I did not know any better way to fix this problem.

Improve:

we can change postgresql to libpq5 like this:

RUN apt-get update && apt-get install libpq5 -y

only take 40MB+.

Dolphin
  • 29,069
  • 61
  • 260
  • 539
2

It's recommended to use the same os image base, for example:

FROM rust:1.54-bullseye-slim as builder
# ...
FROM debian:bullseye-slim
Stargateur
  • 24,473
  • 8
  • 65
  • 91
1

For my case, I was setting up a Dockerfile for Actix Web, Diesel and Postgres. But it shouldn't matter since the real problem actually lies with diesel and postgres instead.

Supposed we have a multistage build like your setup above, in the second stage (based on distroless image), we need to copy the related libpq files over from the previous build stage.

Something like the following

# ---------------------------------------------------
# 2 - Deploy Stage
#
# Use a distroless image for minimal container size
# - Copy `libpq` dependencies into the image (Required by diesel)
# - Copy application files into the image
# ---------------------------------------------------
FROM gcr.io/distroless/cc-debian11

# Set the architecture argument (arm64, i.e. aarch64 as default)
# For amd64, i.e. x86_64, you can append a flag when invoking the build `... --build-arg "ARCH=x86_64"`
ARG ARCH=aarch64

# libpq related (required by diesel)
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libpq.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libgssapi_krb5.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libldap_r-2.4.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libkrb5.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libk5crypto.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libkrb5support.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/liblber-2.4.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libsasl2.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libgnutls.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libp11-kit.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libidn2.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libunistring.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libtasn1.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libnettle.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libhogweed.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libgmp.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /usr/lib/${ARCH}-linux-gnu/libffi.so* /usr/lib/${ARCH}-linux-gnu/
COPY --from=build /lib/${ARCH}-linux-gnu/libcom_err.so* /lib/${ARCH}-linux-gnu/
COPY --from=build /lib/${ARCH}-linux-gnu/libkeyutils.so* /lib/${ARCH}-linux-gnu/

# Application files
COPY --from=build /usr/local/cargo/bin/codefee-works-api /usr/local/bin/codefee-works-api
COPY --from=build /usr/src/codefee-works-api/.env /.env

Notice that I set a default value here for ARG ARCH=aarch64. That is because I am on an arm64 architecture machine, e.g. M1 Mac. If you happen to be on an amd64, i.e. x86_64 machine, you can set it to ARG ARCH=x86_64 instead. Or simply have the build argument value passed in upon running the Docker build command.

I have written an in-depth article on this topic. You can find out more over here https://www.codefeetime.com/post/docker-config-for-actix-web-diesel-and-postgres#32-resolving-missing-lib-dependencies

DriLLFreAK100
  • 1,575
  • 2
  • 16
  • 26