iTranslated by AI
[Docker] The uid option for RUN --mount=type=ssh
Introduction
This article assumes some prior knowledge of Docker BuildKit. If you would like to learn more about BuildKit, please refer to the official documentation or other articles.
To be honest, reading the link above might not be enough to understand everything. For specific features like --mount, you will likely need to look them up individually, such as checking the RUN section in the Dockerfile reference.
About --mount
Suppose you want to build a Docker image that depends on the contents of a private Git repository.
In the past, there were primarily two ways to do this: either git clone on the host (which holds the credentials) and use the COPY command, or COPY the private key to the image and git clone during the build process. With the latter method, you had to be especially careful to use multi-stage builds to ensure the private key wasn't inadvertently left in the image [1].
Since Docker 18.09, BuildKit has become available, allowing us to benefit from several useful features like parallelization. One of these features is --mount, which can be specified in a Dockerfile to mount a filesystem and reference it during the build.
You can specify the type of mount, such as bind, cache, secret, or ssh. When you want to perform a git clone, ssh is the appropriate choice.
For example, if you create a Dockerfile with the following content and try to build it normally, you will naturally get a "Permission denied" error.
FROM ubuntu
RUN apt-get update
RUN apt-get install -y ssh
RUN mkdir -m 700 ~/.ssh
RUN ssh-keyscan github.com > ~/.ssh/known_hosts
RUN ssh -T git@github.com
$ docker build .
:
Warning: Permanently added 'github.com' (ED25519) to the list of known hosts.
git@github.com: Permission denied (publickey)
:
However, by prefixing the command with --mount=type=ssh, enabling BuildKit [2] with DOCKER_BUILDKIT=1, and passing --ssh default, SSH authentication will succeed as shown below.
(Though the build still fails because the exit code is 1.)
FROM ubuntu
RUN apt-get update
RUN apt-get install -y ssh
RUN --mount=type=ssh ssh -o StrictHostKeyChecking=no -T git@github.com
$ DOCKER_BUILDKIT=1 docker build --ssh default --progress plain build .
:
#9 1.720 Hi eduidl! You've successfully authenticated, but GitHub does not provide shell access.
:
When trying to run as a non-root user
However, if you create a dev user and try to do the same thing as that user, it will fail.
FROM ubuntu
RUN apt-get update
RUN apt-get install -y ssh
RUN useradd -m -u 1000 dev
USER dev
RUN mkdir -m 700 ~/.ssh
RUN ssh-keyscan github.com > ~/.ssh/known_hosts
RUN --mount=type=ssh ssh -T git@github.com
$ DOCKER_BUILDKIT=1 docker build --ssh default --progress plain build .
:
#10 1.214 git@github.com: Permission denied (publickey).
:
This is because, by default, the mount is only visible to the user with uid=0. It will work again if you explicitly specify uid=1000 (corresponding to useradd -u 1000) in the Dockerfile.
FROM ubuntu
RUN apt-get update
RUN apt-get install -y ssh
RUN useradd -m -u 1000 dev
USER dev
RUN mkdir -m 700 ~/.ssh
RUN ssh-keyscan github.com > ~/.ssh/known_hosts
RUN --mount=type=ssh,uid=1000 ssh -T git@github.com
$ DOCKER_BUILDKIT=1 docker build --ssh default --progress plain build .
:
#10 1.942 Hi eduidl! You've successfully authenticated, but GitHub does not provide shell access.
:
Other available options can be found here:
References
I solved the issue by referring to this when I had no idea what the cause was:
-
Nonetheless, it feels like this happens naturally when trying to minimize image size. ↩︎
-
It is also possible to always enable BuildKit in
/etc/docker/daemon.json(https://docs.docker.com/build/buildkit/#getting-started) ↩︎
Discussion