|
| 1 | +# ============================================================================= |
| 2 | +# Stage 1: Tool Cache - Build/install cargo tools once and cache them |
| 3 | +# ============================================================================= |
| 4 | +FROM rustlang/rust:nightly-alpine AS tool-cache |
| 5 | + |
| 6 | +RUN apk add --no-cache libc-dev openssl-dev sqlite-dev perl make |
| 7 | + |
| 8 | +# Install cargo tools in a dedicated stage for better caching |
| 9 | +RUN cargo install sqlx-cli --no-default-features --features sqlite --locked |
| 10 | +RUN cargo install cargo-leptos --locked |
| 11 | + |
| 12 | +# ============================================================================= |
| 13 | +# Stage 2: Builder - Build the Leptos SSR application |
| 14 | +# ============================================================================= |
| 15 | +FROM rustlang/rust:nightly-alpine AS builder |
| 16 | + |
| 17 | +# Install build dependencies |
| 18 | +RUN apk update && \ |
| 19 | + apk add --no-cache \ |
| 20 | + bash \ |
| 21 | + curl \ |
| 22 | + npm \ |
| 23 | + libc-dev \ |
| 24 | + binaryen \ |
| 25 | + openssl-dev \ |
| 26 | + openssl-libs-static \ |
| 27 | + pkgconfig \ |
| 28 | + sqlite \ |
| 29 | + sqlite-dev \ |
| 30 | + musl-dev |
| 31 | + |
| 32 | +# Copy pre-built tools from cache stage |
| 33 | +COPY --from=tool-cache /usr/local/cargo/bin/sqlx /usr/local/cargo/bin/sqlx |
| 34 | +COPY --from=tool-cache /usr/local/cargo/bin/cargo-sqlx /usr/local/cargo/bin/cargo-sqlx |
| 35 | +COPY --from=tool-cache /usr/local/cargo/bin/cargo-leptos /usr/local/cargo/bin/cargo-leptos |
| 36 | + |
| 37 | +# Add WASM target for client-side hydration |
| 38 | +RUN rustup target add wasm32-unknown-unknown |
| 39 | + |
| 40 | +# Set working directory |
| 41 | +WORKDIR /work |
| 42 | + |
| 43 | +# Copy dependency manifests first and create dummy src for dependency caching |
| 44 | +COPY Cargo.toml Cargo.lock ./ |
| 45 | +RUN mkdir -p src && \ |
| 46 | + echo "fn main() {}" > src/main.rs && \ |
| 47 | + echo "pub fn dummy() {}" > src/lib.rs |
| 48 | +RUN cargo build --release --features ssr && rm -rf src target/release/deps/flashy* |
| 49 | + |
| 50 | +# Now copy real source code |
| 51 | +COPY src ./src |
| 52 | +COPY style ./style |
| 53 | +COPY public ./public |
| 54 | +COPY migrations ./migrations |
| 55 | + |
| 56 | +ENV DATABASE_URL=sqlite:build.db |
| 57 | +RUN sqlx database create && \ |
| 58 | + sqlx migrate run && \ |
| 59 | + cargo sqlx prepare --workspace -- --lib --features ssr && \ |
| 60 | + rm build.db* |
| 61 | + |
| 62 | +# Set SQLx to offline mode for the actual build |
| 63 | +ENV SQLX_OFFLINE=true |
| 64 | + |
| 65 | +# Build the application in release mode with optimizations |
| 66 | +ENV CARGO_PROFILE_RELEASE_STRIP=symbols |
| 67 | +ENV CARGO_PROFILE_RELEASE_LTO=true |
| 68 | +ENV CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 |
| 69 | +RUN cargo leptos build --release -vv |
| 70 | + |
| 71 | +# ============================================================================= |
| 72 | +# Stage 3: Runtime Dependencies - Build minimal sqlx for runtime |
| 73 | +# ============================================================================= |
| 74 | +FROM rustlang/rust:nightly-alpine AS runtime-tools |
| 75 | + |
| 76 | +RUN apk add --no-cache libc-dev openssl-dev sqlite-dev musl-dev |
| 77 | + |
| 78 | +# Build sqlx statically for distroless |
| 79 | +RUN cargo install sqlx-cli --no-default-features --features sqlite --locked \ |
| 80 | + --target x86_64-unknown-linux-musl || \ |
| 81 | + cargo install sqlx-cli --no-default-features --features sqlite --locked |
| 82 | + |
| 83 | +# ============================================================================= |
| 84 | +# Stage 4: Runner - Distroless minimal runtime image |
| 85 | +# ============================================================================= |
| 86 | +# :debug needed for busybox shell for entrypoint script |
| 87 | +FROM gcr.io/distroless/cc-debian12:debug |
| 88 | + |
| 89 | +WORKDIR /app |
| 90 | + |
| 91 | +COPY --from=builder --chmod=755 /work/target/release/flashy /app/flashy |
| 92 | +COPY --from=builder --chmod=644 /work/Cargo.toml /app/Cargo.toml |
| 93 | + |
| 94 | +COPY --from=builder /work/target/site /app/site |
| 95 | +COPY --from=builder /work/migrations /app/migrations |
| 96 | + |
| 97 | +COPY --from=runtime-tools --chmod=755 /usr/local/cargo/bin/sqlx /app/sqlx |
| 98 | + |
| 99 | +COPY --chmod=755 docker-entrypoint.sh /app/docker-entrypoint.sh |
| 100 | + |
| 101 | +ENV RUST_LOG="info" |
| 102 | +ENV LEPTOS_SITE_ADDR="0.0.0.0:8080" |
| 103 | +ENV LEPTOS_SITE_ROOT="/app/site" |
| 104 | +ENV DATABASE_URL="sqlite:/app/data/flashy.db" |
| 105 | + |
| 106 | +EXPOSE 8080 |
| 107 | + |
| 108 | +VOLUME ["/app/data"] |
| 109 | + |
| 110 | +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ |
| 111 | + CMD ["/busybox/wget", "-q", "-O", "/dev/null", "http://localhost:8080/"] |
| 112 | + |
| 113 | +ENTRYPOINT ["/busybox/sh", "/app/docker-entrypoint.sh"] |
0 commit comments