|
2 | 2 | # Stage 1: Builder |
3 | 3 | # This stage builds the application and its dependencies. |
4 | 4 | # ------------------------------------------------------------------------------ |
5 | | -FROM rust:1.88-slim-bookworm AS builder |
| 5 | +FROM --platform=linux/amd64 rust:1.88-slim-bookworm AS builder |
6 | 6 |
|
7 | | -# Install build dependencies required by rusqlite (bundled feature compiles |
8 | | -# SQLite from source via the cc crate and needs a C compiler) |
| 7 | +# -- Install system packages --------------------------------------------------- |
| 8 | +# gcc / pkg-config: required by libsqlite3-sys (bundled feature compiles from |
| 9 | +# source via the cc crate) |
| 10 | +# musl-tools: provides musl-gcc, the C linker required for the |
| 11 | +# x86_64-unknown-linux-musl target |
9 | 12 | RUN apt-get update && apt-get install -y --no-install-recommends \ |
10 | 13 | gcc \ |
11 | 14 | pkg-config \ |
| 15 | + musl-tools \ |
12 | 16 | && rm -rf /var/lib/apt/lists/* |
13 | 17 |
|
| 18 | +RUN rustup target add x86_64-unknown-linux-musl |
| 19 | + |
14 | 20 | WORKDIR /app |
15 | 21 |
|
16 | | -# Copy dependency manifests first to leverage layer caching |
| 22 | +# -- Pre-build dependencies (cached) ------------------------------------------ |
| 23 | +# Copy only the manifests and a stub main.rs so Cargo can compile all |
| 24 | +# dependencies in isolation. This layer is cached and only invalidated when |
| 25 | +# Cargo.toml or Cargo.lock change — not when application source changes. |
17 | 26 | COPY Cargo.toml Cargo.lock ./ |
18 | | - |
19 | | -# Stub out a minimal src/main.rs so Cargo can resolve and compile dependencies |
20 | | -# without the real application sources — this layer is only invalidated when |
21 | | -# Cargo.toml or Cargo.lock change. |
22 | 27 | RUN mkdir src && echo "fn main() {}" > src/main.rs |
23 | 28 |
|
24 | 29 | RUN --mount=type=cache,target=/usr/local/cargo/registry \ |
25 | 30 | --mount=type=cache,target=/app/target \ |
26 | | - cargo build --release |
27 | | - |
28 | | -# Overlay with the real application sources |
| 31 | + CC_x86_64_unknown_linux_musl=musl-gcc \ |
| 32 | + cargo build --release --target x86_64-unknown-linux-musl |
| 33 | + |
| 34 | +# -- Build application --------------------------------------------------------- |
| 35 | +# Overlay with the real sources. The stub main.rs is overwritten by the COPY, |
| 36 | +# but Cargo uses mtime to detect changes — touching main.rs after the COPY |
| 37 | +# ensures Cargo recompiles the application crate without re-compiling |
| 38 | +# dependencies (which remain in the cache-mounted target/). |
29 | 39 | COPY src/ ./src/ |
30 | 40 | COPY migrations/ ./migrations/ |
31 | 41 | COPY Rocket.toml ./ |
32 | 42 |
|
33 | | -# Touch main.rs so Cargo detects the change, rebuild only app code, then copy |
34 | | -# the binary out of the cache-mounted target/ into the image layer. |
35 | 43 | RUN --mount=type=cache,target=/usr/local/cargo/registry \ |
36 | 44 | --mount=type=cache,target=/app/target \ |
37 | 45 | touch src/main.rs && \ |
38 | | - cargo build --release && \ |
39 | | - cp target/release/rust-samples-rocket-restful /app/rust-samples-rocket-restful |
| 46 | + CC_x86_64_unknown_linux_musl=musl-gcc \ |
| 47 | + cargo build --release --target x86_64-unknown-linux-musl && \ |
| 48 | + cp target/x86_64-unknown-linux-musl/release/rust-samples-rocket-restful /app/rust-samples-rocket-restful |
40 | 49 |
|
41 | 50 | # ------------------------------------------------------------------------------ |
42 | 51 | # Stage 2: Runtime |
43 | 52 | # This stage creates the final, minimal image to run the application. |
44 | 53 | # ------------------------------------------------------------------------------ |
45 | | -FROM debian:bookworm-slim AS runtime |
46 | | - |
47 | | -# Install curl for health check |
48 | | -RUN apt-get update && apt-get install -y --no-install-recommends \ |
49 | | - curl \ |
50 | | - && rm -rf /var/lib/apt/lists/* |
| 54 | +FROM --platform=linux/amd64 alpine:3.23 AS runtime |
51 | 55 |
|
52 | 56 | WORKDIR /app |
53 | 57 |
|
54 | | -# Metadata labels for the image. These are useful for registries and inspection. |
| 58 | +# -- Install system packages --------------------------------------------------- |
| 59 | +RUN apk add --no-cache curl |
| 60 | + |
| 61 | +# -- Metadata ------------------------------------------------------------------ |
55 | 62 | LABEL org.opencontainers.image.title="🧪 RESTful API with Rust and Rocket" |
56 | 63 | LABEL org.opencontainers.image.description="Proof of Concept for a RESTful API made with Rust and Rocket" |
57 | 64 | LABEL org.opencontainers.image.licenses="MIT" |
58 | 65 | LABEL org.opencontainers.image.source="https://github.com/nanotaboada/rust-samples-rocket-restful" |
59 | 66 | LABEL org.sonarsource.docker.dockerfile="/Dockerfile" |
60 | 67 |
|
61 | | -# https://rules.sonarsource.com/docker/RSPEC-6504/ |
62 | | - |
63 | | -# Copy application binary and Rocket configuration |
| 68 | +# -- Copy artifacts ------------------------------------------------------------ |
64 | 69 | COPY --from=builder /app/rust-samples-rocket-restful . |
65 | 70 | COPY --from=builder /app/Rocket.toml ./Rocket.toml |
66 | | - |
67 | | -# Copy metadata docs for container registries (e.g.: GitHub Container Registry) |
68 | 71 | COPY --chmod=444 README.md ./ |
69 | | - |
70 | | -# Copy entrypoint and healthcheck scripts |
71 | 72 | COPY --chmod=555 scripts/entrypoint.sh ./entrypoint.sh |
72 | 73 | COPY --chmod=555 scripts/healthcheck.sh ./healthcheck.sh |
73 | 74 |
|
74 | | -# Add system user and prepare volume mount point |
75 | | -RUN addgroup --system rocket && \ |
76 | | - adduser --system --ingroup rocket rocket && \ |
| 75 | +# -- Configure runtime --------------------------------------------------------- |
| 76 | +# https://rules.sonarsource.com/docker/RSPEC-6504/ |
| 77 | +RUN addgroup -S rocket && \ |
| 78 | + adduser -S -G rocket rocket && \ |
77 | 79 | mkdir -p /storage && \ |
78 | 80 | chown -R rocket:rocket /storage |
79 | 81 |
|
|
0 commit comments