Dockerfile.debian
Rama develop-3.x · réplica de lectura del repositorio original.
# Use the official Rust image as a build stage
FROM --platform=$BUILDPLATFORM rust:trixie AS builder
# Define ARGs for target and build platforms
ARG TARGETPLATFORM
ARG BUILDPLATFORM
# Custom ARGs
ARG FIPS=0
ARG NOPGO=0
# Install packages for cross-compiling software
RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \
--mount=type=cache,sharing=locked,target=/var/lib/apt \
--mount=type=cache,sharing=locked,target=/usr/local/cargo/git \
--mount=type=cache,sharing=locked,target=/usr/local/cargo/registry \
# Install packages for cross-compiling software
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key \
> /etc/apt/trusted.gpg.d/apt.llvm.org.asc && \
echo "deb http://apt.llvm.org/trixie/ llvm-toolchain-trixie-23 main" \
> /etc/apt/sources.list.d/llvm.list && \
echo "deb-src http://apt.llvm.org/trixie/ llvm-toolchain-trixie-23 main" \
>> /etc/apt/sources.list.d/llvm.list && \
apt update && DEBIAN_FRONTEND=noninteractive \
apt install -y debootstrap clang-23 lld-23 libclang-23-dev wrk \
nghttp2-client openssl python3 llvm-23 qemu-user cmake curl \
clang lld libclang-dev llvm && \
cargo install bindgen-cli
# Install the right Rust target
RUN \
# Determine the target
TARGET_TRIPLE="" && \
if ! [ "$BUILDPLATFORM" = "$TARGETPLATFORM" ]; then \
case "$TARGETPLATFORM" in \
"linux/386") TARGET_TRIPLE="i686-unknown-linux-gnu";; \
"linux/amd64") TARGET_TRIPLE="x86_64-unknown-linux-gnu";; \
"linux/arm64") TARGET_TRIPLE="aarch64-unknown-linux-gnu";; \
"linux/arm/v7") TARGET_TRIPLE="armv7-unknown-linux-gnueabihf";; \
"*") echo "Unsupported target platform for cross-compilation: $TARGETPLATFORM" && exit 1 ;; \
esac \
else \
TARGET_TRIPLE="$(rustc --print host-tuple)"; \
fi && \
# Install the Rust target
rustup target add $TARGET_TRIPLE && \
# Save target triple
echo "$TARGET_TRIPLE" > /tmp/target_triple && \
# Create base port directory
mkdir -p /tmp/cross_build_baseport_cached
RUN --mount=type=cache,sharing=locked,target=/tmp/cross_build_baseport_cached \
# Determine the base port
BASE_PORT="$(cat /tmp/cross_build_baseport_cached/base_port 2>&1 || true)" && \
# If base port is missing or greater than 32735 (32768 - 32 - 1), set to 18080,
# otherwise increment by 32
BASE_PORT="$(echo "$BASE_PORT" | awk '{print ($1 > 32735) ? 18080 : $1 + 32}')" && \
echo "$BASE_PORT" > /tmp/cross_build_baseport_cached/base_port && \
echo "$BASE_PORT" > /tmp/cross_build_baseport
# Set the working directory
WORKDIR /usr/src/ferron
# Copy the source code
COPY . .
# Build the application and copy binaries to an accessible location
RUN --mount=type=cache,sharing=private,target=/usr/local/cargo/git \
--mount=type=cache,sharing=private,target=/usr/local/cargo/registry \
--mount=type=cache,sharing=shared,target=/usr/src/ferron/target \
--mount=type=cache,sharing=shared,target=/usr/src/ferron/cross-build/sysroots/prepared \
# Set target triple and path
TARGET_TRIPLE="$(cat /tmp/target_triple)" && \
TARGET_PATH="target/$TARGET_TRIPLE/release" && \
# Prepare the sysroot with lockfile protection
flock -x /usr/src/ferron/cross-build/sysroots/prepared/prepare.lock \
./cross-build/sysroots/prepare-gnu.sh $TARGET_TRIPLE && \
# FIPS compliance check
FIPS_ADD_ARG="" && \
if [ "${FIPS}" == "1" ]; then \
FIPS_ADD_ARG="--fips"; \
fi && \
# Build Ferron binaries
if [ "${NOPGO}" != "1" ]; then \
BENCH_BASE_PORT="$(cat /tmp/cross_build_baseport)" \
CLANG="clang-23" CLANGXX="clang++-23" \
LLVM_PROFDATA="llvm-profdata-23" LLVM_AR="llvm-ar-23" LLVM_RANLIB="llvm-ranlib-23" \
./cross-build/build.sh $TARGET_TRIPLE $FIPS_ADD_ARG --pgo; \
else \
# These targets would fail with PGO, due to missing libprofiler_builtins
BENCH_BASE_PORT="$(cat /tmp/cross_build_baseport)" \
CLANG="clang-23" CLANGXX="clang++-23" \
LLVM_PROFDATA="llvm-profdata-23" LLVM_AR="llvm-ar-23" LLVM_RANLIB="llvm-ranlib-23" \
./cross-build/build.sh $TARGET_TRIPLE $FIPS_ADD_ARG; \
fi && \
# Copy executables out of the cache
mkdir .dist && cp $TARGET_PATH/ferron $TARGET_PATH/ferron-fmt $TARGET_PATH/ferron-passwd $TARGET_PATH/ferron-precompress $TARGET_PATH/ferron-kdl2ferron $TARGET_PATH/ferron-serve .dist
# Use a slim Debian base image for the final image
FROM debian:trixie-slim
# Update the packages & install CA certificates
RUN --mount=type=cache,sharing=private,target=/var/cache/apt \
--mount=type=cache,sharing=private,target=/var/lib/apt \
apt update && \
DEBIAN_FRONTEND=noninteractive apt upgrade -y && \
DEBIAN_FRONTEND=noninteractive apt install -y ca-certificates && \
apt clean && \
rm -rf /var/lib/apt/lists/* && \
rm -rf /var/cache/apt/*
# Copy the compiled binaries from the builder stage
COPY --from=builder /usr/src/ferron/.dist /usr/local/bin
# Create :
# - an ACME cache directory
# - a directory where Ferron logs are stored
# - a configuration directory
RUN mkdir -p /var/cache/ferron-acme && chown -R nobody:nogroup /var/cache/ferron-acme && \
mkdir -p /var/log/ferron && chown -R nobody:nogroup /var/log/ferron && \
mkdir -p /etc/ferron && chown -R nobody:nogroup /etc/ferron && \
mkdir -p /etc/ferron/conf.d && chown -R nobody:nogroup /etc/ferron/conf.d
# Switch to "nobody" user to make commands like WORKDIR use the correct owner
USER nobody
# Copy the web server configuration
COPY --chown=nobody configs/ferron.docker-entrypoint.conf /etc/ferron/ferron.conf
COPY --chown=nobody configs/ferron.docker.conf /etc/ferron/conf.d/00-default.conf
# Copy the web root contents
COPY --chown=nobody wwwroot /var/www/ferron/
# Expose the port 80 (used for HTTP)
EXPOSE 80
# Set the command to run the binary
CMD ["/usr/local/bin/ferron", "run", "-c", "/etc/ferron/ferron.conf"]