Fetching Private Go Modules During Docker Build

# ERROR 1
go: github.com/jwenz723/privatepackage@v1.0.0: unknown revision v1.0.0
go: error loading module requirements
# ERROR 2
github.com/inContact/orch-entity-contact@v0.0.0-20190530222558-8a8073e6b7d7
: git fetch -f origin refs/heads/*:refs/heads/* refs/tags/*:refs/tags/* in /go/pkg/mod/cache/vcs/72c960bac0ed57f7476f8d5540fea5f31c278ae0591ac68bee5481c69cc5a5ef: exit status 128:
fatal: could not read Username for 'https://github.com': terminal prompts disabled

Create a Personal Access Token

Before proceeding with the solutions listed below, you will need a personal access token that has ‘repo’ access to your private git repositories that contain your go dependencies. For example, if you use GitHub, then after logging in browse here. Click the button to create a new token, check the ‘repo’ option (see screenshot below), then click Generate Token. Copy the personal access token that is generated and save it somewhere for later.

Solution 1

The easy route is to create a .netrc file in a directory near your Dockerfile. The .netrc file should contain your git user and personal access token that you generated in the previous step. For example, if my git user was mygituser and my personal access token was 12345678901234567890 then my .netrc file would look like this:

machine github.com
login mygituser
password 12345678901234567890
machine api.github.com
login mygituser
password 12345678901234567890
# First stage: build the executable.
FROM golang:1.12.5-alpine AS builder
# git is required to fetch go dependencies
RUN apk add --no-cache ca-certificates git
# Create the user and group files that will be used in the running
# container to run the process as an unprivileged user.
RUN mkdir /user && \
echo 'nobody:x:65534:65534:nobody:/:' > /user/passwd && \
echo 'nobody:x:65534:' > /user/group
# Copy the predefined netrc file into the location that git depends on
COPY ./netrc /root/.netrc
RUN chmod 600 /root/.netrc
# Set the working directory outside $GOPATH to enable the support for modules.
WORKDIR /src
# Fetch dependencies first; they are less susceptible to change on every build
# and will therefore be cached for speeding up the next build
COPY ./go.mod ./go.sum ./
RUN go mod download
# Import the code from the context.
COPY . .
# Build the executable to `/app`. Mark the build as statically linked.
RUN CGO_ENABLED=0 go build \
-installsuffix 'static' \
-o /app .
# Final stage: the running container.
FROM scratch AS final
# Import the user and group files from the first stage.
COPY --from=builder /user/group /user/passwd /etc/
# Import the Certificate-Authority certificates for enabling HTTPS.
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
# Import the compiled executable from the first stage.
COPY --from=builder /app /app
# Perform any further action as an unprivileged user.
USER nobody:nobody
# Run the compiled binary.
ENTRYPOINT ["/app"]

Solution 2

Since we can’t commit the netrc file into git, then we should make the docker build create the file at build time. This can be accomplished using the following Dockerfile (the only difference between this file and the last is that the netrc file is being created by the printf RUN command using user specified build-args):

# First stage: build the executable.
FROM golang:1.12.5-alpine AS builder
# It is important that these ARG's are defined after the FROM statement
ARG ACCESS_TOKEN_USR="nothing"
ARG ACCESS_TOKEN_PWD="nothing"
# git is required to fetch go dependencies
RUN apk add --no-cache ca-certificates git
# Create the user and group files that will be used in the running
# container to run the process as an unprivileged user.
RUN mkdir /user && \
echo 'nobody:x:65534:65534:nobody:/:' > /user/passwd && \
echo 'nobody:x:65534:' > /user/group
# Create a netrc file using the credentials specified using --build-arg
RUN printf "machine github.com\n\
login ${ACCESS_TOKEN_USR}\n\
password ${ACCESS_TOKEN_PWD}\n\
\n\
machine api.github.com\n\
login ${ACCESS_TOKEN_USR}\n\
password ${ACCESS_TOKEN_PWD}\n"\
>> /root/.netrc
RUN chmod 600 /root/.netrc
# Set the working directory outside $GOPATH to enable the support for modules.
WORKDIR /src
# Fetch dependencies first; they are less susceptible to change on every build
# and will therefore be cached for speeding up the next build
COPY ./go.mod ./go.sum ./
RUN go mod download
# Import the code from the context.
COPY . .
# Build the executable to `/app`. Mark the build as statically linked.
RUN CGO_ENABLED=0 go build \
-installsuffix 'static' \
-o /app .
# Final stage: the running container.
FROM scratch AS final
# Import the user and group files from the first stage.
COPY --from=builder /user/group /user/passwd /etc/
# Import the Certificate-Authority certificates for enabling HTTPS.
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
# Import the compiled executable from the first stage.
COPY --from=builder /app /app
# Perform any further action as an unprivileged user.
USER nobody:nobody
# Run the compiled binary.
ENTRYPOINT ["/app"]
docker build -f Dockerfile.buildargs -t test --build-arg ACCESS_TOKEN_USR=mygituser --build-arg ACCESS_TOKEN_PWD=12345678901234567890 .
docker build -f Dockerfile.buildargs -t test --build-arg ACCESS_TOKEN_USR=${ACCESS_TOKEN_USR} --build-arg ACCESS_TOKEN_PWD=${ACCESS_TOKEN_PWD} .

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store