# Alpine because there is nothing to compile and nothing to link against: the # application is one Python module with no dependencies outside the standard # library, so the base image is almost the whole image. FROM python:3.13-alpine AS runtime ENV PYTHONUNBUFFERED=1 WORKDIR /app COPY pyproject.toml README.md ./ COPY music_curator.py ./ RUN pip install --no-cache-dir . \ && rm -rf build music_curator.egg-info # The store lives here. Mount a volume over it, or the history is re-downloaded # from Last.fm every time the container is recreated. ENV MUSIC_CURATOR_DB=/data/curator.db VOLUME ["/data"] # Runs as root by default so a bind-mounted dataset of any ownership is # writable. Override with `user:` in compose to run as the dataset's owner. ENTRYPOINT ["music-curator"] # Test stage: build it with `--target test`; a failing test fails the build. # The suite talks to a fake transport, never to Last.fm, so it needs no # credentials and no network. The published image is the `runtime` stage above # and carries none of this. FROM runtime AS test RUN pip install --no-cache-dir pytest COPY pytest.ini ./ COPY tests ./tests RUN python -m pytest