# ============================================================================= # yt-local — multi-stage, non-root, Tor-ready # ============================================================================= # --------------- build stage --------------- FROM python:3.11-alpine AS builder ENV PIP_NO_CACHE_DIR=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1 \ PYTHONDONTWRITEBYTECODE=1 RUN apk add --no-cache build-base libffi-dev COPY requirements.txt /tmp/requirements.txt RUN pip install --prefix=/install --no-cache-dir -r /tmp/requirements.txt # --------------- runtime stage --------------- FROM python:3.11-alpine LABEL maintainer="heckyel@riseup.net" LABEL org.opencontainers.image.source="https://git.sr.ht/~heckyel/yt-local" LABEL org.opencontainers.image.licenses="AGPL-3.0" ENV LANG=C.UTF-8 \ PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ HOME=/home/appuser # tor package creates its own tor user/group and /var/lib/tor # su-exec for privilege drop in entrypoint RUN apk add --no-cache tor su-exec # App user (non-root) RUN addgroup -g 1000 -S appgroup \ && adduser -u 1000 -S appuser -G appgroup -h /home/appuser # Python packages from builder COPY --from=builder /install /usr/local # Application source (root-owned, read-only for appuser) WORKDIR /srv/app COPY --chown=root:root . /srv/app/ # Compile translations (.po → .mo) RUN python manage_translations.py compile # Persistent data dir (settings.txt, data/, etc.) RUN mkdir -p /home/appuser/.yt-local/data \ && chown -R appuser:appgroup /home/appuser/.yt-local \ && chmod 750 /home/appuser/.yt-local VOLUME /home/appuser/.yt-local # Tor: fix perms on dirs already created by apk RUN chown tor:tor /var/lib/tor /var/log/tor \ && chmod 700 /var/lib/tor /var/log/tor # Entrypoints (root-owned, executable) COPY --chmod=755 entrypoint.sh entrypoint-tor.sh / EXPOSE 9010 HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ CMD sh -c 'python -c "import urllib.request; urllib.request.urlopen(\"http://127.0.0.1:9010\")"' ENTRYPOINT ["/entrypoint.sh"]