Есть более одного способа кожи кошки, но этот рисунок заставляет мое сердце трепетать.
Контейнеризировать приложение Python
Asgi.py
в нашем приложении каталог
from fastapi import FastAPI app = FastAPI() @app.get("/") def hello(): return "World"
Dockerfile.
FROM python:3.7-buster as base ENV SHELL=/bin/bash \ USER=python \ UID=10001 # Create a user for the app to be owned by RUN set -eux; adduser \ --disabled-password \ --gecos "" \ --home "/var/lib/python3" \ --shell "/sbin/nologin" \ --no-create-home \ --uid "${UID}" \ "${USER}" # Manually create the users home directory RUN mkdir -p "/var/lib/python3" && chown -R "${USER}" /var/lib/python3 FROM base as build # Install the app requirements in its own layer. # Isolating the "build" stage from the application stage removes # some of the unwanted cruft that comes with install # python dependencies USER ${USER} RUN python -m pip install \ --user \ 'uvicorn[standard]' \ 'fastapi' \ 'wheel' FROM base COPY --from=build --chown=${USER} /var/lib/python3/.local /var/lib/python3/.local ENV PATH=$PATH:/var/lib/python3/.local/bin USER root ENTRYPOINT ["docker-entrypoint.sh"] COPY docker-entrypoint.sh /usr/bin/docker-entrypoint.sh # Create a designated location for the app as the python user USER ${USER} WORKDIR /usr/lib/python COPY ./app ./app CMD ["app.asgi:app"]
Входная точка
#!/bin/bash -e # If the CMD has not changed process it as a pure Python implementation if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ]; then set -- uvicorn "$@" --host 0.0.0.0 --http h11 --loop asyncio fi echo echo "Running $@" echo exec "$@"
Ломаться на этапы докера
Этот докер отделен на нескольких этапах, чтобы организовать функцией его этапа сборки. Многоступенчатая строгая полоски нашего применения ненужных файлов.
базовый этап
Первый этап псевдонимой как «база». Эти этапы загрузочные наши необходимые инструкции, которые доля остальных слоев. Пользователь позволяет нам устанавливать требования за пределами пользователя root.
Стадия сборки
Второй этап приносит внешние требования и устанавливает их как Python
Пользователь. Это полезно, потому что только пользователь .LOCAL
каталог должен быть скопирован на заключительном этапе. Копирование .LOCAL
Каталог приносит только требованиям, которые требуются приложение для запуска.
Безымянный этап приложения
Базовое изображение приложения начинается с чистого слоя с первого этапа. Удаление необходимости Redeclare любые уже предоставленные инструкции.
Требования могут быть скопированы на .местный
каталог, как они были установлены PIP. Слой приложений не основан на построить
слой, чтобы уменьшить оставшиеся влево, приведен PIP Установить
Отказ
Наконец, сам приложение копируется в каталог за пределами дома пользователя.
- https://www.docker.com/blog/containerized-python-development-part-1/
- https://stackoverflow.com/a/55757473/12429735
- https://github.com/nodejs/docker-node/blob/master/docker-entrypoint.sh
Оригинал: “https://dev.to/ndfishe/my-favorite-way-to-write-a-dockerfile-for-a-python-app-260i”