Suppose you have a private Git Repository in your project, how do you solve it? Right now go mod defaults to proxy.golang.org to grab the latest data, but if you want to grab the private one, you need to do it some other way:

1
go env -w GOPRIVATE=github.com/appleboy

The above represents the go command that tells you to read github.com/appleboy as soon as you encounter it, no need to go through the Proxy process. Using GitHub as an example, how do you use it for local development? First, you have to apply for a Personal Access Token, and then set up the Git

1
git config --global url."https://$USERNAME:$ACCESS_TOKEN@github.com".insteadOf "https://github.com"

The Username is the GitHub account, and the Access token is the Personal Access Token above.

With Drone CI/CD

The first step in the CI/CD process is to download the Go package, so we need to do the above steps again. First, write main.go.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package main

import (
    "fmt"

    hello "github.com/appleboy/golang-private"
)

func main() {
    fmt.Println("get private module")
    fmt.Println("foo:", hello.Foo())
}

In this case, golang-private is a private repository. Then copy the YAML file to Drone as in the native version.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
steps:
- name: build
  image: golang:1.14
  environment:
    USERNAME:
      from_secret: username
    ACCESS_TOKEN:
      from_secret: access_token
  commands:
  - go env -w GOPRIVATE=github.com/$USERNAME
  - git config --global url."https://$USERNAME:$ACCESS_TOKEN@github.com".insteadOf "https://github.com"
  - go mod tidy
  - go build -o main .

Compiling with Dockerfile

Now that Docker supports Multiple Stage, basically many deployment methods are moving towards a Dockerfile solution, and of course the Go language is no exception, so let’s look at the traditional way of writing:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Start from the latest golang base image
FROM golang:1.14 as Builder

RUN GOCACHE=OFF

RUN go env -w GOPRIVATE=github.com/appleboy

# Set the Current Working Directory inside the container
WORKDIR /app

# Copy everything from the current directory to the Working Directory inside the container
COPY . .

ARG ACCESS_TOKEN
ENV ACCESS_TOKEN=$ACCESS_TOKEN

RUN git config --global url."https://appleboy:${ACCESS_TOKEN}@github.com".insteadOf "https://github.com"

# Build the Go app
RUN go build -o main .

CMD ["/app/main"]

From the above, you can see that the same way to read Private Repository in Docker using git, but you will find two problems with the above compiled image, the first is the file size is particularly large, of course you will say that then use alpine can also ah, yes, but still very large. The other most important problem is that ACCESS_TOKEN is exposed, so you can run docker build directly on the local side first.

1
2
3
docker build \
  --build-arg ACCESS_TOKEN=test1234 \
  -t appleboy/golang-module-private .

Then you can use the following command to find out directly what commands are given and what parameters are brought in for each layer?

1
2
docker history --no-trunc \
  appleboy/golang-module-private

You will find a line where you can see the ACCESS_TOKEN of your application.

1
/bin/sh -c #(nop)  ENV ACCESS_TOKEN=xxxxxxx

If your docker image is on docker hub and is public, it will be taken away directly. It’s the same as having your GitHub account stolen. What is the best way to solve this problem? It’s simple: you can solve it with multiple stages.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Start from the latest golang base image
FROM golang:1.14 as Builder

RUN GOCACHE=OFF

RUN go env -w GOPRIVATE=github.com/appleboy

# Set the Current Working Directory inside the container
WORKDIR /app

# Copy everything from the current directory to the Working Directory inside the container
COPY . .

ARG ACCESS_TOKEN
ENV ACCESS_TOKEN=$ACCESS_TOKEN

RUN git config --global url."https://appleboy:${ACCESS_TOKEN}@github.com".insteadOf "https://github.com"

# Build the Go app
RUN go build -o main .

FROM scratch

COPY --from=Builder /app/main /

CMD ["/main"]

Using multiple stages not only minimizes image size, but also prevents specific ARGS from being seen to be broken. In this way, you can successfully read private git repositories with optimal security.

Integrate Drone to automate Docker Image uploads

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
- name: build-image
  image: plugins/docker
  environment:
    ACCESS_TOKEN:
      from_secret: access_token
  settings:
    username:
      from_secret: username
    password:
      from_secret: password
    repo: appleboy/golang-module-private
    build_args_from_env:
      - ACCESS_TOKEN

The above simply passes ACCESS_TOKEN to ARGS settings via environment. With Drone, it is easy to automatically compile and upload to Docker Hub or your own Private Registry.