Привет! Давайте рассмотрим способы запуска Docker в Docker-контейнере (вложенное использование Docker). Такой подход не является повседневным использованием, но иногда помогает решить задачи: При построении пайплайна CI/CD в GitLab или Jenkins для создания образов Docker и их публикации в реджестри (реестре образов) При использовании Jenkins Dynamic Agents (динамических Docker-контейнеров)  При необходимости построения изолированной среды от хоста, где будет выполнятся стендовая работа, а после проведения можно будет легко удалить её.     Запуск docker путём монтирования docker.sock (метод DooD) Использовать дочерний контейнер внутри контейнера  (метод dind) Использование среды выполнения Nestybox sysbox Docker  Для эксперимента создадим виртуальную машину в облаке Cloud4Y из готового шаблона ubuntu-server-2204 по мануалу. Далее установим docker (https://docs.docker.com/engine/install/ubuntu/). Я воспользуюсь скриптом:  #curl -sSL https://get.docker.com/ | sh Проверим версию  # docker –vDocker version 20.10.22, build 3a2c30b /var/run/docker.sock является сокетом Unix по умолчанию (IPC-сокет). Сокеты предназначены для обмена данными между процессами на одном хосте. Демон Docker по умолчанию прослушивает docker.sock. Если вы находитесь на том же хосте, на котором запущен демон Docker, вы можете использовать /var/run/docker.sock для управления контейнерами. Например, если мы запустим следующую команду:  # curl --unix-socket /var/run/docker.sock http://localhost/version она вернёт версию docker engine, такую же, как мы проверяли ранее: Теперь давайте запустим Docker in Docker с помощью /var/run/docker.sock. Для этого нам нужно запустить docker с сокетом Unix по умолчанию и передать docker.sock в качестве тома: # docker run -v /var/run/docker.sock:/var/run/docker.sock -ti docker Этот метод иногда называют DooD (Docker outside of Docker), потому что он использует Docker вне Docker.  Поскольку он монтирует только сокет хост-среды, используемый образ Docker не используется dind, и не требует привилегированный -privileged режим, как это описано далее в методе 2.  Тут нужно понимать риски безопасности, что если ваш контейнер получает доступ к docker.sock, это означает, что у него будут повышенные привилегии по сравнению с docker.  Теперь из контейнера мы имеем возможность выполнять команды docker для создания и отправки образов в реджестри. Фактически, в данном случае операции docker выполняются на хосте виртуальной машины, на которой запущен ваш базовый контейнер docker, а не внутри контейнера. То есть, если вы выполняете команды docker из контейнера, вы даёте указание docker подключиться к docker-engine хоста виртуальной машины через docker.sock.  Воспользуемся примером выше, где мы используем официальный образ docker из docker hub и запускаем контейнер Docker в интерактивном режиме.  # docker run --name dood -v /var/run/docker.sock:/var/run/docker.sock -ti docker Внутри запущенного контейнера скачаем образ docker —  alpine, командой # docker pull  alpine И посмотрим доступные локальные образы в контейнере  # docker images REPOSITORY   TAG       IMAGE ID       CREATED       SIZE docker       latest    81a4721a045e   8 days ago    152MB alpine       latest    49176f190c7e   3 weeks ago   7.05MB Теперь, если мы выйдем из контейнера и посмотрим доступные образы на хостовой машине, то увидим те же, что и в контейнере.  Данный метод позволяет экономить место на диске, поскольку не дублирует образы Docker, но позволяет из контейнера увидеть другие контейнеры, запущенные на хостовой машине.   Этот метод фактически создаёт дочерний контейнер внутри контейнера. Используйте этот метод, только если вы действительно хотите, чтобы контейнеры и образы находились внутри контейнера.  Для этого нужно использовать официальный образы docker с тэгом dind. Образ dind загружается с необходимыми утилитами для запуска Docker внутри контейнера Docker и требуют для запуска привилегированный режим. Запустим контейнер: # docker run --privileged -d --name dind docker:dind И войдем интерактивно:  # docker exec -it dind /bin/sh повторим, что делали ранее, но скачаем теперь другой образа docker —  busybox # docker pull busybox И посмотрим доступные локальные образы  в контейнере  # docker images REPOSITORY   TAG       IMAGE ID       CREATED       SIZE busybox      latest    334e4a014c81   7 days ago    4.86MB Теперь выйдем из контейнера и посмотрим на хостовой машине  # docker images REPOSITORY   TAG       IMAGE ID       CREATED       SIZE docker       dind      d74418bd2227   8 days ago    322MB docker       latest    81a4721a045e   8 days ago    152MB alpine       latest    49176f190c7e   3 weeks ago   7.05MB Поскольку Docker на хост-машине и Docker в контейнере docker: dind являются отдельными, образы в контейнере (busybox) не видны с хост-машины, и наоборот.   С этим методом связано много проблем: Он плохо работает с модулями безопасности Linux (LSM) Есть проблемы с драйвером хранилища и возможным несоответствии между файловой системой, используемой для контейнеров созданных внутри родительского контейнера, с файловой системой хоста. Могут возникать комбинации, когда это не будет работать.  С безопасностью — из-за необходимости использования привилегированного режима.  Отсутствием поддержки docker-compose в установке по умолчанию и необходимости установки https://docs.docker.com/compose/install/  Методы 1 и 2 имеют недостатки с точки зрения безопасности из-за запуска базовых контейнеров в привилегированном режиме. Nestybox пытается решить эту проблему, используя среду выполнения Sysbox Docker. Sysbox — это бесплатная среда выполнения контейнеров с открытым исходным кодом, которая расширяет возможности контейнеров двумя ключевыми способами: Улучшает изоляцию контейнера: Пространство имён пользователей Linux во всех контейнерах (т. е. пользователь root в контейнере не имеет привилегий на хосте). Виртуализирует части procfs и sysfs внутри контейнера. Скрывает информацию о хосте внутри контейнера и другие. Позволяет контейнерам работать подобно виртуальным машинам: С помощью Sysbox контейнеры могут запускать программное обеспечение системного уровня, такое как systemd, Docker, Kubernetes, K3s, buildx, устаревшие приложения и т. д. беспрепятственно и безопасно. Это программное обеспечение может работать внутри контейнеров Sysbox без модификации и без использования специальных версий программного обеспечения. Никаких привилегированных контейнеров, специальных монтирований томов и т. д. Sysbox достигает этого, используя контейнер максимально похожий на виртуальную среду, с помощью передовых методов виртуализации ОС. Для этого метода установим Sysbox по документации. Теперь мы можем запустить наш контейнер с использованием среда выполнения sysbox при помощи # docker run --runtime=sysbox-runc --name sysbox -d docker:dind И войти интерактивно:  # docker exec -it sysbox /bin/sh Используйте Docker в Docker только в том случае, если это действительно необходимо вам. Проводите достаточное тестирование, прежде чем переносить любые продуктовые решения на метод Docker-in-Docker. При использовании контейнеров в привилегированном режиме убедитесь, что вы получили необходимые разрешения от групп безопасности на то, что вы планируете делать. Использовании Docker-in-Docker не влияет на производительность контейнера, но определяется производительностью хоста.  В качестве примера рассмотрим работу gitlab-runner с использованием всех методов. Для этого на нашей виртуальной машине установим gitlab-runner с executor-м docker:  зарегистрируем три раннера с разными тэгами: dood-tag,  dind-tag, sysbox-tag для каждого метода и образом по умолчанию docker:stable.  # docker run --rm -it -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register В конфигурацию соответствующего раннера в /srv/gitlab-runner/config/config.toml внесём правки: В раннер dood-tag с методом 1, ставим настройки   volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]  В раннер dind-tag с методом 2, ставим настройки   privileged = true В раннер sysbox-tag с методом 3, ставим настройки  runtime = "sysbox-runc" В итоге CI/CD Settings нашего проекта мы увидим  Напишем конфигурацию для  GitLab .gitlab-ci.yml  с тремя стейджами и заданием для каждого метода, запускаемого на своем раннере, и посмотрим результат docker images Результаты по каждому раннеру:  DooD_Runner Dind_runner Sysbox_runner Мы видим сходство результата по второму и третьему методу, при этом мы не использовали привилегированный режим в третьем.   Подробности по раннерам смотрите в документации GitLab:  https://docs.gitlab.com/runner/install/docker.html  https://docs.gitlab.com/runner/executors/docker.html Написано на базе этой статьи. Спасибо за внимание! → Информационная безопасность и глупость: необычные примеры → NAS за шапку сухарей → Как распечатать цветной механический телевизор на 3D-принтере → Создание e-ink дисплея с прогнозом погоды → Аналоговый компьютер Telefunken RA 770 Подписывайтесь на наш Telegram-канал, чтобы не пропустить очередную статью. Пишем только по делу. А ещё напоминаем про второй сезон нашего сериала ITить-колотить. Его можно посмотреть на YouTube и ВКонтакте.  Корпоративный облачный провайдер