Manuel L.
Manuel L.

Reputation: 15

Docker Rootless in Docker Rootless, It's possble?

For my job, I would like to run Jenkins and Docker Rootless (with the sysbox runtime only for this container), all in Docker Rootless.

I would like this because I need a secure environment given I don't inspect Jenkins pipelines

But when I run docker rootless in docker rootless, I get this error:

[rootlesskit:parent] error: failed to setup UID/GID map: newuidmap 54 [0 1000 1 1 100000 65536] failed: newuidmap: write to uid_map failed: Operation not permitted
: exit status 1

I tried many actions but failed to get it to work. Someone would have a solution to do this, please?

Thanks for reading me, have a nice day!


Edit 1

Hello, I take the liberty of relaunching this question, because being essential for the safety of our environment, my bosses remind me every day. Would someone have the answer to this problem please

Upvotes: 1

Views: 3016

Answers (1)

Skeptic
Skeptic

Reputation: 1564

Things getting a little tricky when you want to use the docker build command inside a Jenkins container. I stumbled upon this issue when wanted to build docker images without being root, under the user 'jenkins' instead. I wrote the solution in an article in which I explain in detail what is happening under the hood. The key point is to figure out which GID the docker.sock socket is running under (depends on the system). So here is what you gotta do:

Run the command:

$ stat /var/run/docker.sock

Output:

jenkins@wsl-ubuntu:~$ stat /var/run/docker.sock
  File: /var/run/docker.sock
  Size: 0               Blocks: 0          IO Block: 4096   socket
Device: 17h/23d Inode: 552         Links: 1
Access: (0660/srw-rw----)  Uid: (    0/    root)   Gid: ( 1001/  docker)
Access: 2021-03-03 10:43:05.570000000 +0200
Modify: 2021-03-03 10:43:05.570000000 +0200
Change: 2021-03-03 10:43:05.570000000 +0200
 Birth: -

In this case, the GID is 1001, but can also be 999 or something else in your machine.

Now, create a Dockerfile and paste the code below replacing the ENV variable with your own from the stat command output above:

FROM jenkins/jenkins:lts-alpine

USER root

ARG DOCKER_HOST_GID=1001 #Replace with your own docker.sock GID
ARG JAVA_OPTS=""

ENV DOCKER_HOST_GID $DOCKER_HOST_GID
ENV JAVA_OPTS $JAVA_OPTS

RUN set -eux \
&& apk --no-cache update \
&& apk --no-cache upgrade --available \
&& apk --no-cache add shadow \
&& apk --no-cache add docker curl --repository http://dl-cdn.alpinelinux.org/alpine/latest-stable/community \
&& deluser --remove-home jenkins \
&& addgroup -S jenkins -g $DOCKER_HOST_GID \
&& adduser -S -G jenkins -u $DOCKER_HOST_GID jenkins \
&& usermod -aG docker jenkins \
&& apk del shadow curl

USER jenkins
WORKDIR $JENKINS_HOME

For the sake of a working example, here is a docker-compose file:

version: '3.3'

services:
  jenkins:
    image: jenkins_master
    container_name: jenkins_master
    hostname: jenkins_master
    restart: unless-stopped
    env_file:
      - jenkins.env
    build:
      context: .
    cpus: 2
    mem_limit: 1024m
    mem_reservation: 800M
  
    ports:
      - 8090:8080
      - 50010:50000
      - 2375:2376
    volumes:
      - ./jenkins_data:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - default

volumes:
  jenkins_data: {}
networks:
  default:
    driver: bridge

Now lets create the ENV variables:

cat > jenkins.env <<EOF
DOCKER_HOST_GID=1001 #Replace with your own docker.sock GID
JAVA_OPTS=-Dhudson.slaves.NodeProvisioner.MARGIN0=0.85
EOF

and lastly, run the command docker-compose up -d. It will build the image, and run it. Then visit HTTP://host_machine_ip:8090 , and that's all.

If you run docker inspect --format '{{ index (index .Config.Env) }}' jenkins_master you will see that the 1st and 2nd variables are the ones we set. More details can be found here: How to run rootless docker in dockerized Jenkins installation

Upvotes: 1

Related Questions