Dockerfile
Rama main · réplica de lectura del repositorio original.
# ── Stage 1: Build frontend ──────────────────────────────────────────────────
FROM node:20-alpine AS frontend-builder
WORKDIR /build/frontend
COPY frontend/package*.json ./
RUN npm ci --ignore-scripts --silent
COPY frontend/ ./
RUN npm run build
# ── Stage 2: Install Python deps ─────────────────────────────────────────────
FROM python:3.12-slim AS backend-deps
COPY --from=ghcr.io/astral-sh/uv:0.12.19 /uv /usr/local/bin/uv
WORKDIR /build
COPY backend/pyproject.toml backend/uv.lock ./
RUN uv export --frozen --no-dev --no-emit-project --output-file /tmp/requirements.txt \
&& uv pip install --python /usr/local/bin/python --prefix=/install \
--only-binary :all: --require-hashes -r /tmp/requirements.txt
# ── Stage 3: Runtime image ────────────────────────────────────────────────────
FROM python:3.12-slim
ARG APP_VERSION=0.0.0
LABEL org.opencontainers.image.title="Observer Lite" \
org.opencontainers.image.description="Lightweight self-hosted uptime monitoring with email and Telegram alerts." \
org.opencontainers.image.version="${APP_VERSION}" \
org.opencontainers.image.source="https://github.com/cagatayuresin/observer-lite" \
org.opencontainers.image.licenses="MIT"
# iputils-ping for PING monitor type
RUN apt-get update && \
apt-get install -y --no-install-recommends iputils-ping && \
rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Python packages
COPY --from=backend-deps /install /usr/local
# Backend source
COPY VERSION ./VERSION
COPY backend/app ./app
COPY backend/alembic ./alembic
COPY backend/alembic.ini ./
# Built frontend assets (served as static files)
COPY --from=frontend-builder /build/frontend/dist ./static
# Data directory for SQLite
RUN mkdir -p /data && chmod 755 /data
ENV PORT=3000
ENV DATABASE_PATH=/data/observer.db
ENV DATABASE_URL=sqlite+aiosqlite:////data/observer.db
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
VOLUME ["/data"]
EXPOSE 3000
COPY docker-entrypoint.sh ./
RUN chmod +x docker-entrypoint.sh
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD python -c "import os, urllib.request; urllib.request.urlopen(f'http://localhost:{os.environ.get(\"PORT\", \"3000\")}/api/docs')" || exit 1
ENTRYPOINT ["./docker-entrypoint.sh"]