ARG DI_VER="1.2.5" FROM rust:1.53 AS builder # Here, we define the versions of the libraries we want to build ARG DI_VER ARG PQ_VER="11.12" ARG ZLIB_VER="1.2.11" ARG SSL_VER="1.0.2u" WORKDIR /usr/src ENV PREFIX="/usr/src/musl" \ CC="musl-gcc -fPIC -pie -static" \ LD_LIBRARY_PATH="$PREFIX" \ PKG_CONFIG_PATH="/usr/local/lib/pkgconfig" \ PATH="/usr/local/bin:/root/.cargo/bin:$PATH" # Minimal build requirements for hilde's C dependencies RUN apt update && \ apt install -y --no-install-recommends \ musl-dev \ musl-tools \ libpq-dev \ libssl-dev && \ rustup target add x86_64-unknown-linux-musl && \ mkdir "$PREFIX" && \ echo "$PREFIX/lib" >> /etc/ld-musl-x86_64.path # =====BUILDING LIBRARIES===== # Because I think it's cool, I wanted to make a fully static binary for hilde. That's why I'm # manually compiling zlib, openssl & libpq using musl-gcc. This certainly wouldn't have been # possible without this amazing Dockerfile, so I'm very glad I found it. # https://github.com/clux/muslrust/blob/master/Dockerfile # Build zlib (as in, gzip) RUN curl -sSL "https://zlib.net/zlib-$ZLIB_VER.tar.gz" | tar xz && \ cd "zlib-$ZLIB_VER" && \ LDFLAGS="-L$PREFIX/lib" CFLAGS="-I$PREFIX/include" ./configure \ --static \ --prefix "$PREFIX" && \ make -j$(nproc) && \ make install # Build openSSL (needed to build libpq, & send https requests using reqwest) RUN curl -sSL "https://www.openssl.org/source/old/1.0.2/openssl-$SSL_VER.tar.gz" | tar xz && \ cd "openssl-$SSL_VER" && \ ./Configure \ no-zlib \ no-shared \ -fPIC \ --prefix="$PREFIX" \ --openssldir="$PREFIX/ssl" \ linux-x86_64 && \ env C_INCLUDE_PATH="$PREFIX/include" make depend 2> /dev/null && \ make -j$(nproc) && \ make install # Build libpq RUN curl -sSL "https://ftp.postgresql.org/pub/source/v$PQ_VER/postgresql-$PQ_VER.tar.gz" | tar xz && \ cd "postgresql-$PQ_VER" && \ LDFLAGS="-L$PREFIX/lib" CFLAGS="-I$PREFIX/include" ./configure \ --without-readline \ --with-openssl \ --prefix="$PREFIX" \ --host=x86_64-unknown-linux-musl && \ cd src/interfaces/libpq && \ make -s -j$(nproc) all-static-lib && \ make -s install install-lib-static && \ cd ../../bin/pg_config && \ make -j $(nproc) && \ make install # As far as I know these env vars just config the libraries in the correct way # to properly compile them later ENV PATH=$PREFIX/bin:$PATH \ PKG_CONFIG_ALLOW_CROSS=true \ PKG_CONFIG_ALL_STATIC=true \ PQ_LIB_STATIC_X86_64_UNKNOWN_LINUX_MUSL=true \ PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig \ PG_CONFIG_X86_64_UNKNOWN_LINUX_GNU=/usr/bin/pg_config \ OPENSSL_STATIC=true \ OPENSSL_DIR=$PREFIX \ SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt \ SSL_CERT_DIR=/etc/ssl/certs \ LIBZ_SYS_STATIC=1 # =====BUILD DUMB-INIT===== # dumb-init is a very basic init system designed to act as the PID 1 process inside a Docker container. # The Makefile already specifies static build flags, so we don't have to specify them here. RUN curl -sSL "https://github.com/Yelp/dumb-init/archive/refs/tags/v$DI_VER.tar.gz" | \ tar xzf - && \ cd "dumb-init-$DI_VER" && \ CC="musl-gcc" make build # =====BUILD HILDE===== # Now that we've compiled all our C dependencies, we can build the actual binary using Cargo. COPY . ./hilde/ RUN cd hilde && \ cargo build \ --release \ --target x86_64-unknown-linux-musl # =====CREATE RELEASE IMAGE===== # Thanks to all the compiling done above, we can now create a working Docker image using just static binaries. # This way, we don't need a base OS, which drastically reduces the final image size. FROM scratch ARG DI_VER COPY --from=builder /usr/src/dumb-init-$DI_VER/dumb-init /bin/dumb-init COPY --from=builder /usr/src/hilde/target/x86_64-unknown-linux-musl/release/hilde /bin/hilde ENTRYPOINT [ "/bin/dumb-init", "--" ] CMD [ "/bin/hilde" ]