How to Add a User to the Docker Group

How to Add a User to the Docker Group

Reading time1 min
#Docker#Linux#Security#DevOps#AWS

How to Add a User to the Docker Group

On Linux, the Docker CLI talks to the daemon through the Unix socket /var/run/docker.sock. The socket is owned by root and the group docker. A user who is in neither gets permission denied mentioning /var/run/docker.sock and ends up typing sudo docker for everything. Adding the user to the docker group fixes that.

Read the security section before doing it on a shared machine. Membership in the docker group is equivalent to root.

Add a user

# The group is created by the Docker packages; create it if it is missing
getent group docker || sudo groupadd docker

# Add the current user
sudo usermod -aG docker "$USER"

# Or a specific user
sudo usermod -aG docker alice

The -a matters. usermod -G docker alice without -a replaces all of alice's supplementary groups with just docker, which can remove sudo or wheel and lock her out of admin rights.

Apply the new group

Group membership is read at login. Existing sessions keep their old groups, so after usermod nothing seems to change. Options:

  • Log out and log back in. Over SSH, close the connection and reconnect. If you use SSH connection sharing (ControlMaster), close the master connection too, or the new session reuses the old one.
  • Start a shell with the new group for the current session only:
    newgrp docker
    
  • Long-running services that run as that user need a restart.

Verify

id                        # docker should appear in the groups list
docker run --rm hello-world

If id lists docker but you still get permission denied:

  • Check the socket: ls -l /var/run/docker.sock should show group docker with read and write permission.
  • Check that the daemon runs: systemctl status docker.
  • A warning like Error loading config file: /home/alice/.docker/config.json ... permission denied means ~/.docker was created by an earlier sudo docker run. Fix the ownership:
    sudo chown -R "$USER":"$USER" "$HOME/.docker"
    

Do not chmod 666 /var/run/docker.sock. It gives every local user and process root-equivalent access, and it is reset when the daemon restarts anyway.

EC2 instances

On Amazon Linux 2023 the default login user is ec2-user:

sudo dnf install -y docker
sudo systemctl enable --now docker
sudo usermod -aG docker ec2-user

Then disconnect and reconnect, whether you came in with plain ssh ec2-user@203.0.113.10, EC2 Instance Connect or SSM Session Manager. On Ubuntu AMIs the login user is ubuntu. Session Manager sessions run as ssm-user by default, so add that user if you work through Session Manager.

To set this up at launch, put the same commands in the instance user data (it runs as root):

#!/bin/bash
dnf install -y docker
systemctl enable --now docker
usermod -aG docker ec2-user

GitLab Runner

This is needed only for the shell executor, where jobs run docker commands directly as the gitlab-runner user. The Docker executor talks to the daemon from the runner service itself and does not need it.

sudo usermod -aG docker gitlab-runner
sudo gitlab-runner restart
sudo -u gitlab-runner -H docker info

If docker info succeeds as gitlab-runner, jobs will too. GitLab's own documentation points out that this gives the runner user full root permissions on the host, so keep such runners off shared machines and away from untrusted projects.

Jenkins

For Jenkins installed from packages, the service runs as the jenkins user:

sudo usermod -aG docker jenkins
sudo systemctl restart jenkins
sudo -u jenkins docker info

The restart is required. The running Jenkins process keeps the group list it started with.

If Jenkins itself runs in a container with the host socket mounted, there is no usermod to run. Give the container the socket's group ID instead:

docker run -d --name jenkins \
  -p 8080:8080 \
  -v jenkins_home:/var/jenkins_home \
  -v /var/run/docker.sock:/var/run/docker.sock \
  --group-add "$(stat -c '%g' /var/run/docker.sock)" \
  my-jenkins:1.0

The image (here a custom my-jenkins built from jenkins/jenkins:lts) must contain the Docker CLI. The same warning applies: any job that can run docker can take over the host. Running builds on dedicated agents rather than on the controller limits the damage.

Why the docker group equals root

The Docker daemon runs as root, and anyone who can talk to it can ask it to do anything root can. For example, mount the host's root filesystem into a container:

docker run --rm -v /:/host alpine cat /host/etc/shadow

No password prompt, no sudo log entry. That is why Docker's own post-install documentation warns that the docker group grants root-level privileges. Add only users you would also give full sudo, and remove them when they no longer need it:

sudo gpasswd -d alice docker

Alternatives to the docker group

  • Rootless Docker. The daemon runs as the user, so access to it is not root on the host. Set it up with dockerd-rootless-setuptool.sh install and the packages the Docker docs list for your distribution. Some features, such as binding ports below 1024, need extra configuration.
  • Keep using sudo. A sudoers rule like alice ALL=(root) /usr/bin/docker logs every invocation but is still root-equivalent for the same reason as above. It is not a security boundary.
  • Docker Desktop. On macOS and Windows the daemon runs in a VM and there is no docker group to manage.

Quick reference

getent group docker || sudo groupadd docker
sudo usermod -aG docker "$USER"         # always -aG, never -G alone
newgrp docker                           # or log out and back in
id && docker run --rm hello-world       # verify

sudo usermod -aG docker ec2-user        # Amazon Linux
sudo usermod -aG docker gitlab-runner && sudo gitlab-runner restart
sudo usermod -aG docker jenkins && sudo systemctl restart jenkins

sudo gpasswd -d alice docker            # remove again