Антипаттерн 1: Тяжёлый базовый образ вместо целевого
В примере из лекции используется FROM ubuntu:18.04 как базовый образ для Python-приложения. Ubuntu содержит сотни пакетов, которые не нужны приложению.
Из лекции (старое)
# Dockerfile (из лекции)
FROM ubuntu:18.04
RUN apt-get update && apt-get install -y python3
COPY . /app
WORKDIR /app
CMD ["python3", "app.py"]
Размер образа: ~180 МБ только базовый. Устаревшая Ubuntu 18.04 (EOL апрель 2023).
Современный подход
# Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python3", "app.py"]
python:3.12-slim ~ 50 МБ. Python уже установлен. Актуальная версия.
Антипаттерн 2: ADD для скачивания URL вместо COPY
В примере сложного Dockerfile из лекции использовалась инструкция ADD с URL. Это считается антипаттерном — скачанный файл не верифицируется, сборка зависит от доступности внешнего ресурса.
Из лекции (старое)
# Dockerfile (из лекции)
FROM python:3.7.2-alpine3.8
ADD https://raw.githubusercontent.com/...
/my_app_directory
Проблемы: зависит от интернета при сборке, нет проверки целостности, сложно кешировать.
Современный подход
# Dockerfile
FROM python:3.12-alpine
# Скачать заранее, проверить хеш, положить в проект
# Или использовать пакетный менеджер
COPY vendor/ /app/vendor/
# ADD только для .tar.gz с локальной распаковкой:
ADD archive.tar.gz /app/
COPY — явно, воспроизводимо, кешируется правильно.
Антипаттерн 3: Запуск под root
По умолчанию все команды в Dockerfile выполняются от пользователя root. Если приложение скомпрометировано, злоумышленник получает root-доступ к файловой системе контейнера.
Из лекции (старое)
# Dockerfile (из лекции)
FROM debian:stable-slim
RUN apt-get update && apt-get install -y curl
COPY fetch_data.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/fetch_data.sh
CMD ["/usr/local/bin/fetch_data.sh"]
# Всё выполняется под root!
Современный подход
# Dockerfile
FROM debian:stable-slim
RUN apt-get update && apt-get install -y curl \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Создать непривилегированного пользователя
RUN useradd -m -u 1001 appuser
COPY fetch_data.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/fetch_data.sh
# Переключиться на непривилегированного пользователя
USER appuser
CMD ["/usr/local/bin/fetch_data.sh"]
Антипаттерн 4: Пароль в переменной окружения Dockerfile
Хардкодить пароли через ENV в Dockerfile — грубая ошибка безопасности. Они попадают в историю образа и видны через docker history и docker inspect.
Небезопасно (НИКОГДА ТАК)
# Dockerfile — ОПАСНО!
FROM mysql:8.0
ENV MYSQL_ROOT_PASSWORD=my-hardcoded-pw
# Пароль виден в docker inspect и docker history!
Правильно
# Dockerfile
FROM mysql:8.0
# Пароли не указываем здесь!
# EXPOSE 3306
# Терминал — передаём при запуске
docker run -d \
-e MYSQL_ROOT_PASSWORD=secret \
mysql:8.0
Или используйте Docker Secrets / .env файл с Docker Compose.
Антипаттерн 5: Несколько RUN вместо объединённого
Каждый RUN создаёт новый слой. Разбитые команды — больше слоёв, больше итоговый образ.
Из лекции (устарело)
# Dockerfile
RUN apt-get update
RUN apt-get upgrade
RUN apt-get install -y curl
RUN apt-get install -y git
# 4 слоя, кеш пакетов не очищается
Современный подход
# Dockerfile
RUN apt-get update && apt-get install -y \
curl \
git \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# 1 слой, кеш очищен, образ меньше
Антипаттерн 6: Порядок слоёв — код перед зависимостями
Неоптимально (частая ошибка)
# Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY . . # 1. копируем ВСЁ
RUN pip install -r requirements.txt # 2. ставим зависимости
CMD ["python3", "app.py"]
# При любом изменении кода → кеш requirements сбрасывается!
Оптимально (кеш зависимостей сохраняется)
# Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt . # 1. только requirements
RUN pip install --no-cache-dir -r requirements.txt # 2. кешируется!
COPY . . # 3. код — меняется часто
CMD ["python3", "app.py"]