Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Create multi-arch Dockerfiles #986

@joswayski

Description

@joswayski

As a self hoster / deployer, I'd like to deploy to wherever architecture my servers run on not just whatever you're using. This is mostly for the backend Rust API services as the FE web app can be built with buildx just fine I believe.

I simply want to run buildx with my current architecture and a target architecture(s) and get a runable docker file.

I asked chatGPT to do this or the API and it spit this out, it looks mostly correct. The main issue was with the copy commands we currently have there and the target builds. Didn't test it.

docker buildx create --use
docker buildx build --platform linux/amd64,linux/arm64 -t plutomi/api:latest-local -f api/Dockerfile . --load
# Builder stage using an official Rust image 
FROM --platform=$BUILDPLATFORM rust:1.79.0-bullseye AS builder

ARG TARGETPLATFORM
ARG BUILDPLATFORM

WORKDIR /app

# Copy the shared library code first
COPY ./shared /app/shared

# Setup the working directory for the API service
WORKDIR /app/api

# Copy dependency manifests
COPY ./api/Cargo.toml ./api/Cargo.lock ./

# Create a dummy main file to compile dependencies only
RUN mkdir src && \
    echo "fn main() {}" > src/main.rs

# Set the correct target based on the build platform
RUN case "$TARGETPLATFORM" in \
        "linux/amd64")  RUST_TARGET="x86_64-unknown-linux-gnu" ;; \
        "linux/arm64")  RUST_TARGET="aarch64-unknown-linux-gnu" ;; \
        *)              echo "Unsupported platform: $TARGETPLATFORM" && exit 1 ;; \
    esac && \
    echo "RUST_TARGET=$RUST_TARGET" >> $GITHUB_ENV && \
    rustup target add $RUST_TARGET

# Build dependencies only
RUN --mount=type=cache,target=/usr/local/cargo/registry \
    --mount=type=cache,target=/app/target \
    cargo build --release --target $RUST_TARGET --locked

# Now copy the actual source code
COPY ./api/src ./src

# Build the actual application
RUN --mount=type=cache,target=/usr/local/cargo/registry \
    --mount=type=cache,target=/app/target \
    cargo build --release --target $RUST_TARGET --locked

# Install runtime dependencies
RUN apt update && apt install -y musl-tools musl-dev wget ca-certificates

# Final stage uses a minimal Debian image for the runtime
FROM --platform=$TARGETPLATFORM debian:bullseye-slim as final

ARG TARGETPLATFORM

# Copy the built binary from the builder stage
RUN case "$TARGETPLATFORM" in \
        "linux/amd64")  RUST_TARGET="x86_64-unknown-linux-gnu" ;; \
        "linux/arm64")  RUST_TARGET="aarch64-unknown-linux-gnu" ;; \
        *)              echo "Unsupported platform: $TARGETPLATFORM" && exit 1 ;; \
    esac && \
    echo "RUST_TARGET=$RUST_TARGET" >> $GITHUB_ENV

COPY --from=builder /app/api/target/$RUST_TARGET/release/api /app/api

# Copy CA certificates for SSL
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

# Set up a non-root user for security purposes
RUN addgroup --system --gid 1001 apigroup && \
    adduser --system --uid 1001 apiuser
USER apiuser

# Expose the port the API service listens on
EXPOSE 8080

# Set the entrypoint to run the API
ENTRYPOINT ["/app/api"]

Acceptance Criteria:

  • I can build for x86 & ARM for the API using ONE Dockerfile
  • I can build for x86 & ARM for the events-consumer using ONE Dockerfile
  • I can build for x86 & ARM for the web app using ONE Dockerfile

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions