Упакуйте ваше приложение FastAPI с помощью «Distroless» Docker Images

Distroless Docker Images — это проект, предложенный компанией Google для создания более компактных контейнеров. В описании проекта говорится, что это «образы докеров, ориентированные на язык, без операционной системы». Звучит интересно, правда?

По сравнению с обычными базовыми образами, такими как ubuntu, alpine, debian, которые содержат множество пакетов ОС и библиотек, которые могут быть не нужны для вашего приложения, Distroless Images содержат только то, что вам нужно для работы вашего приложения.

Стоит отметить, что Distroless контейнеры не всегда являются наиболее безопасным решением, как объясняет RedHat в этой статье.

Хотя упаковать приложение python было бы сложно, поскольку его стандартная библиотека полагается на некоторые высокоуровневые возможности ОС, это возможно.

Бездистрольные контейнеры Python требуют многоэтапного процесса сборки, поскольку образ gcr.io/distroless/python3 не имеет ни pip, ни даже easy_install.

Давайте попробуем упаковать FastAPI api с помощью «Distroless» Docker Images.

Вот пример api сервера:

import fastapi, uvicorn
from starlette.requests import Request
import prometheus_client
import os

api = fastapi.FastAPI()

REQUESTS = prometheus_client.Counter(
    'requests', 'Application Request Count',
    ['endpoint']
)

@api.get('/ping')
def index(request: Request):
    REQUESTS.labels(endpoint='/ping').inc()
    return "pong"

@api.get('/metrics')
def metrics():
    return fastapi.responses.PlainTextResponse(
        prometheus_client.generate_latest()
    )

if __name__ == "__main__":
    print("Starting webserver...")
    uvicorn.run(
        api, 
        host="0.0.0.0",
        port=int(os.getenv("PORT", 8080)),
        debug=os.getenv("DEBUG", False),
        log_level=os.getenv('LOG_LEVEL', "info"),
        proxy_headers=True
    )
Вход в полноэкранный режим Выход из полноэкранного режима

В качестве менеджера пакетов мы будем использовать Pipenv. Вот наш Pipfile:

[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
fastapi = "==0.77.1"
uvicorn = "==0.17.6"
prometheus-client = "==0.14.1"
Jinja2 = "==3.1.2"

[dev-packages]

[requires]
python_version = "3.10"
Войти в полноэкранный режим Выйти из полноэкранного режима

Итак, в итоге у меня получился следующий Dockerfile (прокомментированный), позволяющий упаковать FastAPI-приложение с образом Python без дистрибутива.

Первый этап:

FROM python:3.10-slim AS base

# Setup env

## Avoid to write .pyc files on the import of source modules
ENV PYTHONDONTWRITEBYTECODE 1

# Enable fault handler
ENV PYTHONFAULTHANDLER 1
Вход в полноэкранный режим Выход из полноэкранного режима

Второй этап:

# Dependencies
FROM base AS python-deps

### Install pipenv and compilation dependencies
RUN pip install pipenv 
    && apt-get update 
    && apt-get install -y --no-install-recommends gcc

### Install python dependencies in /.venv
COPY Pipfile .
COPY Pipfile.lock .

# Allows to install the pipenv packages into the project instead of home user
# --deploy
RUN PIPENV_VENV_IN_PROJECT=1 pipenv install --deploy
Войти в полноэкранный режим Выйти из полноэкранного режима

Третий этап:

# Runtime
FROM gcr.io/distroless/python3

WORKDIR /app

# Copy the python packages because the distroless base image does 
COPY --from=python-deps /.venv/lib/python3.10/site-packages /app/site-packages

# Set the Python path where the interpreter will look for the packages
ENV PYTHONPATH /app/site-packages
COPY . .

EXPOSE 8080
ENTRYPOINT ["python", "app.py"]
Войти в полноэкранный режим Выход из полноэкранного режима

Полученное изображение было размером около 25 Мб.

Весь код можно найти на моем репозитории github.

Если у вас есть какие-либо соображения по поводу того, стоит или не стоит использовать «Distroless» для python-приложений, не стесняйтесь оставлять комментарии.

Оцените статью
devanswers.ru
Добавить комментарий