Allow setting `userns` on a per job basis (docker-executor with podman backend)

Description

TL;DR

When running jobs as non-root user, file permissions are a frequent source of problems. With the userns command-line argument being available from the job specification, file permission issues can be circumvented for the podman backend.

Detailed description

The following applies to the docker executor when being used with podman as backend. I'm referring to podman instead of docker here, because

  1. I'm using podman in my setup
  2. podman's documentation is way clearer compared to docker's in this regard

When running jobs as a non-root user (either by means of the USER directive or by means of the recently introduced user config key), source files remain owned by root. Even worse, in a multi-stage pipeline, files being generated by a non-root user in one stage may well end up without actual owner in subsequent stages.

To my understanding, this is because how user and group ids are mapped from the runner host into the execution container: by default, the host user (gitlab-runner) get's mapped to uid 0 (root) even when using either the USER directive or the user config key. Source files end up being owned by root inside the container. Generating files inside the container as non-root user leaves such files with "dangling" owner uids (i.e. do not point to existing users) on the host and in subsequent containers.

As described in podman's troubleshooting guides (item 2, item 34 and item 36), this can be mitigated by using the keep-id mode for the userns commandline argument to podman run.

To my understanding, the docker executor already has support for the userns commandline argument by means of the userns_mode config key. Currently, this config key applies to runners (as opposed to jobs). I.e. one can only specify a custom uid mapping "globally" for a single runner instead of on a per-job basis within a pipeline.

Proposal

To specify a custom uid mapping on a per-job basis, I suggest to extend the image:docker config key by an additional field userns. I suggest userns to take a string (in order to accommodate all the possible values for userns as documented) and to make it overwrite userns_mode from the runner's config in case both keys are specified.

Example:

arm-sql-job:
  script: echo "Run sql tests"
  image:
    name: super/sql:experimental
    docker:
      platform: arm64/v8
      user: dave
      userns: "keep-id:uid=1042,gid=1042"

would pass --userns=keepid:uid=1042,gid=1042 to the underlying call to podman run.

Unfortunately, docker does not support this kind of userns (at least, I did not find it being documented). But adding the userns config key to jobs does not harm users using the docker backend either (they simply cannot take advantage of it).

Links to related issues and merge requests / references

Edit: fixed link to image:docker config key

Edited by 90degs2infty