Рекомендации по созданию файлов Dockerfile производственного уровня

Docker стал одним из основных продуктов в мире разработки программного обеспечения. Все и их мамы пользуются гибкостью микросервисов. Но даже после быстрого роста его популярности я все еще вижу, как разработчики используют его неэффективно; очень многие овладели основами, но им не хватает этого экспертного преимущества, чтобы пройти весь путь.
Вы можете подумать, что написание Dockerfile должно быть простым процессом, но на самом деле для создания готового образа может потребоваться много времени.
Неоптимизированные DockerFiles обычно приводят к увеличению общего образа. Это создает больший вектор атаки для угроз и может увеличить вероятность уязвимостей системы безопасности. Все это плохие новости для вашего приложения.
Сегодня мы сосредоточимся на некоторых передовых методах создания файлов Docker для создания высококачественных и эффективных образов.
# 1 — Использование инструмента многоэтапной сборки
В 2017 году был выпущен Docker 17.06 CE, а вместе с ним и многоэтапный инструмент сборки. Это была попытка Docker внедрить в инструмент функциональность Builder Pattern, и это одна из самых малоиспользуемых функций во всем Docker.
Многоэтапная сборка использует преимущества использования нескольких FROM команд в Dockerfile . Каждая из этих инструкций будет основываться на предыдущих этапах и создавать новые. Создавая таким образом поэтапно, мы можем отделить все шаги, которые нам не понадобятся в конечном приложении, и исключить их, сэкономив место.
Например, мы можем создать этап сборки, на котором мы устанавливаем некоторые зависимости, загружаем наш код, запускаем некоторые тесты и т. д. Но поскольку большая часть этого не нужна в финальном образе, мы можем удалить ее до того, как она попадет в нашу окончательную сборку. . Мы компилируем наше приложение на этапе сборки и копируем наш скомпилированный код только в окончательный, уменьшенный образ для запуска.
Давайте посмотрим на пример:
# First, specify a base image that has the dependencies and tools needed to build your application FROM golang:1.14 as builder # Copy your application code into the image COPY . /app # Use the RUN command to build your application RUN cd /app && go build -o myapp # Now, create a new stage using a lightweight base image # that only has the dependencies needed to run your application FROM alpine:3.12 # Copy the compiled binary from the previous stage into this stage COPY --from=builder /app/myapp /usr/local/bin/myapp # Set the default command to run when a container is started from this image CMD ["myapp"]
Использование этой многоэтапной техники сборки в Docker имеет несколько преимуществ:
- Повышенная эффективность и производительность: создав несколько этапов в файле Docker, вы можете изолировать различные этапы процесса сборки и включать в каждый этап только необходимые файлы и зависимости. Это может помочь вам создавать более эффективные и легкие образы Docker, которыми проще управлять и обслуживать.
- Уменьшенный размер образа. Используя упрощенный базовый образ на заключительном этапе сборки, вы можете уменьшить размер образов Docker и упростить их распространение и развертывание. Это может быть особенно полезно, если вы развертываете свои контейнеры в среде с ограниченными ресурсами, например на облачной контейнерной платформе.
- Повышенная безопасность. Используя многоэтапную сборку, вы можете избежать включения конфиденциальной или конфиденциальной информации в окончательные образы Docker. Это поможет защитить ваше приложение и ваших пользователей, а также поможет вам соблюдать правила безопасности и конфиденциальности.
В целом, метод многоэтапной сборки необходим для создания высококачественных изображений, которые являются более эффективными и простыми в обслуживании.
# 2 — Выбирайте базовое изображение с умом
Вы можете написать лучший Dockerfile, который когда-либо видел мир, но если вы используете неправильный базовый образ, все это пустая трата времени. Всякий раз, когда вы используете команду From, вы берете весь код из предыдущего изображения и каждого изображения, от которого оно наследуется. Поэтому обязательно запустите Dockerfile с базовым образом, в котором есть все, что нужно вашему приложению для запуска, например, определенная версия операционной системы. Это сделает ваш Dockerfile более эффективным и уменьшит размер конечного образа.
Вы должны стремиться учитывать следующее:
- Совместимость с вашим приложением. Базовый образ должен включать операционную систему и зависимости, необходимые вашему приложению для запуска. Это могут быть определенные версии языковых сред выполнения, библиотек или инструментов, от которых зависит ваше приложение.
- Размери эффективность. Базовый образ должен быть как можно меньше и эффективнее, чтобы уменьшить размер окончательного образа Docker и повысить производительность.
- Безопасность. Базовый образ должен быть безопасным и поддерживаться в хорошем состоянии, с регулярными обновлениями безопасности и исправлениями. Это поможет защитить ваше приложение и ваших пользователей от уязвимостей и других угроз безопасности.
- Репутация и надежность. Базовый образ должен быть получен из авторитетного источника, широко использоваться и хорошо протестирован в сообществе Docker.
- Гибкость и настройка. Базовый образ должен быть достаточно гибким, чтобы вы могли настраивать его и добавлять собственные зависимости и конфигурацию. Это даст вам больше контроля над окончательным образом Docker и позволит вам адаптировать базовый образ к вашим конкретным потребностям.
№3 — Определение переменных среды с помощью ENV
Еще одна лучшая практика — использовать ENV для определения переменных среды. Это сделает ваши контейнеры более переносимыми и поможет избежать каких-либо изменений в операционной системе Linux внутри контейнера без изменения операционной системы хост-системы.
# Start with a base image that has the dependencies and tools needed to run your application FROM python:3.8 # Use the ENV command to define your environment variables ENV APP_NAME="My Application" ENV APP_PORT=5000 # Use the COPY or ADD command to add your application code to the image COPY . /app # Use the RUN command to install any additional dependencies and perform other setup tasks RUN pip install -r /app/requirements.txt # Use the EXPOSE command to specify the ports that your application listens on EXPOSE 5000 # Use the CMD command to specify the default command that should be run when a container is started from your image CMD ["python", "/app/main.py"]
Например, вы можете использовать переменную APP_NAME в коде вашего приложения, чтобы отобразить имя вашего приложения, и вы можете использовать переменную APP_PORT, чтобы указать порт, который слушает ваше приложение.
Команду ENV можно использовать для определения любого количества переменных среды, и при необходимости вы можете использовать команду ENV несколько раз в своем Dockerfile. Это может упростить управление и настройку вашего приложения, когда оно работает в контейнере Docker.
#4 — Открытые порты
Кроме того, помните, какие порты открыты. По умолчанию Docker предоставляет всем вашим контейнерам ряд случайных внутренних портов. Это может быть угрозой безопасности, поэтому, если вы используете службу, которая должна быть открыта для общедоступного Интернета, обязательно создайте запись в своем Dockerfile.
# 5 — Примите решение о контроле версий
Вы должны зафиксировать свой Dockerfile в своем репозитории, чтобы вы могли легко ссылаться на него позже. Некоторым это может показаться очень очевидным, но использование контроля версий позволит вам отслеживать изменения и сотрудничать с другими над вашим проектом.
«Общий репозиторий исходного кода для всей компании — один из самых мощных механизмов, используемых для интеграции локальных открытий во всей организации».
— Руководство DevOps, Джин Ким.
И, наконец, сделайте свой Dockerfile максимально простым. Не пытайтесь добавить ненужную сложность и убедитесь, что другим разработчикам легко понять и выполнить без посторонней помощи.
Спасибо за прочтение.