Search code examples
linuxdockerubuntudocker-composeroot

using docker-compose without sudo doesn't work


I was recently told that running docker or docker-compose with sudo is a big nono, and that I had to create/add my user to the docker group in order to run docker and docker-compose commands without sudo. Which I did, as per the documentation here

Now, docker runs normally via my user. e.g. :

~$ docker run hello-world

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete
Digest: sha256:df5f5184104426b65967e016ff2ac0bfcd44ad7899ca3bbcf8e44e4461491a9e
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

But when I try to run docker-compose, I get a Permission Denied

~$ docker-compose --help

-bash: /usr/local/bin/docker-compose: Permission denied

Could you please explain how this works ? I thought having a docker group enabled the usage of these commands because the binaries belong to this group, but actually they don't, they only belong to root...

~$ ls -al /usr/bin/docker*
-rwxr-xr-x 1 root root  71706288 Jul 23 19:36 /usr/bin/docker
-rwxr-xr-x 1 root root    804408 Jul 23 19:36 /usr/bin/docker-init
-rwxr-xr-x 1 root root   2944247 Jul 23 19:36 /usr/bin/docker-proxy
-rwxr-xr-x 1 root root 116375640 Jul 23 19:36 /usr/bin/dockerd
~$ ls -al /usr/local/bin/
total 12448
drwxr-xr-x  2 root root     4096 May 26 11:08 .
drwxr-xr-x 10 root root     4096 May 14 19:36 ..
-rwxr--r--  1 root root 12737304 May 26 11:08 docker-compose

So, how does this work? And how do I enable docker-compose to run for users that belong to the docker group?


Solution

  • sudo chmod a+x /usr/local/bin/docker-compose
    

    As of Jun 2023, the docker-compose command has been deprecated in favor of the compose plugin.

    https://docs.docker.com/compose/install/linux/

    Install the Compose plugin

    sudo apt-get update
    sudo apt-get install docker-compose-plugin
    
    ...
    
    docker compose ps # note that docker and compose are now two words.
    

    Will turn your permissions on.

    docker-compose is just a wrapper, and it uses an external docker daemon, the same way the docker command doesn't actually run anything but gives an order to a docker daemon.

    You can change the docker daemon you communicate with using the DOCKER_HOST variable. By default, it is empty ; and when it is empty, both docker and docker-compose assume it is located at /var/run/docker.sock

    According to the dockerd documentation :

    By default, a unix domain socket (or IPC socket) is created at /var/run/docker.sock, requiring either root permission, or docker group membership.

    And this is enforced by giving read and write access to the docker group to the socket.

    $ ls -l /var/run/docker.sock 
    srw-rw---- 1 root docker 0 nov.  15 19:54 /var/run/docker.sock
    

    As described in https://docs.docker.com/engine/install/linux-postinstall/, to add an user to the docker group, you can do it like that :

    sudo usermod -aG docker $USER # this adds the permissions
    newgrp docker # this refreshes the permissions in the current session
    

    That being said, using docker with sudo is the same as using it with the docker group, because giving acces to the /var/run/docker.sock is equivalent to giving full root acces:

    From https://docs.docker.com/engine/install/linux-postinstall/

    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.

    If root permission is a security issue for your system, another page is mentioned :

    To run Docker without root privileges, see Run the Docker daemon as a non-root user (Rootless mode).


    docker is composed of multiple elements : https://docs.docker.com/get-started/overview/

    First, there are clients :

    $ type docker
    docker is /usr/bin/docker
    $ dpkg -S /usr/bin/docker
    docker-ce-cli: /usr/bin/docker
    

    You can see that the docker command is installed when you install the docker-ce-cli package.

    Here, ce stands for community edition.

    The docker cli communicates with the docker daemon, also known as dockerd.

    dockerd is a daemon (a server) and exposes by default the unix socket /var/run/docker.sock ; which default permissions are root:docker.

    There are other components involved, for instance dockerd uses containerd : https://containerd.io/


    The rest is basic linux permission management :

    • operating the docker daemon is the same as having root permission on that machine.
    • to operate the docker daemon, you need to be able to read and write from and to the socket it listens to ; in your case it is /var/run/docker.sock. whether or not you are a sudoer does not change anything to that.
    • to be able to read and write to and from /var/run/docker.sock, you must either be root or being in the docker group.
    • docker-compose is another cli it has the same requirements as docker.