Выбор base image для Python
Сборка Python-образа начинается с выбора FROM .... Этот выбор определяет: размер образа, скорость сборки, какие зависимости поставятся, безопасность, удобство дебага. Для Junior DE это часто первый момент, где «работает» vs «работает плохо» — потому что выбор python:3.13-alpine для DE-приложения с pandas — это часовое мучение со сборкой.
В этом уроке: разница между python:3.13, python:3.13-slim, python:3.13-alpine, distroless. Почему slim — золотая середина для DE. Когда стоит выходить за рамки.
Что такое base image
Когда ты пишешь FROM python:3.13-slim, Docker тянет образ python:3.13-slim с Docker Hub. Этот образ собран maintainer’ами Python (официальная команда docker-library) и содержит:
- ОС-базу (Debian / Alpine / другая).
- Python interpreter нужной версии.
- pip, setuptools, wheel.
- Минимальный набор системных библиотек, чтобы Python работал (libssl, libffi, etc.).
Выбор base — это выбор ОС + размера + предустановленных пакетов.
Дистрибутивы Linux: Debian, RHEL, Arch, Alpine
python:3.13 (full)
Размер: ~1 ГБ.
База: Debian 12 (Bookworm), полный.
Что внутри: всё, что есть в debian:12 (gcc, make, git, curl, vim, man-pages, …), плюс Python. Самый «жирный», но удобный для разработки — большая часть build deps уже есть, никаких сюрпризов.
Когда брать: редко. Только если нужны GCC, build-essentials прямо в финальном образе (например, для пересборки native libs во время старта). В 99% случаев избыточен.
FROM python:3.13
# 1 ГБ образ
python:3.13-slim (slim)
Размер: ~150 МБ.
База: Debian 12 slim — Debian с урезанными man-pages, locale, без многих утилит.
Что внутри: Python + минимум системных библиотек. Нет gcc, нет git, нет curl (его надо apt-get install).
Когда брать: большинство DE-приложений. Slim — это compromise между размером и совместимостью. Любая pip-зависимость с native code (psycopg, numpy, pandas, lxml, cryptography) собирается прозрачно — либо есть wheel под manylinux2014 (Debian-compatible), либо собирается через apt-get install build-essential gcc + pip install.
Это стандарт для production-Python в Docker. Когда сомневаешься — берёшь slim.
FROM python:3.13-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc=4:12.* \
libpq-dev=15.* \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
python:3.13-alpine (alpine)
Размер: ~50 МБ.
База: Alpine Linux — минималистичный дистрибутив на musl libc и BusyBox.
Кажется привлекательным: маленький, быстрый. Но musl libc — это ключевая разница, которая ломает Python-экосистему.
Почему alpine плох для DE
Python wheels на PyPI собираются под manylinux — стандарт, который требует glibc (стандартный libc на Linux). Alpine использует musl — альтернативный libc. Они бинарно несовместимы.
Что это значит на практике:
FROM python:3.13-alpine
RUN pip install pandas
pip ищет wheel для pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl. Если есть — отлично, ставит за секунды. Если нет — pip пытается собрать pandas из исходников. Сборка pandas с нуля требует gcc, gfortran, и около 10 минут CPU-времени. Образ распухает с 50 МБ до 700 МБ только за счёт build-tools.
В 2024-2025 ситуация улучшилась — большинство популярных пакетов выпускают musllinux wheels. Но не всё:
- pandas — есть musl wheel.
- numpy — есть.
- scipy — есть.
- pyarrow — нет musl wheel под все версии. На alpine надо собирать из исходников. Около 20 минут.
- polars — есть.
- duckdb — есть.
- confluent-kafka — собирается с натяжкой.
- psycopg[c] — есть musl wheel.
Для проекта с pyarrow / sklearn / TensorFlow — alpine лишает тебя сна. Сборка будет занимать 30 минут, образ — 1.5 ГБ (со всеми build-tools).
Не используй python:3.13-alpine для DE-проектов, если только не уверен, что все зависимости имеют musllinux-wheels. Меньше размер образа (50 МБ vs 150 МБ slim) не стоит часов сборки и проблем совместимости. Для веб-API без pandas (FastAPI + sqlalchemy + asyncpg) — alpine ОК.
distroless (Google)
Размер: ~50 МБ (python3-debian12).
База: «distroless» — нет shell, нет package manager, только Python и минимум runtime libs.
Что внутри: Python, libssl, libcrypto, libcrypt, libz, тд — всё что Python нужно для работы. Нет sh, нет apt, нет ls.
FROM python:3.13-slim AS builder
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
FROM gcr.io/distroless/python3-debian12
COPY --from=builder /root/.local /root/.local
ENV PATH=/root/.local/bin:$PATH
COPY . /app
WORKDIR /app
ENTRYPOINT ["python", "main.py"]
Distroless обычно используется в multi-stage: builder ставит зависимости, distroless runtime их забирает.
Преимущества:
- Security: меньше attack surface (нет shell — нечего эксплойтить).
- Compliance: легче пройти security audit.
- Размер: 50-100 МБ.
Недостатки:
- Дебаг сложен: нельзя
docker exec -it bash(см. модуль 14 урок 2). Для дебага —:debug-вариант с busybox. - Стороннее ПО ставить негде: если приложение хочет вызвать
curl— нельзя. - Glibc-compatibility issues: основано на debian, так что glibc-wheels работают, но не все мелкие либы.
Когда брать: production-grade образы для прода, когда команда уже умеет дебажить через :debug и nsenter. Для junior — overkill, slim комфортнее.
chainguard images
Размер: ~30-80 МБ.
База: альтернатива distroless от Chainguard, основана на Wolfi (musl + glibc-совместимая ОС, специально под безопасность).
FROM cgr.dev/chainguard/python:latest
Преимущества: минимум CVE (Chainguard сами поддерживают forks популярных пакетов с актуальными патчами), маленький размер, OCI-compliant.
Недостатки: проприетарные source (бесплатна latest, исторические — за деньги). Меньше известно community wise.
Для DE 2026 это активная альтернатива distroless — стоит знать, попробовать в pet-проекте, для production команды решают.
Сравнительная таблица
| Образ | Размер | Базовая ОС | CVE (типично) | Совместимость pip | Когда брать |
|---|---|---|---|---|---|
| python:3.13 | ~1 ГБ | Debian full | 40-60 | full | Никогда (избыточен) |
| python:3.13-slim | ~150 МБ | Debian slim (glibc) | 30-50 | full (glibc, manylinux) | Default DE |
| python:3.13-alpine | ~50 МБ | Alpine (musl) | 10-20 | musllinux only | Простые web/CLI |
| distroless/python3 | ~50 МБ | Debian (glibc) | 5-15 | full | Production с opinions |
| chainguard/python | ~30-80 МБ | Wolfi | 0-5 | full | Production security focus |
Pin tag версии
python:3.13 — последний 3.13.x. python:3.13.0 — конкретно 3.13.0.
В production предпочитай specific:
FROM python:3.13.0-slim
Это гарантирует, что через год сборка даст идентичный результат. python:3.13-slim может через месяц стать 3.13.1 с потенциальными изменениями.
Самый строгий вариант — digest:
FROM python:3.13.0-slim@sha256:abc123...
Привязка к конкретному SHA256 образа. Никаких сюрпризов вообще. Цена — каждое обновление = ручная замена digest.
Для junior — pin’и до patch-версии (3.13.0-slim), digest можно опустить.
Multi-arch (ARM64 + x86_64)
С 2020 года Apple Silicon (M1/M2/M3/M4) — ARM64. Большинство облаков предлагают ARM64 (AWS Graviton, GCP T2A) с скидкой 20-40%. Образы должны работать на обоих.
Все официальные python-образы — multi-arch. docker pull python:3.13-slim на M1 mac автоматически потянет ARM64 версию.
Проблемы:
- Не все wheels на PyPI собраны под ARM64. Некоторые экзотические пакеты падают на M1.
- Если ты собираешь образ на x86 для деплоя на ARM (или наоборот), нужен
docker buildxс--platform linux/arm64,linux/amd64.
Проверка:
docker inspect python:3.13-slim --format '{{.Architecture}}'
Покажет либо amd64, либо arm64 — зависит от хоста.
Реальный кейс выбора
DE-проект: Airflow + pandas + sqlalchemy + psycopg + pyarrow + duckdb. Что выбрать.
python:3.13-alpine— пробуем.pip install pyarrowкрутится 15 минут — нет musl wheel в 2026 для pyarrow 15. Решение: отказываемся.python:3.13-slim—pip install ...за 40 секунд. Образ 280 МБ. Дебаг через bash. Берём.distroless/python3— финальный размер 150 МБ. Но дебаг сложнее, в команде junior’ы. Откладываем на потом.
Итоговый Dockerfile:
FROM python:3.13-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq5=15.* \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
RUN useradd -m -u 1000 app
COPY --chown=app:app . .
USER app
CMD ["python", "etl.py"]
280 МБ, собирается за 50 секунд, удобный дебаг. Это про-junior baseline.
Попробуй сам
- Собери одно простое приложение (
pip install pandas requests) на трёх образах:
Замени FROM наFROM python:3.13-slim RUN pip install pandas requestspython:3.13-alpineиpython:3.13. Замерь размеры и время сборки. Сравни. - На alpine попробуй
pip install pyarrow— будь готов к 15-минутной сборке (или fail). - Проверь архитектуру образа:
docker inspect python:3.13-slim --format '{{.Architecture}}'. На M-маке — arm64, на x86 — amd64. - Сравни CVE:
trivy image python:3.13vstrivy image python:3.13-slimvstrivy image python:3.13-alpine. Запиши количество HIGH/CRITICAL. - Бонус: попробуй chainguard или distroless. Для distroless — multi-stage с builder.