В этом руководстве мы рассмотрим, что такое Dockerfile и как его создать, следуя ведущим передовым практикам безопасности, включая многоэтапные сборки, создание минимальных образов, использование соответствующих инструкций для минимизации количества слоев, линтинг, чего следует избегать и многое другое.
Итак, давайте погрузимся в безопасность Dockerfile.
- 1. Что такое Dockerfile?
- 3. Используйте минимальный базовый образ Dockerfile
- 4. Используйте минимальное количество портов
- 5. Используйте надежные и безопасные базовые образы
- 5.1. Проверка на наличие уязвимостей
- 5.2. Используйте подписанные образы
- 6. Используйте линтер
- 7. Избегайте использования тега Latest
- 8. Группировка инструкций RUN, COPY и ADD
- 9. Многоэтапная сборка
- 10. Избегайте включения секретов или учетных данных
- 11. Использование .dockerignore
- 12. Заключение
1. Что такое Dockerfile?
Dockerfile в самом простом понимании – это текстовый файл, содержащий необходимые команды, которые используются для создания образа Docker.
Если вы не знакомы с тем, что такое образ Docker, я настоятельно рекомендую начать свое путешествие по контейнерам с документации Docker.
- 🎢 Что такое Dockerfile и как создать образ Docker?
- 🐳 Понимание инструкции Dockerfile VOLUME
- 🐳 Краткое введение в Dockerfile
Итак, что же делает dockerfile?
Dockerfile позволяет пользователям автоматизировать процесс сборки своих образов контейнеров повторяющимся, последовательным образом, без необходимости выполнять каждую команду вручную, что является большим бонусом.
Теперь, когда вы знаете, что такое dockerfile, в следующих разделах мы рассмотрим лучшие методы обеспечения безопасности при его написании.
2. Используйте инструкцию USER
Для того чтобы контейнеры не запускались от имени root, следует по возможности использовать инструкцию USER. Избегание использования root поможет предотвратить атаки повышения привилегий хоста, которые могут нанести ущерб безопасности системы.
Чтобы помочь пользователям в решении этой задачи, некоторые образы включают встроенного пользователя.
Например, Node.js включает своего пользователя node, как показано ниже.
USER node
Если встроенный пользователь не нужен, его следует удалить.
Используя тот же пример с Node.js, что и выше, это можно сделать, добавив следующее в Dockerfile.
# Для образов на базе debian используйте: RUN userdel -r node # Для образов на базе alpine используйте: RUN deluser --remove-home node
3. Используйте минимальный базовый образ Dockerfile
Образы должны быть минимальными и включать только те пакеты, которые необходимы для успешного запуска приложения.
При этом поверхность атаки значительно сокращается за счет удаления ненужных и потенциально уязвимых пакетов.
Чтобы помочь разработчикам в этих усилиях, многие источники разработали базовые образы, включающие только самое необходимое.
Distroless и Alpine – два наиболее распространенных и рекомендуемых базовых образа для создания минимальных контейнеров.
4. Используйте минимальное количество портов
В дополнение к использованию минимального образа, следует обнародовать только необходимые порты.
Использование инструкции EXPOSE поможет пользователям определить, какие порты предназначены для публикации.
Однако важно отметить, что инструкция EXPOSE предназначена исключительно для целей комментирования и/или документирования.
Поэтому она не предотвращает раскрытие дополнительных портов во время выполнения программы.
EXPOSE 80/tcp
5. Используйте надежные и безопасные базовые образы
Хотя существует ряд инструментов для получения таких результатов, Docker поставляется в комплекте с командой docker scan, предлагая пользователям быстрый и простой способ сканирования образов.
5.1. Проверка на наличие уязвимостей
PS user> docker scan node:14 \ Analyzing container dependencies for node:14 \ Querying vulnerabilities database......Package manager: deb Project name: docker-image|node Docker image: node:14 Platform: linux/amd64Tested 413 dependencies for known vulnerabilities, found 548 vulnerabilities.
5.2. Используйте подписанные образы
$ export DOCKER_CONTENT_TRUST=1
Для проверки уже извлеченных образов Docker предлагает команду docker trust inspect, как показано ниже.
6. Используйте линтер
7. Избегайте использования тега Latest
FROM node:14
8. Группировка инструкций RUN, COPY и ADD
9. Многоэтапная сборка
Многоэтапная сборка в Dockerfiles предлагает способ создания промежуточных сборок, иначе называемых стейджами (этапами).
Этапы позволяют пользователям копировать полученную сборку с предыдущего этапа и использовать ее в последующем этапе.
Использование многоэтапной сборки позволяет уменьшить площадь атаки и потенциальные уязвимости сборки за счет ограничения пакетов, содержащихся в конечном образе.
Например, пользователь может захотеть использовать этап, использующий инструменты сборки, но не иметь требований к этим инструментам сборки в конечном образе.
При многоэтапной сборке пользователь запускает этап с инструкцией FROM “base_image” как “name_of_stage1″, затем копирует результат этого этапа в следующий этап FROM с помощью инструкции COPY -from=”name_of_stage1”.
Смотрите следующий Dockerfile для примера использования Node:10 в качестве среды сборки, а затем Distroless Node:10 от Google для финального образа.
FROM node:10 as build-env COPY ./app WORKDIR /appRUN npm ci --only=productionFROM gcr.io/distroless/nodejs:10 COPY --from=build-env /app /app WORKDIR /app CMD ["app.js"]
10. Избегайте включения секретов или учетных данных
Docker использует кэширование слоев, что, по сути, означает, что все слои все еще присутствуют в конечном образе.
Некоторые команды, такие как docker history, покажут, какие слои присутствуют в образе и как они были собраны.
docker history node:14
Это становится особенно актуальным, когда речь идет об использовании секретов или учетных данных в Dockerfile, поскольку любой пользователь, имеющий доступ к образу, сможет увидеть их содержимое.
Чтобы преодолеть проблему безопасности, необходимо, чтобы пользователи никогда не включали секреты или учетные данные в свои Dockerfile, будь они записаны в открытом виде непосредственно в Dockerfile, переданы в виде файла или переданы в качестве аргумента сборки.
Вместо этого пользователи должны использовать такие инструменты, как Docker BuildKit с опцией командной строки -secret для передачи необходимой секретной информации.
Например, в Dockerfile пользователь получит доступ к секрету через команду RUN, как показано ниже.
RUN --mount=type=secret,id=secret cat /run/secrets/secret
docker build --no-cache --progress=plain --secret id=secret,src=secret.txt .
11. Использование .dockerignore
.git
logs
*.md
!README.md
12. Заключение
В заключение следует отметить, что Dockerfile – это отличный инструмент для создания повторяемых и согласованных образов контейнеров, если это делается безопасно.
Избегание latest тегов, проверка уязвимостей и устранение любых возникающих, использование только подписанных образов во избежание потенциальных проблем с цепочкой поставок, а также остальные описанные лучшие практики гарантируют, что ваша разработка начнется с правильной точки зрения безопасности и предотвратит любые головные боли в будущем.
см. также:
- 🐳 Расширенная безопасность Docker
- 🐳 Расширенная безопасность Docker Часть II
- 🐳 Как создавать резервные копии томов Docker
- 🖧 Мгновенная конфиденциальность с помощью tor, privoxy и docker
- 🐳 Использование команд docker logs –follow и –tail
- 🐳 Как очистить логи запущенных контейнеров Docker
- 🐳 Почему процессы в контейнерах Docker не должны запускаться от имени Root
- 🐳 Как проверить изменения в файловой системе контейнера Docker