Files
Jellyswarrm/Dockerfile
2025-12-21 15:24:55 +01:00

126 lines
4.3 KiB
Docker

#################################
# Stage 1: Build UI (Node.js optimized)
#################################
FROM node:20-alpine AS ui-build
# Install git for version detection
RUN apk add --no-cache git
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 install --engine-strict=false --ignore-scripts
# Copy UI source code and git metadata
COPY ui/ ./
COPY .git/modules/ui/ /app/.git/modules/ui/
# Get and print UI version info
RUN UI_VERSION=$(git describe --tags) && \
UI_COMMIT=$(git rev-parse HEAD) && \
echo "UI_VERSION=$UI_VERSION" && \
echo "UI_COMMIT=$UI_COMMIT"
# Build production UI bundle
RUN npm run build:production
# Write ui-version.env file
RUN UI_VERSION=$(git describe --tags) && \
UI_COMMIT=$(git rev-parse HEAD) && \
printf "UI_VERSION=%s\nUI_COMMIT=%s\n" "$UI_VERSION" "$UI_COMMIT" > dist/ui-version.env && \
echo "Generated dist/ui-version.env"
#################################
# Stage 2: Rust Dependencies Cache
#################################
FROM rust:1.92.0-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
COPY crates/jellyfin-api/Cargo.toml crates/jellyfin-api/Cargo.toml
# Create dummy source files to build dependencies
RUN mkdir -p crates/jellyswarrm-proxy/src crates/jellyswarrm-macros/src crates/jellyfin-api/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 \
&& echo "" > crates/jellyfin-api/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 crates/jellyfin-api/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-proxy/migrations crates/jellyswarrm-proxy/migrations
COPY crates/jellyswarrm-macros/src crates/jellyswarrm-macros/src
COPY crates/jellyfin-api/src crates/jellyfin-api/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* \
&& rm -rf /tmp/target/release/deps/libjellyfin_api* \
&& touch crates/jellyswarrm-macros/src/lib.rs \
&& touch crates/jellyfin-api/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"]