mirror of
https://github.com/wizarrrr/wizarr.git
synced 2026-04-21 14:38:45 -04:00
108 lines
3.6 KiB
Docker
108 lines
3.6 KiB
Docker
# ─── Stage 1: Dependencies ───────────────────────────────────────────────
|
|
FROM ghcr.io/astral-sh/uv:python3.13-alpine AS deps
|
|
|
|
# Install system dependencies
|
|
RUN apk add --no-cache nodejs npm
|
|
|
|
# Set working directory
|
|
WORKDIR /app
|
|
|
|
# Enable bytecode compilation for faster startup
|
|
ENV UV_COMPILE_BYTECODE=1
|
|
|
|
# Use copy link mode to avoid warnings with cache mounts
|
|
ENV UV_LINK_MODE=copy
|
|
|
|
# Copy dependency files first for better caching
|
|
COPY pyproject.toml uv.lock ./
|
|
|
|
# Install Python dependencies only (not project) with cache mount for speed
|
|
# Use --frozen to ensure reproducible builds from uv.lock
|
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
uv sync --frozen --no-install-project --no-dev
|
|
|
|
# Copy npm dependency files and install with cache
|
|
COPY app/static/package*.json ./app/static/
|
|
RUN npm --prefix app/static/ ci --cache /tmp/npm-cache
|
|
|
|
# ─── Stage 2: Build assets ────────────────────────────────────────────────
|
|
FROM deps AS builder
|
|
|
|
# Copy source files needed for building
|
|
COPY app/ ./app/
|
|
COPY babel.cfg ./
|
|
|
|
# Install the project now that we have source code
|
|
# Use --frozen to ensure reproducible builds from uv.lock
|
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
uv sync --frozen --no-dev
|
|
|
|
# Build translations (include fuzzy entries so pending translations are bundled)
|
|
RUN uv run --frozen --no-dev pybabel compile --use-fuzzy -d app/translations
|
|
|
|
# Ensure static directories exist and build static assets
|
|
RUN mkdir -p app/static/js app/static/css && npm --prefix app/static/ run build
|
|
|
|
# ─── Stage 3: Runtime ─────────────────────────────────────────────────────
|
|
FROM ghcr.io/astral-sh/uv:python3.13-alpine
|
|
|
|
# Set default environment variables for user/group IDs
|
|
ENV PUID=1000
|
|
ENV PGID=1000
|
|
|
|
# Install runtime dependencies only
|
|
RUN apk add --no-cache curl tzdata su-exec
|
|
|
|
# Set application working directory
|
|
WORKDIR /app
|
|
|
|
# Copy Python environment from builder stage (includes project)
|
|
COPY --chown=1000:1000 --from=builder /app/.venv /app/.venv
|
|
|
|
# Copy source files first (run.py, gunicorn.conf.py, migrations/, etc.)
|
|
COPY --chown=1000:1000 . /app
|
|
|
|
# Then overwrite app/ with built version (has compiled translations)
|
|
COPY --chown=1000:1000 --from=builder /app/app /app/app
|
|
|
|
# Create data directory for database (backward compatibility)
|
|
RUN mkdir -p /data/database
|
|
|
|
# Create directories that need to be writable
|
|
RUN mkdir -p /.cache
|
|
|
|
ARG APP_VERSION=dev
|
|
ENV APP_VERSION=${APP_VERSION}
|
|
|
|
# Set Flask environment to production
|
|
ENV FLASK_ENV=production
|
|
|
|
# Healthcheck: curl to localhost:5690/health
|
|
# Increased start-period to 60s to account for:
|
|
# - Database migrations
|
|
# - Library scanning
|
|
# - Wizard step imports
|
|
# - Worker initialization (4 workers * ~10s each)
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
|
|
CMD curl -fs http://localhost:5690/health || exit 1
|
|
|
|
# Expose port 5690
|
|
EXPOSE 5690
|
|
|
|
# Copy any wizard steps into /opt
|
|
COPY wizard_steps /opt/default_wizard_steps
|
|
|
|
# Copy entrypoint script and make it executable
|
|
COPY docker-entrypoint.sh /usr/local/bin/
|
|
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
|
|
|
# Entrypoint and default CMD
|
|
ENTRYPOINT ["docker-entrypoint.sh"]
|
|
|
|
# By default we run Gunicorn under wizarruser
|
|
CMD ["uv", "run", "--frozen", "--no-dev", "gunicorn", \
|
|
"--config", "gunicorn.conf.py", \
|
|
"--bind", "0.0.0.0:5690", \
|
|
"--umask", "007", \
|
|
"run:app"]
|