Как смонтировать докер-сокет как том в докер-контейнере с правильной группой
Я хочу запустить экземпляр Jenkins в контейнере Docker.
Я хочу, чтобы сама Дженкинс могла раскручивать док-контейнеры в качестве рабов для запуска тестов.
Кажется, лучший способ сделать это - использовать
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
root@5dbd0efad2b0:/# docker info
Containers: 42
Images: 50
...
Так что я думаю, docker
группа, к которой я добавляю пользователя Jenkins - это группа для внутреннего докера, поэтому сокет не читается без sudo
, Это своего рода проблема, поскольку плагин док-станции Jenkins и т. Д. Не настроены для использования sudo
,
Как я могу смонтировать сокет, чтобы его можно было использовать из образа без sudo
?
2 ответа
Немного поздно, но это может помочь другим пользователям, которые борются с той же проблемой:
Проблема здесь в том, что 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
Поскольку это решение зависит от предоставления правильного идентификатора группы демону docker при создании образа, этот образ необходимо будет построить на компьютере (ах), где он используется. Если вы создаете образ, нажимаете его, а кто-то другой загружает его на свой компьютер, скорее всего, идентификаторы группы не будут совпадать снова.
Я использовал ваш 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
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 внутри своего образа. Но этот пакет также находится на вашем хосте (в противном случае на нем нельзя запускать Docker-контейнеры). Поэтому рекомендуется монтировать это в ваш контейнер, а не устанавливать его в файле Docker. Я думаю, что смонтированный /lib64/... специфичен для Centos 7.
$ docker exec -it 9fc27d5fcec1 bash
jenkins@9fc27d5fcec1:/$ whoami
jenkins
jenkins@9fc27d5fcec1:/$ 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