Как подключить гнездо док-станции в качестве тома в контейнере докера с правильной группой

Я хочу запустить экземпляр Jenkins в контейнере докеров.

Я хочу, чтобы сам Дженкинс мог разворачивать контейнеры докеров в качестве ведомых для запуска тестов.

Кажется, лучший способ сделать это - использовать

docker run -v /var/run.docker.sock:/var/run/docker.sock -p 8080:8080 -ti my-jenkins-image

источник

Dockerfile Я использую

FROM jenkins
COPY plugins.txt /usr/share/jenkins/plugins.txt
RUN /usr/local/bin/plugins.sh /usr/share/jenkins/plugins.txt

USER root
RUN apt-get update && apt-get install -y docker.io
RUN usermod -aG docker jenkins
USER jenkins

Если я запустил сеанс bash в моем запущенном контейнере и запустил docker info на моем изображении, я получаю

$ docker info
FATA[0000] Get http:///var/run/docker.sock/v1.18/info: dial unix /var/run/docker.sock: permission denied. Are you trying to connect to a TLS-enabled daemon without TLS?

И если я запустил сеанс bash как root

docker exec -u 0 -ti cocky_mccarthy bash
[email protected]:/# docker info
Containers: 42
Images: 50
...

Итак, я думаю, что группа docker, в которую я добавляю пользователя jenkins, является группой для внутреннего докера, поэтому сокет не читается без sudo. Такая проблема, как плагин docker jenkins и т.д., Не настроена для использования sudo.

Как смонтировать сокет, чтобы его можно было использовать из образа без sudo?

Ответы

Ответ 1

Немного поздно, но это может помочь другим пользователям, которые борются с одной и той же проблемой:

Проблема заключается в том, что группа docker на вашем докерном хосте имеет другой идентификатор группы из идентификатора группы docker внутри вашего контейнера. Поскольку демон только заботится об идентификаторе, а не о названии группы, ваше решение будет работать только в том случае, если эти идентификаторы совпадают случайно.

Способом решения этого является использование tcp вместо использования unix-сокета с помощью - опция H при запуске двигателя Docker. Вы должны быть очень осторожны, так как это позволяет любому, у кого есть доступ к этому порту, получить доступ root к вашей системе.

Более безопасный способ его устранения - убедиться, что группа docker внутри контейнера заканчивается тем же идентификатором группы, что и группа docker вне контейнера. Вы можете сделать это, используя аргументы сборки для docker build:

Dockerfile:

FROM jenkinsci
ARG DOCKER_GROUP_ID

USER root
RUN curl -o /root/docker.tgz https://get.docker.com/builds/Linux/x86_64/docker-1.12.5.tgz && tar -C /root -xvf /root/docker.tgz && mv /root/docker/docker /usr/local/bin/docker && rm -rf /root/docker*
RUN curl -L https://github.com/docker/compose/releases/download/1.7.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose
RUN groupadd -g $DOCKER_GROUP_ID docker && gpasswd -a jenkins docker
USER jenkins

И затем построим его с помощью

docker build --build-arg DOCKER_GROUP_ID=`getent group docker | cut -d: -f3` -t my-jenkins-image .

После этого вы можете запустить свое изображение и получить доступ к докере как не root

docker run -v /var/run/docker.sock:/var/run/docker.sock -p 8080:8080 -ti my-jenkins-image

Поскольку это решение зависит от предоставления правильного идентификатора группы демонам докеров при создании изображения, это изображение должно быть построено на машине (машинах), где она используется. Если вы создадите изображение, нажмите его, а кто-то другой потянет его на свою машину, скорее всего, идентификатор группы больше не будет соответствовать.

Ответ 2

Я использовал ваш файл docker, но сделал небольшое редактирование:

FROM jenkins
COPY plugins.txt /usr/share/jenkins/plugins.txt
RUN /usr/local/bin/plugins.sh /usr/share/jenkins/plugins.txt

USER root
RUN apt-get update
RUN groupadd docker && gpasswd -a jenkins docker
USER jenkins

После создания изображения я могу запустить его, используя (я на centos7):

docker run -d \
-v /var/run/docker.sock:/var/run/docker.sock \
     -v $(which docker):/usr/bin/docker:ro \
     -v /lib64/libdevmapper.so.1.02:/usr/lib/x86_64-linux-gnu/libdevmapper.so.1.02 \
     -v /lib64/libudev.so.0:/usr/lib/x86_64-linux-gnu/libudev.so.0 \
     -p 8080:8080 \
     --name jenkins \
     --privileged=true -t -i \
test/jenkins

Вы пытались установить пакет docker.io внутри своего изображения. Но этот пакет также находится на вашем хосте (иначе он не может запускать на нем контейнеры докеров). Поэтому рекомендуется установить это в ваш контейнер вместо установки его в файл докера. Я думаю, что mount/lib64/... специфичен для Centos 7.

$ docker exec -it 9fc27d5fcec1 bash
[email protected]:/$ whoami 
jenkins
[email protected]:/$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
9fc27d5fcec1        test                "/bin/tini -- /usr/lo"   6 minutes ago       Up 6 minutes        0.0.0.0:8080->8080/tcp, 50000/tcp   jenkins