Docker in Docker for non-root user

We use docker containers to build our software. One of our build jobs needs to create a docker image itself, but the image also needs to access a bind mounted volume on the host with a particular uid, which is itself, an NFS mount, so running as root in the container doesn’t work for us.

Here’s a quick way to recreate the issue:

Dockerfile:

FROM debian:stretch-slim`

RUN groupadd -o -g 1000 myguy \
    && useradd -o -r -m -u 1000 -g 1000 myguy
	
RUN apt-get update && apt-get install -y --no-install-recommends \
		curl \
		unzip \
		bzip2 \
        xz-utils \
		apt-transport-https \
		dirmngr \
        ca-certificates \
        gnupg2 \
        software-properties-common \
		sudo
		
RUN curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - \
    && add-apt-repository \
        "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" \
    && apt-get update && apt-get install -y --no-install-recommends docker-ce-cli
		
RUN usermod -aG sudo myguy \
    && echo "myguy ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
    
COPY docker-entrypoint.sh /home/myguy/docker-entrypoint.sh
ENTRYPOINT ["/home/myguy/docker-entrypoint.sh"]

docker-entrypoint.sh:

#!/bin/bash

#setup docker group based on hosts mount gid
echo "Adding hosts GID to docker system group"
# this only works if the docker group does not already exist
DOCKER_SOCKET=/var/run/docker.sock
DOCKER_GROUP=docker
USER=myguy

if [ -S ${DOCKER_SOCKET} ]; then
    DOCKER_GID=$(stat -c '%g' ${DOCKER_SOCKET})

    #addgroup is distribution specific

    sudo addgroup --gid ${DOCKER_GID} ${DOCKER_GROUP}
    sudo adduser ${USER} ${DOCKER_GROUP}
fi

exec "$@"

then build and run it …

$ chmod 777 docker-entrypoint.sh

$ docker build -t docker-in-docker .

$ docker run -it -u 1000:1000 -v /var/run/docker.sock:/var/run/docker.sock docker-in-docker /bin/bash

Adding hosts GID to docker system group
Adding group `docker' (GID 999) ...
Done.
Adding user `myguy' to group `docker' ...
Adding user myguy to group docker
Done.

myguy@e0efbdd6168f:/$ cat /etc/group | grep docker
docker:x:999:myguy

myguy@e0efbdd6168f:/$ ls -al /var/run/docker.sock
srw-rw---- 1 root docker 0 Feb 22 09:36 /var/run/docker.sock

myguy@e0efbdd6168f:/$ docker ps
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.39/containers/json: dial unix /var/run/docker.sock: connect: permission denied

myguy@e0efbdd6168f:/$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
e0efbdd6168f        docker-in-docker    "/home/myguy/docker-…"   42 seconds ago      Up 40 seconds                           silly_lichterman

How do we get docker-ce-cli to use the docker engine in the host as a non-root user?

Thanks,
Steve Maring
Orlando, FL

So, my solution was to properly affect the user’s group change after the mod. In the end, the docker-entrypoint.sh file makes use of the sg command like so …

#!/bin/bash

DOCKER_SOCKET=/var/run/docker.sock
DOCKER_GROUP=docker
USER=myguy

if [ -S ${DOCKER_SOCKET} ]; then
    DOCKER_GID=$(stat -c '%g' ${DOCKER_SOCKET})

    sudo addgroup --gid ${DOCKER_GID} ${DOCKER_GROUP}
    sudo usermod --append --groups ${DOCKER_GROUP} ${USER}
fi
sg ${DOCKER_GROUP} -c "bash"

exec "$@"

It is basically creating a new bash shell from the new shell, but ensuring the group mods.

ended up changing that to

newgrp ${DOCKER_GROUP}
newgrp $(id -gn)

that way you don’t lose the primary group for the user

Hi Steve,

Thanks for sharing the example.

Another approach you can consider is to run Docker-in-Docker, but without using privileged containers. There is a new container runtime (aka runc) that allows this at www.nestybox.com (I am the lead developer).

It would be a bit more secure than the approach you have above because it avoids the socket connection to the Docker daemon on the host (i.e., since Docker would run inside the unprivileged container itself), thereby restricting the sudo powers of user “myguy” within the container.

And you would be able to bind-mount the host volume / NFS mount you described into the container, and have a non-root user within the container access it per your requirements.

Hope that helps!

1 Like

Hi, When I mount /var/run/docker.sock, on the container its owners are nobody:nogroup . So any docker related commands are failed as permission denied. I run your dockerbuild file but the permissions did not change still. I am stuck with this problem, do you any ideas why I can’t mount docker.socket file without nobody ownership?