How to resolve “Permission Denied” Errors in Docker

If you’ve recently installed Docker on your Linux system, you might have encountered this frustrating error message when trying to run Docker commands without sudo:

docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.35/containers/create: dial unix /var/run/docker.sock: connect: permission denied.

This common roadblock happens because Docker’s daemon runs as root by default, and the Docker socket file has restrictive permissions. In this comprehensive guide, I’ll walk you through multiple approaches to solve this issue, explain why each works, and help you choose the best solution for your specific environment.

Understanding the Problem: Why Do You Get “Permission Denied”?

Before diving into solutions, it’s important to understand what’s happening behind the scenes. When you install Docker, it creates a Unix socket at /var/run/docker.sock that facilitates communication between the Docker client and the Docker daemon. By default, this socket is owned by the root user and the root group, with permissions that don’t allow other users to access it.

When you run a Docker command as a regular user, your user attempts to communicate with the Docker daemon through this socket, but gets denied because it lacks the necessary permissions. That’s why prefixing commands with sudo works—it temporarily elevates your privileges to root level.

Let’s look at the underlying issue by checking the socket’s permissions:

ls -la /var/run/docker.sock

You’ll likely see something like:

srw-rw---- 1 root root 0 Mar 8 09:15 /var/run/docker.sock

The srw-rw---- indicates that only the owner (root) and members of the root group have read-write access to this socket.

Read: How to install and setup Docker on Ubuntu 22.04

Solution 1: The Recommended Approach – Add Your User to the Docker Group

The Docker team officially recommends creating a docker group and adding your user to it. This approach properly balances convenience and security, though it does come with some security implications that we’ll discuss later.

Here’s the step-by-step process:

Step 1: Create the docker group (if it doesn’t exist)

sudo groupadd docker

This command creates a new Unix group called docker. In many cases, the Docker installation process already creates this group, so don’t worry if you see a message saying the group already exists.

Step 2: Add your user to the docker group

sudo usermod -aG docker $USER

This command adds your current user (represented by $USER) to the docker group. The -a flag ensures we’re appending the group rather than replacing existing group memberships, and the -G specifies we’re modifying the user’s groups.

Step 3: Apply the new group membership

For the new group membership to take effect, you need to either log out and log back in, or use one of these commands to update your current session:

newgrp docker

This switches your current session to the new docker group.

Alternatively, you can use:

su - $USER

This logs in as your current user again, which forces a refresh of your group memberships.

Step 4: Verify the solution works

Test if you can now run Docker commands without sudo:

docker run hello-world

If you still encounter permission issues, a system reboot might be necessary:

sudo reboot

Solution 2: Modify Socket Permissions Directly

If adding your user to the Docker group doesn’t work or isn’t suitable for your environment, you can modify the permissions of the Docker socket file directly. This is a more immediate solution but needs to be reapplied after system reboots.

Option A: Change the Socket’s Group Ownership

sudo chown root:docker /var/run/docker.sock
sudo chmod 660 /var/run/docker.sock

This changes the group ownership of the socket to the docker group and sets permissions so that both the owner (root) and the group members (docker) can read and write to the socket.

Option B: Change the Socket’s User Ownership

sudo chown $USER /var/run/docker.sock

This approach makes your user the owner of the socket file. While effective, it’s generally less recommended since it doesn’t preserve the security model as well as using groups.

Option C: Use Access Control Lists (ACLs)

For more fine-grained control, you can use Access Control Lists:

sudo setfacl -m user:$USER:rw /var/run/docker.sock

This grants read-write access specifically to your user without modifying the base permissions. Note that you might need to install the ACL utilities first:

sudo apt install acl  # For Ubuntu/Debian
# or
sudo yum install acl  # For CentOS/RHEL

Read: How to Set Environment Variables in Docker

Solution 3: Permanent Socket Configuration

The solutions above may need to be reapplied after each system restart. For a more permanent solution, you can modify the Docker socket service configuration:

sudo nano /lib/systemd/system/docker.socket

Change the configuration to include:

[Unit]
Description=Docker Socket for the API

[Socket]
ListenStream=/var/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker

[Install]
WantedBy=sockets.target

After making changes, reload the systemd configuration and restart Docker:

sudo systemctl daemon-reload
sudo systemctl restart docker

Solution 4: Using Aliases or Functions

If you prefer not to modify system configurations, you can simply create an alias in your shell:

echo 'alias docker="sudo docker"' >> ~/.bashrc
source ~/.bashrc

This creates an alias so that whenever you type docker, it automatically prepends sudo. While this doesn’t fix the underlying permission issue, it does make the commands shorter to type.

Security Considerations

It’s important to understand that giving a user access to the Docker daemon is effectively giving them root-equivalent access to your system. When you’re a member of the docker group, you can create containers that mount the host filesystem and modify it with root privileges.

As Docker’s official documentation warns:

The docker group grants privileges equivalent to the root user. For details on how this impacts security in your system, see Docker Daemon Attack Surface.

For production environments or multi-user systems, carefully consider who gets access to Docker, or look into rootless Docker mode which provides better isolation.

Advanced Solution: Running Docker in Rootless Mode

Docker provides a “rootless mode” that allows running the Docker daemon and containers as a non-root user. This offers the best security isolation but can be more complex to set up and has some limitations.

For high-security environments, consider exploring Docker’s rootless mode documentation at the Docker website.

Troubleshooting Common Issues

Problem: Changes not taking effect after adding user to group

If you’ve added your user to the Docker group but still can’t run Docker commands without sudo, try:

  1. Making sure you’ve applied the group changes with newgrp docker or by logging out and back in
  2. Checking if your Docker daemon is running: sudo systemctl status docker
  3. Verifying the socket permissions again: ls -la /var/run/docker.sock
  4. Restarting the Docker service: sudo systemctl restart docker

Problem: Group changes not persisting through login sessions

Some display managers and authentication systems might have issues with passing group memberships correctly. In these cases:

  1. Check your current groups with groups command
  2. Try running sudo su $USER -c groups to see all assigned groups
  3. If you see a discrepancy, there might be an issue with your login manager or PAM configuration

Problem: Docker socket recreated with wrong permissions after reboot

This typically happens because the systemd socket unit is configuring the socket with default permissions. Use the permanent socket configuration solution described earlier.

Conclusion

Fixing the “permission denied” error in Docker involves understanding Unix socket permissions and user group membership. The recommended approach is to add your user to the Docker group, but several alternatives exist depending on your specific needs and security requirements.

Remember that giving a user access to the Docker daemon essentially grants them elevated privileges on your system, so be cautious about who gets this access, especially in production or multi-user environments.

By following the steps in this guide, you should be able to run Docker commands without sudo while maintaining an appropriate level of security for your use case.

Frequently Asked Questions

Why does running Docker without sudo matter?

Running Docker without sudo improves convenience for developers and aligns with the principle of least privilege—you don’t need to use elevated permissions for all Docker operations. It also prevents accidental modification of system files when working in a shell with sudo.

Will these solutions work on all Linux distributions?

Most solutions work across major Linux distributions, but there might be slight differences in file locations or command syntax. The group-based approach is the most portable and works reliably on Ubuntu, Debian, CentOS, Fedora, and other mainstream distributions.

Do I need to worry about security if I’m the only user on my development machine?

On a single-user development machine, the security risks are lower, but it’s still good practice to follow the least-privilege principle. The Docker group approach provides a good balance of convenience and security for most developers.

What’s the difference between chmod 660 and chmod 666 for the Docker socket?

chmod 660 gives read-write access to the owner and group but no access to others, while chmod 666 gives read-write access to everyone on the system. Always prefer 660 for better security, as 666 would allow any user on the system to access the Docker daemon.

Can I use these same approaches for Docker Compose?

Yes, these solutions also fix permission issues with Docker Compose since it communicates with the same Docker daemon through the same socket file.

Will these changes affect my Docker containers or images?

No, these changes only affect how you interact with the Docker daemon. Your containers, images, networks, and volumes will continue to work exactly as before.


If you like the content, we would appreciate your support by buying us a coffee. Thank you so much for your visit and support.

 

Nikolaus Oosterhof

Nikolaus holds a degree in software development and has a strong passion for all things tech-related, especially gadgets with screens. Though he is nostalgic for older phone models, he's a retired gamer and continues to enjoy programming in open-source environments. Additionally, Nikolaus enjoys writing about Linux, macOS and Windows and has experience designing web pages.

Leave a Reply