ppt-web / Dockerfile
26fwyzpz6f-max
Clean deploy without binary files
6aecb2e
Raw
History Blame Contribute Delete
6.49 kB
# LandPPT Docker Image
# Multi-stage build for minimal image size
# Build stage
FROM python:3.11-slim-bookworm AS builder
# Set environment variables for build
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1 \
PLAYWRIGHT_BROWSERS_PATH=/opt/playwright-browsers \
PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=1
# Install build dependencies
ARG APT_DEBIAN_URL=http://deb.debian.org/debian
ARG APT_SECURITY_URL=http://deb.debian.org/debian-security
RUN set -eux; \
if [ -f /etc/apt/sources.list.d/debian.sources ]; then \
sed -i "s|http://deb.debian.org/debian|${APT_DEBIAN_URL}|g" /etc/apt/sources.list.d/debian.sources; \
sed -i "s|http://deb.debian.org/debian-security|${APT_SECURITY_URL}|g" /etc/apt/sources.list.d/debian.sources; \
elif [ -f /etc/apt/sources.list ]; then \
sed -i "s|http://deb.debian.org/debian|${APT_DEBIAN_URL}|g" /etc/apt/sources.list; \
sed -i "s|http://deb.debian.org/debian-security|${APT_SECURITY_URL}|g" /etc/apt/sources.list; \
fi; \
apt-get -o Acquire::Retries=5 -o Acquire::http::Timeout=30 update; \
apt-get install -y --no-install-recommends \
build-essential \
ca-certificates \
curl \
git \
libpq-dev \
libatomic1 \
; \
rm -rf /var/lib/apt/lists/*
# Install uv for faster dependency management
RUN pip install --no-cache-dir uv
# Create a dedicated virtualenv for runtime dependencies.
# Note: `uv sync` defaults to `.venv`; we explicitly sync to this env via `--active`.
RUN uv venv /opt/venv --python python3.11
ENV VIRTUAL_ENV=/opt/venv \
PATH=/opt/venv/bin:$PATH
# Set work directory and copy dependency files
WORKDIR /app
COPY pyproject.toml uv.lock* uv.toml README.md ./
COPY src/ ./src/
# Install Python dependencies using uv
# uv sync will create venv at UV_PROJECT_ENVIRONMENT and install all dependencies
RUN uv sync --active --no-dev --frozen --extra-index-url=https://pypi.apryse.com && \
# Clean up build artifacts
find /opt/venv -name "*.pyc" -delete && \
find /opt/venv -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true
# Sanity check: fail the build early if core runtime deps are missing.
RUN /opt/venv/bin/python -c "import fastapi, uvicorn, edge_tts; print('Core deps installed')"
# Install Playwright browsers in builder stage
RUN mkdir -p /opt/playwright-browsers && \
/opt/venv/bin/python -m playwright install chromium || \
(echo "Retrying with mirror..." && \
PLAYWRIGHT_DOWNLOAD_HOST=https://npmmirror.com/mirrors/playwright \
/opt/venv/bin/python -m playwright install chromium)
# Production stage
FROM python:3.11-slim-bookworm AS production
# Set environment variables
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONPATH=/app/src:/opt/venv/lib/python3.11/site-packages \
PATH=/opt/venv/bin:$PATH \
PLAYWRIGHT_BROWSERS_PATH=/opt/playwright-browsers \
HOME=/root \
VIRTUAL_ENV=/opt/venv \
PORT=7860 \
WORKERS=4 \
RELOAD=false
# Allow overriding Debian mirrors (useful in restricted networks).
ARG APT_DEBIAN_URL=http://deb.debian.org/debian
ARG APT_SECURITY_URL=http://deb.debian.org/debian-security
# Install essential runtime dependencies
RUN set -eux; \
if [ -f /etc/apt/sources.list.d/debian.sources ]; then \
sed -i "s|http://deb.debian.org/debian|${APT_DEBIAN_URL}|g" /etc/apt/sources.list.d/debian.sources; \
sed -i "s|http://deb.debian.org/debian-security|${APT_SECURITY_URL}|g" /etc/apt/sources.list.d/debian.sources; \
elif [ -f /etc/apt/sources.list ]; then \
sed -i "s|http://deb.debian.org/debian|${APT_DEBIAN_URL}|g" /etc/apt/sources.list; \
sed -i "s|http://deb.debian.org/debian-security|${APT_SECURITY_URL}|g" /etc/apt/sources.list; \
fi; \
apt-get -o Acquire::Retries=5 -o Acquire::http::Timeout=30 update; \
apt-get install -y --no-install-recommends \
ffmpeg \
poppler-utils \
libmagic1 \
libpq5 \
ca-certificates \
curl \
wget \
libgomp1 \
libatomic1 \
fonts-liberation \
fonts-noto-cjk \
fontconfig \
netcat-openbsd \
libjpeg62-turbo \
libxrender1 \
libfontconfig1 \
libx11-6 \
libxext6 \
# Chromium/Playwright runtime dependencies
libnss3 \
libatk1.0-0 \
libatk-bridge2.0-0 \
libcups2 \
libdrm2 \
libxkbcommon0 \
libxcomposite1 \
libxdamage1 \
libxfixes3 \
libxrandr2 \
libgbm1 \
libasound2 \
libpango-1.0-0 \
libcairo2 \
# GPU acceleration support (optional, for NVIDIA containers)
libegl1 \
libgl1 \
libgles2 \
; \
fc-cache -fv; \
apt-get clean; \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /root/.cache
# Create non-root user (for compatibility, but run as root)
RUN groupadd -r landppt && \
useradd -r -g landppt -m -d /home/landppt landppt
# Copy Python packages from builder
COPY --from=builder /opt/venv /opt/venv
# Copy Playwright browsers from builder
COPY --from=builder /opt/playwright-browsers /opt/playwright-browsers
# Sanity check: ensure the copied venv is usable in the runtime image.
RUN /opt/venv/bin/python -c "import fastapi, uvicorn; print('Runtime venv OK')"
# Set permissions for landppt user and playwright browsers
RUN chown -R landppt:landppt /home/landppt && \
chmod -R 755 /opt/playwright-browsers
# Set work directory
WORKDIR /app
# Copy application code (minimize layers)
COPY run.py ./
COPY src/ ./src/
COPY template_examples/ ./template_examples/
COPY docker-healthcheck.sh docker-entrypoint.sh /usr/local/bin/
COPY .env.example ./.env
# Create directories and set permissions in one layer
RUN sed -i 's/\r$//' /usr/local/bin/docker-healthcheck.sh /usr/local/bin/docker-entrypoint.sh && \
chmod +x /usr/local/bin/docker-healthcheck.sh /usr/local/bin/docker-entrypoint.sh && \
mkdir -p temp/ai_responses_cache temp/style_genes_cache temp/summeryanyfile_cache temp/templates_cache \
research_reports lib/Linux lib/MacOS lib/Windows uploads data && \
chown -R landppt:landppt /app /home/landppt && \
chmod -R 755 /app /home/landppt && \
chmod 666 /app/.env
# Expose port
EXPOSE 7860
# Minimal health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=2 \
CMD ["/usr/local/bin/docker-healthcheck.sh"]
# Set entrypoint and command
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["/opt/venv/bin/python", "run.py"]