Можно ли запускать Docker изнутри Docker?
Я запускаю Дженкинса в контейнере Docker. Интересно, может ли контейнер Jenkins быть хостом Docker? Я думаю о том, чтобы запустить новый докер-контейнер для каждой сборки интеграционного теста из Jenkins (для запуска баз данных, брокеров сообщений и т. Д.). Таким образом, контейнеры должны быть закрыты после завершения интеграционных испытаний. Есть ли причина избегать запуска докер-контейнеров из другого док-контейнера таким образом?
5 ответов
Запуск Docker внутри Docker (aka dind), по возможности, следует избегать, если это вообще возможно. (Источник предоставлен ниже.) Вместо этого вы хотите настроить способ, с помощью которого ваш главный контейнер будет создавать и взаимодействовать с одноуровневыми контейнерами.
Жером Петаццони (Jérôme Petazzoni) - автор функции, позволившей Docker запускаться в контейнере Docker, - на самом деле написал сообщение в блоге, в котором говорилось, что не следует этого делать. Описанный им вариант использования соответствует точному сценарию использования OP контейнера Docker CI, который должен запускать задания внутри других контейнеров Docker.
Петаццони перечисляет две причины, по которым Динд мешает:
- Он плохо взаимодействует с модулями безопасности Linux (LSM).
- Это создает несоответствие в файловых системах, что создает проблемы для контейнеров, созданных внутри родительских контейнеров.
Из этого поста в блоге он описывает следующую альтернативу:
Самый простой способ - это просто выставить сокет Docker для вашего CI-контейнера, привязав его с помощью
-v
флаг.Проще говоря, когда вы запускаете свой CI-контейнер (Jenkins или другой), вместо того, чтобы взламывать что-то вместе с Docker-in-Docker, начните его с:
docker run -v /var/run/docker.sock:/var/run/docker.sock ...
Теперь этот контейнер будет иметь доступ к сокету Docker и, следовательно, сможет запускать контейнеры. За исключением того, что вместо запуска "дочерних" контейнеров, он запускает "родственные" контейнеры.
Ранее я отвечал на аналогичный вопрос о том, как запустить Docker-контейнер внутри Docker.
Запустить докер внутри докера определенно можно. Главное, что ты
run
внешний контейнер с дополнительными привилегиями (начиная с--privileged=true
), а затем установите докер в этот контейнер.Проверьте это сообщение в блоге для получения дополнительной информации: Docker-in-Docker.
Один из возможных вариантов использования для этого описан в этой записи. В блоге описывается, как создавать док-контейнеры в док-контейнере Jenkins.
Однако Docker внутри Docker не является рекомендуемым подходом для решения проблем такого типа. Вместо этого рекомендуется создать "одноуровневые" контейнеры, как описано в этом посте.
Таким образом, запуск Docker внутри Docker многие считали хорошим решением для этого типа проблем. Теперь, тенденция состоит в том, чтобы использовать "родственные" контейнеры вместо этого. Смотрите ответ @predmijat на этой странице для получения дополнительной информации.
Можно запускать Docker-in-Docker (DinD), и на самом деле Docker (компания) имеет для этого официальный образ DinD.
Однако предостережение заключается в том, что для этого требуется привилегированный контейнер, который в зависимости от ваших потребностей в безопасности может быть неэффективной альтернативой.
Альтернативное решение запуска Docker с использованием одноуровневых контейнеров (также известных как Docker-out-of-Docker или DooD) не требует привилегированного контейнера, но имеет несколько недостатков, связанных с тем, что вы запускаете контейнер из контекста, который отличается от того, в котором он запущен (то есть вы запускаете контейнер изнутри контейнера, но он работает на уровне хоста, а не внутри контейнера).
Я написал блог, описывающий плюсы и минусы DinD vs DooD здесь.
При этом Nestybox (стартап, который я только что основал) работает над решением, которое безопасно запускает настоящий Docker-in-Docker (без использования привилегированных контейнеров). Вы можете проверить это на сайте https://www.nestybox.com/.
Да, мы можем запустить докер в докере, нам нужно будет прикрепить сокет unix "/var/run/docker.sock", на котором демон докера по умолчанию слушает родительский докер как том, используя "-v /var / run /docker.sock:/var/run/docker.sock". Иногда могут возникнуть проблемы с разрешениями для сокета демона докеров, для которого вы можете написать "sudo chmod 757 /var/run/docker.sock".
А также потребуется запустить докер в привилегированном режиме, поэтому команды будут такими:
sudo chmod 757 /var/run/docker.sock
docker run --privileged=true -v /var/run/docker.sock:/var/run/docker.sock -it...
Я изо всех сил старался запускать контейнеры внутри контейнеров, как и вы, в течение последних нескольких дней. Потрачено много часов. До сих пор большинство людей советовали мне делать такие вещи, как использование образа DIND докера, который неприменим для моего случая, так как мне нужно, чтобы основным контейнером была ОС Ubuntu, или запускать какую-то команду привилегий и отображать сокет демона в контейнер. (Что никогда не работает для меня)
Решение, которое я нашел, заключалось в использовании Nestybox в моей системе Ubuntu 20.04, и оно работает лучше всего. Его также чрезвычайно просто выполнить, если ваша локальная система — Ubuntu (которую они поддерживают лучше всего), поскольку среда выполнения контейнера специально разработана для такого приложения. Он также имеет самые гибкие настройки. Бесплатная версия Nestybox, пожалуй, лучший метод на ноябрь 2022 года. Настоятельно рекомендуем вам попробовать ее, не беспокоясь обо всех утомительных настройках, которые предлагают другие люди. У них есть много готовых решений для удовлетворения таких конкретных потребностей с помощью простой командной строки.
Nestybox предоставляет специальную среду выполнения для вновь созданного контейнера докеров, а также предоставляет некоторые образы ОС ubuntu/common со встроенными докером и systemd. Их цель — сделать так, чтобы основной контейнер функционировал точно так же, как и виртуальная машина. Вы также можете буквально подключиться по ssh к своему основному контейнеру Ubuntu без возможности доступа к чему-либо на основной машине. Из вашего основного контейнера вы можете создавать все виды контейнеров, как это делает обычная локальная система. Этот systemd очень важен для удобной настройки докера внутри контейнера.
Одна простая общая команда для запуска sysbox:
dock run --runtime=sysbox-runc -it any_image
Если вы думаете, что это то, что вы ищете, вы можете узнать больше на их github:https://github.com/nestybox/sysbox
Быстрая ссылка на инструкции по развертыванию простого контейнера среды выполнения sysbox: https://github.com/nestybox/sysbox/blob/master/docs/quickstart/README.md