Files
Jellyswarrm/Dockerfile
2025-10-02 14:57:10 +02:00

102 lines
3.4 KiB
Docker

#################################
# Stage 1: Build UI (Node.js optimized)
#################################
FROM node:20-alpine AS ui-build
WORKDIR /app/ui
# Copy package files for dependency caching
COPY ui/package.json ui/package-lock.json* ./
# Install all dependencies (including dev deps needed for build)
RUN --mount=type=cache,target=/root/.npm \
npm ci --ignore-scripts
# Copy UI source code
COPY ui/ ./
# Build production UI bundle
RUN npm run build:production
#################################
# Stage 2: Rust Dependencies Cache
#################################
FROM rust:1-alpine AS rust-deps
WORKDIR /app
# Install build dependencies
RUN apk add --no-cache \
build-base \
pkgconf \
sqlite-dev \
openssl-dev
# Copy Cargo manifests for dependency caching
COPY .cargo .cargo
COPY Cargo.toml Cargo.lock rust-toolchain.toml ./
COPY crates/jellyswarrm-proxy/Cargo.toml crates/jellyswarrm-proxy/Cargo.toml
COPY crates/jellyswarrm-macros/Cargo.toml crates/jellyswarrm-macros/Cargo.toml
# Create dummy source files to build dependencies
RUN mkdir -p crates/jellyswarrm-proxy/src crates/jellyswarrm-macros/src \
&& echo "fn main() {}" > crates/jellyswarrm-proxy/src/main.rs \
&& echo "" > crates/jellyswarrm-proxy/src/lib.rs \
&& echo "use proc_macro::TokenStream; #[proc_macro_attribute] pub fn multi_case_struct(_args: TokenStream, input: TokenStream) -> TokenStream { input }" > crates/jellyswarrm-macros/src/lib.rs
# Build dependencies only (will be cached)
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/usr/local/cargo/git \
--mount=type=cache,target=/tmp/target,sharing=locked \
CARGO_TARGET_DIR=/tmp/target cargo build --release --bin jellyswarrm-proxy \
&& cp /tmp/target/release/jellyswarrm-proxy /app/jellyswarrm-proxy-deps \
&& rm -rf crates/jellyswarrm-proxy/src crates/jellyswarrm-macros/src
#################################
# Stage 3: Build Rust Application
#################################
FROM rust-deps AS rust-build
# Set env var so build.rs skips internal UI build (we already did it)
ENV JELLYSWARRM_SKIP_UI=1
# Copy UI build artifacts from stage 1
COPY --from=ui-build /app/ui/dist crates/jellyswarrm-proxy/static/
# Copy Rust source code and configuration
COPY crates/jellyswarrm-proxy/askama.toml crates/jellyswarrm-proxy/askama.toml
COPY crates/jellyswarrm-proxy/src crates/jellyswarrm-proxy/src
COPY crates/jellyswarrm-macros/src crates/jellyswarrm-macros/src
# Build only the application code (dependencies already cached)
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/usr/local/cargo/git \
--mount=type=cache,target=/tmp/target,sharing=locked \
rm -rf /tmp/target/release/deps/libjellyswarrm_macros* /tmp/target/release/deps/jellyswarrm_macros* \
&& touch crates/jellyswarrm-macros/src/lib.rs \
&& CARGO_TARGET_DIR=/tmp/target cargo build --release --bin jellyswarrm-proxy \
&& cp /tmp/target/release/jellyswarrm-proxy /app/jellyswarrm-proxy
#################################
# Stage 4: Runtime Image (Alpine)
#################################
FROM alpine:3.20 AS runtime
WORKDIR /app
ENV RUST_LOG=info
# Install minimal runtime dependencies
RUN apk add --no-cache \
ca-certificates \
sqlite-libs \
&& update-ca-certificates
# Copy the compiled binary
COPY --from=rust-build /app/jellyswarrm-proxy /app/jellyswarrm-proxy
EXPOSE 3000
ENTRYPOINT ["/app/jellyswarrm-proxy"]