架設 Go Proxy 服務加速 go module 下載速度

golang logo

Go 語言在 1.11 推出 go module 來統一市面上不同管理 Go 套件的工具,像是 dep 或 govendor 等,還不知道如何使用 go module,可以參考之前寫的一篇文章『Go Module 導入到專案內且搭配 Travis CI 或 Drone 工具』,在團隊內如果每個人在開發專案時,都透過網路去下載專案使用到的套件,這樣 10 個人就會浪費 10 個人的下載時間,並且佔用公司網路頻寬,所以我建議在公司內部架設一台 Go Proxy 服務,減少團隊在初始化專案所需要的時間,也可以減少在跑 CI/CD 流程時,所需要花費的時間,測試過公司 CI/CD 流程,有架設 Go Proxy,一般來說可以省下 1 ~ 2 分鐘時間,根據專案使用到的相依性套件用量來決定花費時間。本篇來介紹如何架設 ATHENS 這套開源 Go Proxy 專案。

教學影片

架設 ATHENS 服務

你也可以使用外面公開的 GO Proxy 服務,非 China 地區請使用 goproxy.io,如果在中國內地,請使用 gorpoxy.cn,會降低不少 CI/CD 時間。架設 ATHENS 並不難,只需要透過 Docker 一個指令就可以完成,更詳細的步驟可以參考官方文件

export ATHENS_STORAGE=~/athens-storage
mkdir -p $ATHENS_STORAGE
docker run -d -v $ATHENS_STORAGE:/var/lib/athens \
   -e ATHENS_DISK_STORAGE_ROOT=/var/lib/athens \
   -e ATHENS_STORAGE_TYPE=disk \
   --name athens-proxy \
   --restart always \
   -p 3000:3000 \
   gomods/athens:latest

其中 ATHENS_STORAGE 請定義一個實體空間路徑,存放從網路抓下來的第三方套件,當然 ATHENS 還有支援不同的 storage type,像是 Memory, AWS S3 或公司內部有架設 Minio,都是可以設定的。

如何使用 Go Proxy

使用方式非常簡單,只要在您的開發環境加上一些環境變數

$ export GO111MODULE=on
$ export GOPROXY=http://127.0.0.1:3000

接著專案使用的任何 Go 指令,只要需要 Donwload 第三方套件,都會先詢問公司內部的 Proxy 服務,如果沒有就會透過 Proxy 抓一份下來 Cache,下次有團隊同仁需要用到,就不需要上 Internet 抓取了。

至於 CI/CD 流程該如何設定呢?非常簡單,底下是 drone 的設定方式:

- name: embedmd
  pull: always
  image: golang:1.12
  commands:
  - make embedmd
  environment:
    GO111MODULE: on
    GOPROXY: http://127.0.0.1:3000
  volumes:
  - name: gopath
    path: /go

心得

團隊如果尚未導入 GO Proxy 的朋友們,請務必導入,不然就要自己 cache mod 目錄,但是我覺得不是很方便就是了,架設一台 Proxy,不用一分鐘,但是可以省下團隊開發及部署很多時間,這項投資很值得的。

  • 張育誠

    想請教一下,athens-proxy有架起來了,但是drone好像連不到
    我試了link, network設定在一起
    也試了Aliase連接跟IP(docker engine那台server ip)直接連
    但是都連不成功

    還把它寫到drone的docker-compose內,像這樣

    drone-server:
    image: drone:latest
    ports:
    - 80:8000
    - 9000
    networks:
    - drone

    athens-proxy:
    image: gomods/athens:v0.5.0
    ports:
    - 3001:3000
    networks:
    - drone

    .drone.yml

    go-test:
    image: golang:1.12
    environment:
    GO111MODULE: "on"
    GOPROXY: http://athens-proxy:3001
    commands:
    - go test github.com/ggwhite/go-masker -cover
    when:
    event: [ push ]

    結果:

    go: finding gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce
    go: finding github.com/go-sql-driver/mysql v1.4.1
    go: finding github.com/mattn/go-colorable v0.1.2
    go: finding github.com/satori/go.uuid v1.2.0
    go: finding github.com/golang/mock v1.3.1
    go: finding github.com/kr/pretty v0.1.0
    go: finding github.com/denisenkom/go-mssqldb v0.0.0-20190806190131-db2462fef53b
    go: finding github.com/golang/protobuf v1.3.2

    go: gopkg.in/mgo.v2@v2.0.0-20180705113604-9856a29383ce: Get http://athens-proxy:3000/gopkg.in/mgo.v2/@v/v2.0.0-20180705113604-9856a29383ce.info: dial tcp: lookup athens-proxy on 127.0.0.11:53: no such host

  • appleboy48

    應該是 http://athens-proxy:3000 不是 3001

  • 張育誠

    他是跟我說 no such host

    不過單純用個contanier ping是可以

    docker run --rm --network drone alpine ping athens-proxy

    PING athens-proxy (172.28.0.2): 56 data bytes
    64 bytes from 172.28.0.2: seq=0 ttl=64 time=0.126 ms
    64 bytes from 172.28.0.2: seq=1 ttl=64 time=0.095 ms

  • 張育誠

    我發現Drone本身的container可以
    但是.drone.yml內生出來的container不行

  • appleboy48

    喔喔,因為不同網路架構,我建議你直接用個 domain 對應到該台 VM,然後再 .drone.yml 直接寫 http://your_domain:3001 這樣比較快。

  • 張育誠

    好笑的是我本機一樣架個drone跑一樣的東西
    連ip+port
    我本機上的可以,公司上的不行

  • appleboy48

    兩邊的 network 可能要比對一下,另外如同我上面的建議,搭建一個有 domain 的,應該可以解決