There are two problems to solve here:
1. How to allow Docker to access local SSH keys, safely?
2. How to tell Go not to use public registry to fetch private packages?
Short Answers
Since Docker v18.09, there's a built-in solution to handle SSH authentication during the build phase (more). It's also much easier and safer, compared to passing build arguments, and eliminates the need for a multi-stage Docker build.
Go has a GOPRIVATE environment variable to identify private packages. (more)
Long Answer
Step-by-step:
1. Make sure ssh-agent is setup and knows the SSH key
Github has a quick guide on this subject, explaining the process for different operating systems. See Generating a new SSH key and adding it to SSH agent.
2. Enable BuildKit for Docker
Without BuildKit, docker build won't recognize --ssh option.
From the Docker reference:
Easiest way from a fresh install of docker is to set the
DOCKER_BUILDKIT=1 environment variable when invoking the docker build
command, such as:
$ DOCKER_BUILDKIT=1 docker build .
To enable docker BuildKit by
default, set daemon configuration in /etc/docker/daemon.json feature
to true and restart the daemon:
{ "features": { "buildkit": true } }
Docker Desktop users can manage daemon configurations via Preferences > Docker Engine.
4. Update Dockerfile
4.1. Make sure Git uses SSH instead of HTTPs
Go tends to fetch public packages via HTTPs. You can adjust this behavior by updating git configurations:
RUN git config --global url.git@github.com:.insteadOf https://github.com/
You should probably do this on your local machine as well.
4.2. Request SSH access where it's required
Each RUN command the needs SSH access should be mounted with type=ssh. For
Example:
RUN --mount=type=ssh git clone ...
4.3. Make sure Go knows your private packages
Update GOPRIVATE variable:
RUN go env -w GOPRIVATE="github.com/your-org/private-repo"
Putting all of it together, in following sample of a Dockerfile:
FROM golang:1.16.3-alpine3.13
RUN apk update
RUN apk add git openssh
RUN mkdir /app
ADD . /app
WORKDIR /app
# You can replace github.com with any other Git host
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
# Make sure git uses SSH to fetch packages, not HTTPs
RUN git config --global url.git@github.com:.insteadOf https://github.com/
# Make Go knows which packages are private.
RUN go env -w GOPRIVATE="github.com/your-org/private-repo"
# GOPRIVATE is a comma separated list glob-patterns.
# You can use a wildcard to match every repo in an organization:
# e.g.: GOPRIVATE="github.com/your-org/*"
# Mount the build command with type `ssh`.
RUN --mount=type=ssh go get && go build -o main .
CMD ["/app/main"]
6. Build the image with --ssh option:
Having BuildKit enabled by default:
$ docker build --ssh default -t my-app:latest .