Accessing private Go modules in a Docker container (with a PAT)
If you're building Docker containers which reference a private Go module, you'll likely need to work out a way to pass in credentials, so you don't have to build on your host machine.
I first encountered this last March and as I've hit it again today, I thought I'm make sure I write it up as a form of blogumentation.
This could be done by using a rewritten URL to call out to the source code provider, embedding the Personal Access Token (PAT) in the URL.
However this would be noted as a security problem:
1 warning found:
- SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "GITLAB_TOKEN") (line 5)
Sensitive data should not be used in the ARG or ENV commands
More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
Additionally, if you were using the Git config, it would persists the secret in the layers of the image so therefore should not be used!!
(See also Why Dockerfile Build Args Shouldn't Be Used For Secrets for more details)
Instead we should instead be using secret mounts.
GitHub
Using SSH
To use SSH from the host, we can use the following Dockerfile
snippet:
FROM golang:1.23
# prepare for SSH
RUN git config --global url."ssh://git@github.com".insteadOf "https://github.com"
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
# ensure that any private modules are declared here
ENV GOPRIVATE=github.com/some-org/repo
WORKDIR /app
COPY go.mod .
COPY go.sum .
RUN --mount=type=ssh go mod download
# then copy everything else
COPY . .
# and do whatever else is needed in the build
# ...
This can then be built by i.e.
# pre-requisites, via https://docs.docker.com/reference/cli/docker/buildx/build/#ssh
$ eval $(ssh-agent)
$ ssh-add ~/.ssh/id_ed25519
# or
$ ssh-add ~/.ssh/id_rsa
# then build it
$ docker buildx build --ssh default .
# or
$ docker buildx build --ssh default=$SSH_AUTH_SOCK .
Using a PAT
For the following Dockerfile
snippet:
FROM golang:1.23
# prepare for PAT
# ensure that any private modules are declared here
ENV GOPRIVATE=github.com/some-org/private-go-module
WORKDIR /app
COPY go.mod .
COPY go.sum .
RUN --mount=type=secret,id=GITHUB_NETRC,dst=/root/.netrc,required=true \
go mod download
# then copy everything else
COPY . .
# and do whatever else is needed in the build
# ...
This can then be built by i.e.
# This requires that you have pre-created a `.netrc` (via: https://www.dudley.codes/posts/2020.12.28-dockerfile-build-args-exposed/)
# ⚠️ ⚠️ ⚠️ ⚠️
# NOTE that you need to make sure that `.netrc` is in your `.gitignore`!!!
# ⚠️ ⚠️ ⚠️ ⚠️
docker build --secret id=GITHUB_NETRC,src=./.netrc .
GitLab
Using SSH
To use SSH from the host, we can use the following Dockerfile
snippet:
FROM golang:1.23
# prepare for SSH
RUN git config --global url."ssh://git@gitlab.com".insteadOf "https://gitlab.com"
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan gitlab.com >> ~/.ssh/known_hosts
# ensure that any private modules are declared here
ENV GOPRIVATE=gitlab.com/some-org/repo
WORKDIR /app
COPY go.mod .
COPY go.sum .
RUN --mount=type=ssh go mod download
# then copy everything else
COPY . .
# and do whatever else is needed in the build
# ...
This can then be built by i.e.
# pre-requisites, via https://docs.docker.com/reference/cli/docker/buildx/build/#ssh
$ eval $(ssh-agent)
$ ssh-add ~/.ssh/id_ed25519
# or
$ ssh-add ~/.ssh/id_rsa
# then build it
$ docker buildx build --ssh default .
# or
$ docker buildx build --ssh default=$SSH_AUTH_SOCK .
Using a PAT
For the following Dockerfile
snippet:
FROM golang:1.23
# prepare for PAT
# ensure that any private modules are declared here
ENV GOPRIVATE=gitlab.com/some-org/private-module
WORKDIR /app
COPY go.mod .
COPY go.sum .
RUN --mount=type=secret,id=GITLAB_NETRC,dst=/root/.netrc,required=true \
go mod download
# then copy everything else
COPY . .
# and do whatever else is needed in the build
# ...
This can then be built by i.e.
# This requires that you have pre-created a `.netrc` (via: https://www.dudley.codes/posts/2020.12.28-dockerfile-build-args-exposed/)
# ⚠️ ⚠️ ⚠️ ⚠️
# NOTE that you need to make sure that `.netrc` is in your `.gitignore`!!!
# ⚠️ ⚠️ ⚠️ ⚠️
docker build --secret id=GITLAB_NETRC,src=./.netrc .