# syntax=docker/dockerfile:1 # Keep this syntax directive! It's used to enable Docker BuildKit # Based on https://github.com/python-poetry/poetry/discussions/1879?sort=top#discussioncomment-216865 # but I try to keep it updated (see history) ################################ # PYTHON-BASE # Sets up all our shared environment variables ################################ FROM python:3.9-slim as python-base # python ENV PYTHONUNBUFFERED=1 \ # prevents python creating .pyc files PYTHONDONTWRITEBYTECODE=1 \ \ # pip PIP_DISABLE_PIP_VERSION_CHECK=on \ PIP_DEFAULT_TIMEOUT=100 \ \ # poetry # https://python-poetry.org/docs/configuration/#using-environment-variables POETRY_VERSION=1.3.2 \ # make poetry install to this location POETRY_HOME="/opt/poetry" \ # make poetry create the virtual environment in the project's root # it gets named `.venv` POETRY_VIRTUALENVS_IN_PROJECT=true \ # do not ask any interactive question POETRY_NO_INTERACTION=1 \ \ # paths # this is where our requirements + virtual environment will live PYSETUP_PATH="/opt/pysetup" \ VENV_PATH="/opt/pysetup/.venv" # prepend poetry and venv to path ENV PATH="$POETRY_HOME/bin:$VENV_PATH/bin:$PATH" ################################ # BUILDER-BASE # Used to build deps + create our virtual environment ################################ FROM python-base as builder-base RUN apt-get update \ && apt-get install --no-install-recommends -y \ # deps for installing poetry curl \ # deps for building python deps build-essential # install poetry - respects $POETRY_VERSION & $POETRY_HOME # The --mount will mount the buildx cache directory to where # Poetry and Pip store their cache so that they can re-use it RUN --mount=type=cache,target=/root/.cache \ curl -sSL https://install.python-poetry.org | python3 - # copy project requirement files here to ensure they will be cached. WORKDIR $PYSETUP_PATH COPY poetry.lock pyproject.toml ./ # install runtime deps - uses $POETRY_VIRTUALENVS_IN_PROJECT internally RUN --mount=type=cache,target=/root/.cache \ poetry install --without=dev ################################ # DEVELOPMENT # Image used during development / testing ################################ FROM python-base as development ENV FASTAPI_ENV=development WORKDIR $PYSETUP_PATH # copy in our built poetry + venv COPY --from=builder-base $POETRY_HOME $POETRY_HOME COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH # quicker install as runtime deps are already installed RUN --mount=type=cache,target=/root/.cache \ poetry install --with=dev # will become mountpoint of our code WORKDIR /app EXPOSE 8000 CMD ["uvicorn", "--reload", "main:app"] ################################ # PRODUCTION # Final image used for runtime ################################ FROM python-base as production ENV FASTAPI_ENV=production COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH COPY ./app /app/ WORKDIR /app CMD ["gunicorn", "-k", "uvicorn.workers.UvicornWorker", "main:app"]