Уменьшение размера образов Docker имеет решающее значение для оптимизации рабочих процессов разработки, ускорения сборки и минимизации времени развертывания, а также для экономии ценного места для хранения.
На основе собственного опыта я обнаружил несколько эффективных стратегий, которые не только оптимизируют образы Docker, но и повышают общую производительность и эффективность. Вот руководство по передовым методам, которые я использовал и настоятельно рекомендую для создания компактных и эффективных образов Docker.
Используйте минимальный базовый Docker образ
Выбор минимального базового образа — один из самых эффективных способов уменьшить размер образа Docker. Минимальные базовые образы, такие как alpine
, scratch
, или debian-slim
, значительно меньше, чем более крупные базовые образы, такие как ubuntu
или debian
, поскольку в них есть только самое необходимое.
Пример с Python
Рассмотрим разницу в размере между типичным изображением Python на основе ubuntu
— и изображением Python на основе alpine
-:
Использование Ubuntu в качестве базового образа:
FROM python:3.11-slim
- Размер образа: примерно 60 МБ (Python 3.11 с базовым образом Ubuntu)
Использование Alpine в качестве базового изображения:
FROM python:3.11-alpine
- Размер образа: примерно 23 МБ (Python 3.11 с базовым образом Alpine)
Образ на основе Alpine примерно в 3 раза меньше, чем образ на основе Ubuntu. Такое значительное уменьшение размера связано с тем, что Alpine Linux — это минимальный дистрибутив, специально разработанный для сред Docker. Использование таких минимальных базовых образов не только уменьшает размер образа, но и снижает вероятность атаки, повышая безопасность.
Многоступенчатые сборки
Многоэтапные сборки позволяют отделить среду сборки от среды выполнения, гарантируя, что в конечный образ попадут только необходимые файлы. Такой подход помогает уменьшить размер конечного образа Docker, исключая инструменты сборки и зависимости, которые не нужны во время выполнения.
Пример с Python
Рассмотрим приложение на Python, в котором вы хотите использовать многоэтапные сборки, чтобы уменьшить размер итогового образа:
Многоступенчатая сборка Dockerfile:
# Build stage
FROM python:3.11-slim AS builder
WORKDIR /app
# Install build dependencies
COPY requirements.txt .
RUN pip install --user -r requirements.txt
# Copy application code
COPY . .
# Final stage
FROM python:3.11-slim
WORKDIR /app
# Install only runtime dependencies
COPY --from=builder /root/.local /root/.local
COPY . .
# Set the path to include user-installed packages
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "app.py"]
Сравнение размеров
- Без многоэтапных сборок: если вы используете одноэтапный Dockerfile, конечный образ будет включать в себя как зависимости сборки, так и код приложения. Например:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
- Размер образа: примерно 150 МБ (включая зависимости для сборки и выполнения).
При многоэтапной сборке: при использовании приведенного примера многоэтапной сборки итоговое изображение будет значительно меньше:
- Размер образа: примерно 60 МБ (содержит только зависимости времени выполнения и код приложения).
Удалите ненужные файлы
Очистка ненужных файлов, таких как кэш, временные файлы и зависимости сборки, является важным шагом в уменьшении размера образа Docker. Эта практика гарантирует, что ваш образ содержит только необходимые компоненты для запуска вашего приложения, при этом сводя к минимуму размер и потенциальную уязвимость.
Пример с Python
Вот пример того, как удалить ненужные файлы в Dockerfile для приложения на Python:
Перед очисткой:
FROM python:3.11-slim
WORKDIR /app
# Install build dependencies
COPY requirements.txt .
RUN pip install -r requirements.txt
# Copy application code
COPY . .
CMD ["python", "app.py"]
С очисткой:
FROM python:3.11-slim
WORKDIR /app
# Install build dependencies
COPY requirements.txt .
RUN pip install -r requirements.txt \
# Clean up temporary files and caches
&& rm -rf /root/.cache/pip
# Copy application code
COPY . .
CMD ["python", "app.py"]
Без очистки: в Dockerfile, где ненужные файлы не удаляются, размер образа может быть больше из-за остатков кэша и временных файлов:
- Размер образа: примерно 150 МБ (включая кэши сборки и ненужные файлы).
С помощью очистки: использование команд очистки, таких как rm -rf /root/.cache/pip
для удаления кэша и временных файлов, может уменьшить размер итогового изображения:
- Размер изображения: примерно 120 МБ (после очистки кэша и временных файлов).
Использовать .dockerignore
Файл
Файл .dockerignore
работает так же, как и файл .gitignore
, но для сборок Docker. Он определяет, какие файлы и каталоги следует исключить из контекста сборки Docker. Это помогает уменьшить размер контекста сборки, что приводит к более быстрой сборке и уменьшению размера образов Docker.
Преимущества использования .dockerignore
- Уменьшение размера контекста сборки: исключая ненужные файлы, вы минимизируете объем данных, отправляемых в демон Docker, что ускоряет процесс сборки.
- Меньшие по размеру образы Docker: исключение файлов, которые не нужны в конечном образе, позволяет не включать их, что помогает уменьшить размер образа.
- Повышенная эффективность сборки: меньшие контексты сборки означают, что Docker может более эффективно кэшировать слои, что приводит к более быстрой сборке.
Пример .dockerignore
Файл
Вот простой пример .dockerignore
файл:
.git
node_modules
*.log
.DS_Store
Без .dockerignore
:
- Когда ненужные файлы включаются в контекст сборки Docker, они отправляются в демон Docker и становятся частью образа Docker, даже если они не используются в конечном образе.
- Например, включение
.git
каталога илиnode_modules
папки может значительно увеличить размер контекста сборки..git
каталог может содержать несколько сотен мегабайт истории версий, аnode_modules
может добавить еще несколько сотен мегабайт зависимостей, которые не нужны в рабочем образе. - Влияние на размер контекста сборки: исключение файлов и каталогов, которые не нужны в конечном образе, помогает уменьшить размер контекста сборки, который в противном случае может достигать нескольких гигабайт в зависимости от размера и количества исключенных файлов. Приблизительный размер контекста сборки может составлять около 1 ГБ, если он включает в себя большой
.git
каталог,node_modules
и другие файлы, которые не нужны в образе.
С .dockerignore
:
- Используя
.dockerignore
файл для исключения ненужных файлов, вы ограничиваете контекст сборки только теми файлами, которые необходимы для приложения. - Это исключение может привести к значительному уменьшению контекста сборки. Например, исключение
.git
,node_modules
и других больших каталогов может уменьшить размер контекста с нескольких гигабайт до нескольких мегабайт. - Влияние на размер образа: хотя
.dockerignore
сам файл напрямую не уменьшает размер конечного образа Docker, он предотвращает добавление ненужных файлов в контекст сборки. Это приводит к более эффективному процессу сборки и помогает создать более компактный конечный образ, гарантируя включение только необходимых файлов. После исключения этих ненужных файлов размер контекста сборки может быть уменьшен до 50 МБ, что может значительно сократить время сборки и сделать конечный образ Docker более эффективным.
Минимизировать слои
В Docker каждая RUN
, COPY
и ADD
инструкция в вашем Dockerfile создает новый слой в результирующем образе. Эти слои могут увеличить общий размер образа Docker и повлиять на производительность сборки. Объединение команд в одну RUN
инструкцию помогает сократить количество слоев, что приводит к созданию более эффективного и компактного образа Docker.
Без минимизации слоя:
- Каждая отдельная инструкция (
RUN
,COPY
и т.д.) Создает новый слой в изображении Docker. Эти слои накапливаются и могут привести к увеличению размера изображения из-за промежуточных файлов, временных данных и дополнительных метаданных. - Например, использование отдельных
RUN
инструкций может привести к появлению нескольких слоёв, каждый из которых добавляет свои собственные метаданные и служебную информацию, что может увеличить размер итогового изображения. - Влияние на размер изображения: если вы используете несколько
RUN
инструкций, таких как:
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get clean
Использование нескольких RUN
инструкций может привести к увеличению размера изображения примерно до 150 МБ, при этом каждый слой увеличивает нагрузку.
С минимизацией слоя:
- Объединение команд в одну
RUN
инструкцию сокращает количество слоёв и помогает объединить изменения в меньшее количество более оптимизированных слоёв. - Например, объединение команд в одну
RUN
инструкция:
RUN apt-get update && apt-get install -y curl && apt-get clean
Объединение команд в одну RUN
инструкцию может уменьшить размер изображения примерно до 130 МБ. Такое уменьшение достигается за счет объединения изменений в меньшее количество слоев и минимизации ненужных промежуточных данных.
Использование специальных команд COPY:
Вместо того чтобы копировать целые каталоги в образ Docker, используйте специальные COPY
команды для включения только необходимых вам файлов. Такой подход позволяет избежать переноса ненужных файлов и уменьшить размер образа.
Пример:
COPY package.json .
COPY src/ src/
- Влияние на размер: копируя только определенные файлы и каталоги, вы избегаете включения нежелательных файлов, которые могут увеличить размер образа. Например, исключение файлов разработки или артефактов сборки может уменьшить размер образа на несколько мегабайт в зависимости от размера исключенных данных.
Используйте многоарочные изображения
Создание образов Docker с несколькими архитектурами обеспечивает совместимость с различными средами (например, ARM, x86). Такой подход оптимизирует образы для различных аппаратных платформ.
Пример:
- Влияние на размер: многоядерные изображения оптимизированы для конкретных архитектур, что потенциально уменьшает размер изображений, используемых на разных платформах. Это помогает избежать раздутых изображений, которые включают поддержку нескольких архитектур, когда нужна только одна.
Заключение
Эти рекомендации позволяют создавать более эффективные, безопасные и быстрые образы Docker, улучшая процессы управления контейнерами и их развёртывания.
Перевод инструкции: How I Cut Docker Image Size by 90%: Best Practices for Lean Containers