# LEGO Instructions Manager # Created by: Jess Rogerson (yelling commands at Claude.AI) FROM python:3.12-slim ENV PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ PIP_NO_CACHE_DIR=1 \ FLASK_APP=run.py \ FLASK_ENV=production \ UPLOAD_FOLDER=/data/uploads \ BACKUP_FOLDER=/data/backups # libpq for psycopg, and the runtime libs PyMuPDF/Pillow need for # PDF thumbnails and image handling. # # fonts-dejavu-core is not optional: python:3.12-slim ships no font files, # and without one Pillow silently falls back to a 10-pixel bitmap font. # Part labels then print letters under a millimetre tall - legible on # screen, unreadable on the sticker. RUN apt-get update && apt-get install -y --no-install-recommends \ libpq5 \ libjpeg62-turbo \ zlib1g \ libfreetype6 \ fonts-dejavu-core \ curl \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY requirements-docker.txt ./ RUN pip install -r requirements-docker.txt COPY . . # Non-root. /data is chowned here; the entrypoint fixes up volume # ownership at runtime since a fresh volume mounts as root. RUN useradd --create-home --uid 1000 lim \ && mkdir -p /data/uploads /data/backups \ && chown -R lim:lim /app /data \ && chmod +x /app/docker/entrypoint.sh VOLUME ["/data"] EXPOSE 8000 HEALTHCHECK --interval=30s --timeout=5s --start-period=40s --retries=3 \ CMD curl -fsS http://localhost:8000/ >/dev/null || exit 1 ENTRYPOINT ["/app/docker/entrypoint.sh"] # One worker, many threads — on purpose. The backup job registry lives in # process memory, so with multiple workers the progress-polling request can # land on a worker that has never heard of the job. Threads keep it coherent # and are plenty for a household-sized instance. CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "1", "--threads", "8", \ "--timeout", "600", "--access-logfile", "-", "--error-logfile", "-", \ "run:app"]