web-dev-qa-db-fra.com

Comment monter le socket Docker en tant que volume dans le conteneur Docker avec le bon groupe

Je veux exécuter une instance Jenkins dans un conteneur Docker.

Je veux que Jenkins lui-même puisse faire tourner des conteneurs dockers en tant qu'esclaves pour exécuter des tests.

Il semble que la meilleure façon de procéder consiste à utiliser

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

source

Le Dockerfile que j'utilise est

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

Si je démarre une session bash dans mon conteneur en cours d'exécution et que j'exécute docker info sur mon image je reçois

$ 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?

Et si je lance la session bash en tant que root

docker exec -u 0 -ti cocky_mccarthy bash
root@5dbd0efad2b0:/# docker info
Containers: 42
Images: 50
...

Donc je suppose que le groupe docker auquel j'ajoute l'utilisateur Jenkins est le groupe du docker interne, donc le socket n'est pas lisible sans Sudo. C'est une sorte de problème car le plugin Jenkins docker, etc. n'est pas configuré pour utiliser Sudo.

Comment puis-je monter le socket afin qu'il puisse être utilisé à partir de l'image sans Sudo?

22
Ollie Edwards

Un peu tard, mais cela pourrait aider d'autres utilisateurs aux prises avec le même problème:

Le problème ici est que le groupe docker sur votre hôte Docker a un ID de groupe différent de l'ID du groupe docker à l'intérieur de votre conteneur. Étant donné que le démon ne se soucie que de l'id et non du nom du groupe, votre solution ne fonctionnera que si ces identifiants correspondent par accident.

La façon de résoudre ce problème consiste à utiliser tcp au lieu d'utiliser un socket unix en utilisant option - H lors du démarrage du moteur Docker. Vous devez être très prudent avec cela, car cela permet à toute personne ayant accès à ce port d'obtenir un accès root à votre système.

Un moyen plus sûr de résoudre ce problème consiste à s'assurer que le groupe docker à l'intérieur du conteneur finit par avoir le même identifiant de groupe que le groupe docker à l'extérieur du conteneur. Vous pouvez le faire en utilisant des arguments de construction pour votre 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

Et puis le construire en utilisant

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

Après cela, vous pouvez exécuter votre image et avoir un accès Docker en tant que non root

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

Étant donné que cette solution dépend de la fourniture de l'ID de groupe correct au démon Docker lors de la création de l'image, cette image doit être créée sur la ou les machines sur lesquelles elle est utilisée. Si vous créez l'image, poussez-la et que quelqu'un d'autre la tire sur sa machine, il est probable que l'ID du groupe ne correspondra plus.

15
eawenden

J'ai utilisé votre dockerfile mais j'ai fait une petite modification:

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

Après avoir construit l'image, je peux la démarrer en utilisant (je suis sur 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

Vous avez essayé d'installer le package docker.io à l'intérieur de votre image. Mais ce package est également sur votre hôte (sinon il n'est pas possible d'y exécuter des conteneurs Docker). Il est donc recommandé de le monter sur votre conteneur au lieu de l'installer dans votre fichier docker. Je pense que le/lib64/... monté est spécifique à 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
5
lvthillo