Getting “Permission Denied” error when pulling a docker image in Jenkins docker container on Mac

Leon Feng
The Startup
Published in
4 min readNov 6, 2019

I was following this tutorial to build a python app using the latest Jenkins container on my mac(10.14)

The image below shows what happened.

TL;DR, check out the solution at the bottom

Environment:

macOS: 10.14

docker CE: 19.03.2

Problem:

Briefly speaking, I created a Jenkins container on my mac and mounted the docker socket and other local directories to the container like what has been mentioned in the tutorial. However, the user in the Jenkins container doesn’t have access permission to the mounted docker socket. I googled this problem, and most of the solutions are the same “adding the user to docker group”. Unfortunately, I misunderstood the solution and got frustrated at the beginning, since there is no “docker group” on macOS, at least I could not find one on my mac.

Command to list all groups on a macOS

dscacheutil -q group

Later I noticed that the user is the one in the Jenkins container instead of the user on my mac.

These commands can reproduce the situation

# create a jenkins container and mount the local docker socket to the container
docker run -d --name jenkins -p 8080:8080 -p 50000:50000 -v /var/run/docker.sock:/var/run/docker.sock -v $(pwd)/local:/var/jenkins_home -v "$HOME":/home jenkinsci/blueocean

The newly created container is named Jenkins. I log in to the container and check its user information.

docker exec -it jenkins bash

Use id to show id and group of the current user, and use docker version to check docker information.

bash-4.4$ id
uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins)
bash-4.4$ docker version
Client:
Version: 18.09.8-ce
API version: 1.39
Go version: go1.11.5
Git commit: 0dd43dd87fd530113bf44c9bba9ad8b20ce4637f
Built: Sat Jul 20 15:21:00 2019
OS/Arch: linux/amd64
Experimental: false
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/version: dial unix /var/run/docker.sock: connect: permission denied

The default user in the container is named jenkins, and its id is 1000 . This user belongs to a user group called jenkins . The id of the group is also 1000 , but they are used to identify different entities(one for the user, the other for the group). This user has access to the Docker client in the container but not to/var/run/docker.sock.

Necessary background knowledge:

A UID (user identifier) is a number assigned by Linux to each user on the system. This number is used to identify the user to the system and to determine which system resources the user can access.

Show all users in the container

bash-4.4$ cat /etc/passwdroot:x:0:0:root:/root:/bin/ash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
ntp:x:123:123:NTP:/var/empty:/sbin/nologin
smmsp:x:209:209:smmsp:/var/spool/mqueue:/sbin/nologin
guest:x:405:100:guest:/dev/null:/sbin/nologin
nobody:x:65534:65534:nobody:/:/sbin/nologin
jenkins:x:1000:1000:Linux User,,,:/var/jenkins_home:/bin/bash
...

A GID (group identifier) is a name that associates a system user with other users sharing something in common.

Show all groups in the container

bash-4.4$ cat /etc/grouproot:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm
adm:x:4:root,adm,daemon
nogroup:x:65533:
nobody:x:65534:
jenkins:x:1000:jenkins
docker:x:101:

...

All files and directories are “owned” by the user who created them. The creator can specify who is allowed to read the file, write to the file, or (if it is an application instead of a text file) who can execute the file.

Display details of the /var/run/docker.sock

bash-4.4$ ls -l /var/run/docker.socksrw-rw---- 1 root docker 0 Nov  4 15:26 /var/run/docker.sock# orbash-4.4$ stat /var/run/docker.sockFile: /var/run/docker.sock
Size: 0 Blocks: 0 IO Block: 4096 socket
Device: 10h/16d Inode: 16532 Links: 1
Access: (0660/srw-rw----) Uid: (0/root) Gid: (101/docker)
Access: 2019-11-05 23:05:38.374793000 +0000
Modify: 2019-11-04 15:26:12.637335983 +0000
Change: 2019-11-05 23:05:13.623936000 +0000
Birth: -

The docker.sock is owned by the user root whose id is 0 and group docker whose id is 101.

srw-rw---- 1 root docker 0 Nov  4 15:26 /var/run/docker.sock
| | | | | |
| | | | owner group
| | | |--- all other users or groups
| | |-- group permission
| |--- owner permission
|--- file type

The ownership of this socket can be dissected into 3 parts:

  1. owner’s permission: rw- . root user, in this case, can write and read this file, but cannot execute it.
  2. owner group’s permission: rw- same as the owner. The owner group is docker.
  3. all other groups or users: --- . Cannot read, write or execute it. Eg. jenkins

Obviously, the user jenkins doesn’t have the permission to write to or read from the docker socket.

At this moment, I realized that the Jenkins container uses the default user jenkins to start all the Jenkins services, and this user is in the jenkinsgroup, not the docker group.

The solution becomes clear: adding userjenkins to groupdocker .

Solution:

  1. log in the container as root user, since userjenkins cannot perform the operation. docker exec -it -u root jenkins bash
  2. install a library called shadow . The Jenkins image is on top of alpine image, it doesn’t have usermod command. Then add the user jenkins to docker group.
apk --no-cache add shadow
usermod -aG docker jenkins

3. log out and restart the container docker restart jenkins

4. user jenkins in the container should have permission now.

Reference:

https://wiki.archlinux.org/index.php/File_permissions_and_attributes

--

--