Mounting & using /var/run/docker.sock in a container not running as root

Hi,

I’m trying to mount the /var/run/docker.sock socket into my container to allow docker-in-docker behaviour on Docker for Mac 17.06.0-cd-mac18 (18433), stable channel. On a mid 2014 MacBook Pro running Sierra 10.12.5.

The container runs as a non-root user (circleci:circleci). When I try and use docker inside it:

docker run -v /var/run/docker.sock:/var/run/docker.sock teviotia/circleci-docker-openjdk-node:latest docker info

I get permission errors, which is not surprising since

docker run -v /var/run/docker.sock:/var/run/docker.sock teviotia/circleci-docker-openjdk-node:latest ls -l /var/run/docker.sock

returns:

srw-rw---- 1 root staff

I tried touching the file and setting its ownership in the Dockerfile:

RUN sudo touch /var/run/docker.sock && sudo chown 3434:3434 /var/run/docker.sock

(3434 is the uid of the circleci user in the container) but this makes no difference to the ownership of the file once it is mounted. Likewise

RUN sudo touch /var/run/docker.sock && sudo chmod o+rw /var/run/docker.sock

makes no difference.

Any ideas?

(I could of course run docker as sudo inside the container, but as you’ve probably noticed the primary use of this container is for circleci, and the scripts work fine on circleci so I’m a bit reluctant to sprinkle sudo everywhere just to solve the ownership of the docker.sock when running locally.)

1 Like

OK, got a solution - adding this to the Dockerfile:

RUN echo "if [ -e /var/run/docker.sock ]; then sudo chown circleci:circleci /var/run/docker.sock; fi" >> /home/circleci/.bashrc

changes the ownership of the docker.sock file after it has been mounted.

I have the same problem but my non-root user is not a sudoer. Is there any other solution?

May i suggest to override userid and groupid when the container is started?

The ’ docker run’ parameter allows to replace the uid:gid of the user of the first USER declartion in the Dockerfile:

--user=[ user | user:group | uid | uid:gid | user:gid | uid:group ]

The following command stores the group ip in the variable docker_gid:
docker_gid=$(cut -d: -f3 < <(getent group docker))

Though, it seems like you can use `docker run --user uid:docker directly…

I am not sure if the gid of the docker group is allways 999, if so, you could create the same group in your Dockerfile and assign the user to this group.

The configuration item “user:” can be used in a docker-compose.yml as a child node of the service as well. Though I am not sure if this is still possible with Swarm Stack deployments.

Hi,

I’ve run in a similar problem when trying to create a docker container for Jenkins.

My host is a MAC OS X and the /var/run/docker.sock has the following permissions:

lrwxr-xr-x  1 root  daemon  72 Nov 26 22:28 /var/run/docker.sock

And when running the docker image, the file has been mounted as:

srw-rw---- 1 root root 0 Dec  1 13:08 /var/run/docker.sock

Following the recommendations that are all over the internet, when building my docker image, I was trying to change the ownership of the file using the command:

RUN usermod -a -G docker jenkins

But, since the file belongs to root (user and group) that will never work :man_facepalming:

So, I’ve tried to change the ownership of the file before, with:

RUN chown root:docker /var/run/docker.sock

But, the file isn’t available at the moment of the image build, and since the file doesn’t exist in the filesystem that will never work! :nerd_face:

So, when I was almost giving up and thinking to add jenkins to root group I’ve run into this thread and notice the command:

RUN sudo touch /var/run/docker.sock

And, I thought, let’s give a try and check the results.

And finally, it worked!

Now, my Dockerfile for jenkins looks like this:

FROM jenkins/jenkins:latest

USER root

#install docker
RUN apt-get update && \
       apt-get -y install apt-transport-https \
       ca-certificates \
       curl \
       gnupg2 \
       software-properties-common && \
       curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg > /tmp/dkey; apt-key add /tmp/dkey && \
       add-apt-repository \
       "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
       $(lsb_release -cs) \
       stable" && \
       apt-get update && \
       apt-get -y install docker-ce

#ensures that /var/run/docker.sock exists
RUN touch /var/run/docker.sock

#changes the ownership of /var/run/docker.sock
RUN chown root:docker /var/run/docker.sock

#gives jenkins user permissions to access /var/run/docker.sock
RUN usermod -a -G docker jenkins

USER jenkins

Many thanks, this thread really made my day :partying_face:

I could not get this working. Because mac host is having this permission of docker socket

ls -l /var/run/docker.sock
lrwxr-xr-x  1 root  daemon  72 15 Apr 17:36 /var/run/docker.sock -> /Users/surajthakur/Library/Containers/com.docker.docker/Data/docker.sock

and when it attaches to docker it overrides the existing permission that we set in dockerfile during build

buildkite-agent@5a822ba15d92:~$ ls -l  /var/run/docker.sock
srwxr-xr-x 1 root root 0 Apr 26 10:25 /var/run/docker.sock

Again sudo is not configured that user, so cant use sudo. Any other suggestions here ?

1 Like

I was able to make it work with the following Dockerfile:

FROM jenkins/jenkins:lts-jdk11

USER root

ENTRYPOINT chown jenkins:jenkins /var/run/docker.sock && runuser -u jenkins -- /sbin/tini -- /usr/local/bin/jenkins.sh

Basically, I changed the entry point to chmod the docker socket file, and calling afterwards the original entrypoint.

Not futureproof, as the Jenking entrypoint can change at any time, but works for now.

Never change the permission of your mounted socket file inside the container! It will be changed on the host too.
You can use socat as root forward a tcp socket to a unix socket. This is how I did it: httpd24-docker-image/local-builder.yml at d8f6807ee454b42ed11b044e5e84da3af0bf5372 · itsziget/httpd24-docker-image · GitHub

version: "3.7"

services:
  socat:
    image: alpine/socat
    command: tcp-listen:2375,fork,reuseaddr unix-connect:/var/run/docker.sock
    user: root
    volumes:
      - type: bind
        source: /var/run/docker.sock
        target: /var/run/docker.sock
    network_mode: host

  ci:
    depends_on:
      - socat
    build:
      dockerfile: local-builder.Dockerfile
      context: .
    environment:
      DOCKER_HOST: localhost:2375
    network_mode: host

I used the host network but it should work without it setting DOCKER_HOST to the right value.

2 Likes

Interestingly enough, on a Mac, it doesn’t propagate the ownership changes back to the host, or at least not for me :). I think it’s related to the fact that the /var/run/docker.sock is mounted with root:root ownership, ignoring any host settings for the socket file.

Actually, I retract that :slight_smile: It seems that you’re right, and the ownership change propagates upstream, just that on a Mac, the ownership change happens only at the “Hypervisor VM” Docker Desktop is creating to be able to operate on this OS. Back to the drawing board, as I really want to be able to use the unix socket.

Should be the accepted answer for this problem. Very nice. Removing the host network mode and setting the DOCKER_HOST to the container name works just fine