Дженкинс в докере с доступом к докеру-хозяину - программирование

Дженкинс в докере с доступом к докеру-хозяину

У меня есть рабочий процесс для публикации webapps на моем dev-сервере. На сервере есть один хост-докер, и я использую docker-compose для управления контейнерами.

  • Нажимайте изменения в моем приложении на приватную gitlab (работает в докере). Приложение включает в себя Dockerfile и docker-compose.yml
  • Gitlab запускает сборку jenkins (jenkins также работает в докере), что делает некоторые обычные сборки (например, run test)
  • Затем Дженкинс должен создать новое изображение докеры и развернуть его, используя компоновку docker.

Проблема заключается в шаге 3. Как я ее настроил, контейнер jenkins имеет доступ к докере хоста, так что запуск любой команды docker в сборке script по существу такой же, как при запуске на хосте. Это делается с использованием следующих DockerFile для jenkins:

FROM jenkins
USER root

# Give jenkins access to docker
RUN groupadd -g 997 docker
RUN gpasswd -a jenkins docker

# Install docker-compose
RUN curl -L https://github.com/docker/compose/releases/download/1.2.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
RUN chmod +x /usr/local/bin/docker-compose

USER jenkins

и отображение следующих томов в контейнер jenkins:

-v /var/run/docker.sock:/var/run/docker.sock
-v /usr/bin/docker:/usr/bin/docker

Типичная сборка script в jenkins выглядит примерно так:

docker-compose build
docker-compose up

Это работает нормально, но есть две проблемы:

  • Это действительно похоже на хак. Но единственными другими опциями, которые я нашел, является использование плагина docker для jenkins, публикация в реестре и последующий способ сообщить хозяину, что он должен перезапустить. Это довольно много движущихся частей, а плагин docker-jenkins требует, чтобы хост-докер находился на открытом порту, который я действительно не хочу раскрывать.

  • Jenkins DockerFile включает groupadd -g 997 docker, который необходим, чтобы дать пользователю jenkins доступ к докере. Однако GID (997) является GID на главной машине и поэтому не переносится.

Я не уверен, какое решение я ищу. Я не вижу практического способа обойти этот подход, но было бы неплохо, если бы был способ разрешить выполнение команд докеров в контейнере jenkins без необходимости жесткого кода GID в DockerFile. У кого-нибудь есть предложения по этому поводу?

4b9b3361

Ответ 1

Я столкнулся с теми же проблемами. Я закончил тем, что предоставил Jenkins права без права sudo из-за проблемы GID. Я писал об этом подробнее: http://container-solutions.com/2015/03/running-docker-in-jenkins-in-docker/

Это не влияет на безопасность, поскольку привилегии докеров действительно эквивалентны правам sudo.

Ответ 2

Мой предыдущий ответ был более общим, рассказывая, как вы можете изменить GID внутри контейнера во время выполнения. Теперь, по совпадению, кто-то из моих близких коллег попросил экземпляр jenkins, который может заниматься разработкой докеров, поэтому я создал это:

FROM bdruemen/jenkins-uid-from-volume
RUN apt-get -yqq update && apt-get -yqq install docker.io && usermod -g docker jenkins
VOLUME /var/run/docker.sock
ENTRYPOINT groupmod -g $(stat -c "%g" /var/run/docker.sock) docker && usermod -u $(stat -c "%u" /var/jenkins_home) jenkins && gosu jenkins /bin/tini -- /usr/local/bin/jenkins.sh

(Родительский файл Docker - это тот же самый, который я описал в своем ответе на: Изменение пользовательского uid в контейнере доклеителя pre-build (jenkins))

Чтобы использовать его, установите оба параметра: jenkins_home и docker.sock.

docker run -d /home/jenkins:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock <IMAGE>

Процесс jenkins в контейнере будет иметь тот же UID, что и установленный хост-каталог. Предполагая, что доклер-сокет доступен для группы докеров на хосте, в контейнере создается группа, также называемая докере, с тем же GID.

Ответ 3

Пожалуйста, взгляните на этот файл докеров, который я только что опубликовал: https://github.com/bdruemen/jenkins-docker-uid-from-volume/blob/master/gid-from-volume/Dockerfile

Здесь GID извлекается из смонтированного тома (каталога хоста) с помощью

stat -c '%g' <VOLUME-PATH>

Затем GID группы пользователя контейнера изменяется на одно и то же значение с помощью

groupmod -g <GID>

Это должно выполняться как root, но затем привилегии root отбрасываются с помощью

gosu <USERNAME> <COMMAND>

Все сделано в ENTRYPOINT, поэтому реальный GID неизвестен, пока вы не запустите

docker run -d -v <HOST-DIRECTORY>:<VOLUME-PATH> ...

Обратите внимание, что после изменения GID в контейнере могут быть другие файлы, которые больше не доступны для процесса, поэтому вам может понадобиться

chgrp -R <GROUPNAME> <SOME-PATH>    

перед командой gosu.

Вы также можете изменить UID, см. мой ответ здесь Изменение пользовательского uid в контейнере докеров для сборки (jenkins) и, возможно, вы хотите изменить оба для повышения безопасности.