← Назад к вопросам

Создавал с нуля образы для Docker

2.0 Middle🔥 91 комментариев
#DevOps и инфраструктура

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Создание Docker образов с нуля

Ответ: Да, и это важный навык

Да, я создавал Docker образы с нуля и регулярно это делаю. Это один из ключевых навыков DevOps-мышления, который ценится у Python-разработчиков.

Что я понимаю в Docker

1. Основы Dockerfile

Я знаю, как писать эффективные Dockerfile:

# Многослойная сборка для оптимизации размера
FROM python:3.11-slim as builder

WORKDIR /app

# Установка зависимостей в отдельный слой
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Финальный образ (только runtime)
FROM python:3.11-slim

WORKDIR /app
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY . .

EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0"]

Ключевые практики:

  • Multi-stage build (уменьшает размер)
  • Слой зависимостей отдельно (кэширование)
  • Slim образы вместо full (экономия места)
  • .dockerignore (исключаем лишнее)

2. Оптимизация образов

# ПЛОХО: большой образ, медленное обновление
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3 python3-pip

# ХОРОШО: маленький и быстрый
FROM python:3.11-slim
RUN pip install --no-cache-dir -r requirements.txt

Что я оптимизирую:

  • Размер базового образа (slim, alpine)
  • Кэширование слоёв (часто меняющийся код в конце)
  • Удаление лишних файлов
  • Многослойная сборка

3. docker-compose для разработки

Я пишу compose файлы для локальной разработки:

version: '3.9'

services:
  app:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
    volumes:
      - .:/app
    depends_on:
      - db
      - redis
    command: uvicorn main:app --host 0.0.0.0 --reload

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: mydb
    volumes:
      - postgres_data:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  postgres_data:

4. Проблемы, которые я решал

Проблема 1: Образ слишком большой

# ДО: 1.2 GB
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3 pip

# ПОСЛЕ: 150 MB
FROM python:3.11-slim
# Multi-stage build добавляет ещё экономию

Проблема 2: Зависимости не кэшируются

# ПЛОХО: pip install выполняется при каждом изменении кода
COPY . .
RUN pip install -r requirements.txt

# ХОРОШО: зависимости кэшируются
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .

Проблема 3: Образ не работает в production

# Забыли USER directive
RUN pip install -r requirements.txt
CMD ["uvicorn", "main:app"]  # Работает локально, падает в prod

# ПРАВИЛЬНО:
RUN useradd -m appuser
USER appuser
CMD ["uvicorn", "main:app"]

Примеры реальных образов

FastAPI приложение

FROM python:3.11-slim

WORKDIR /app

# Системные зависимости
RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc && rm -rf /var/lib/apt/lists/*

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

RUN useradd -m appuser && chown -R appuser:appuser /app
USER appuser

EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD python -c "import requests; requests.get('http://localhost:8000/health')"

CMD ["uvicorn", "main:app", "--host", "0.0.0.0"]

Worker для Celery

FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

RUN useradd -m celery
USER celery

CMD ["celery", "-A", "tasks", "worker", "--loglevel=info"]

Инструменты и практики

Скрипты для сборки:

#!/bin/bash
# build.sh

VERSION=$(git rev-parse --short HEAD)
DOCKER_REGISTRY="registry.example.com"

docker build -t ${DOCKER_REGISTRY}/myapp:${VERSION} .
docker push ${DOCKER_REGISTRY}/myapp:${VERSION}

# Автоматическая сборка при пушe в git

Проверка безопасности:

# Сканирование образа на уязвимости
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy image myapp:latest

Что я знаю про registry

# Вход в Docker Hub
docker login

# Tag образа
docker tag myapp:latest myusername/myapp:latest

# Push в registry
docker push myusername/myapp:latest

# Для приватного registry
docker tag myapp:latest 192.168.1.100:5000/myapp:latest
docker push 192.168.1.100:5000/myapp:latest

Kubernetes и Helm (опционально)

Я также создавал образы для Kubernetes:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: app
        image: myapp:1.0
        ports:
        - containerPort: 8000
        livenessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 30
          periodSeconds: 10

Итог

Да, я комфортно создаю Docker образы и пишу конфигурации. Это важно для:

  • Локальной разработки (docker-compose)
  • CI/CD пайплайнов
  • Production deployments
  • DevOps сотрудничества