boxboat/fixuid

Merge fixdockergid with fixuid

felipecrs opened this issue · 7 comments

I made fixdockergid to prove that #19 is a valid use case.

However, it would be so cool to have this functionality in fixuid instead, so we would not have to deal with this twice. fixdockergid depends on fixuid being installed.

This problem happens when you mount the docker.sock from the host machine on the container, and you try to access it using a non-root user. Then, the docker group id on the host can mismatch with the docker group id from the container, thus causing the non-root users to receive permission denied errors when trying to run docker commands. Microsoft solved it by using socat: https://github.com/microsoft/vscode-dev-containers/tree/master/containers/docker-from-docker#enabling-non-root-access-to-docker-in-the-container

But I consider this approach much better, less intrusive, and less expensive.

We could consider adding another configuration option, such as:

secondaryGroups:
  - name: docker
    gidFromPath: /var/run/docker.sock

The following rules would apply:

  1. If the path does not exist, log an error and skip the path
  2. If the GID from the path already exists in /etc/groups, do not change the group name, but still add the user to the group (and log a message)

Actually, ensuring the group name is docker inside of the container is important, as it allows to use in detached + exec mode:

$ docker run --detach --name=fixdockergid --volume=/var/run/docker.sock:/var/run/docker.sock --user=$(id -u):$(id -g) --group-add=docker felipecrs/fixdockergid sleep infinity
$ docker exec fixdockergid docker version

If the group within the container is not named docker, the --group-add=docker would not be mapping directly to the group which got fixed by fixdockergid, and when running docker exec fixdockergid docker version it would throw a permission denied error.

This use case matters because this is how Jenkins handle pipelines running inside of containers.

Does fix of #30 actually address this issue as well?

I think this could be achieved by adding the GID of the group, computed on the host like this:

docker run ... \
  --volume=/var/run/docker.sock:/var/run/docker.sock \
  --group-add "$(getent group "$(ls -lh /var/run/docker.sock | awk '{ print $4}')" | cut -d':' -f3)"

There may be no named group that matches inside the container, but the container will have access to the socket on the host

I think this could be achieved by adding the GID of the group, computed on the host like this:

docker run ... \
  --volume=/var/run/docker.sock:/var/run/docker.sock \
  --group-add "$(getent group "$(ls -lh /var/run/docker.sock | awk '{ print $4}')" | cut -d':' -f3)"

There may be no named group that matches inside the container, but the container will have access to the socket on the host

Yes, this works. But not for the use case I mentioned... Jenkins.

There, I can pass a list of arguments that should be added to the docker run, but I cannot add a Bash command expansion like this, only static args.

Maybe:

# /etc/fixuid.yml

secondaryGroups:
  - name: docker
    gidFromPath: /var/run/docker.sock
    ensureGroupName: true

If ensureGroupName is enabled, fixuid will not only ensure the user has a group with such GID, but will also rename the group that points to that GID to name:, if one already exists.

Not to mention that we still need the basic functionality of ensuring secondary groups as proposed by @caleblloyd:

secondaryGroups:
  - name: docker
    gidFromPath: /var/run/docker.sock

BTW, I added some tests in fixdockergid to confirm the usefulness of ensureGroupName that I mentioned above:

felipecrs/fixdockergid@2fe4cce