go proxy結合nginx解決golang項目公私有模塊依賴問題

go從1.11開始引入了go module,其中有一個go proxy的特性能幫我們解決第三方模塊的下載,比如 golang.org/x 下的模塊。同時公司也有自己的私有模塊要依賴。這裏是一步解決同時下載公私有模塊的問題。

(注意: goproxy終極解決方法看這裏,這裏適用go1.11、1.12)

1.公用的go proxy

常用的go proxy

export GOPROXY=https://goproxy.io

export GOPROXY=https://athens.azurefd.net

# 國內的
export GOPROXY=https://goproxy.cn

go get 會去請求go proxy,go proxy有的話就返回來,沒有就去github、golang.org等vcs去下載,再緩存起來

2.自己的go proxy

一般公司都有自己的gitlab、gogs之類的託管平臺,上面的公用的go proxy下載不了公司內部的依賴,一個簡單的方法就是找一臺能上谷歌的內網機器做 go proxy,這樣既能下外網的依賴,也能下內網的依賴。這裏假設git.test.com是我公司git服務器的域名。我們可以用這個微軟開源的athens

簡單部署

base=/home/chen/athens
data_dir=$base/data
user_dir=$base/root
name=athens-proxy

# athens默認是3000端口
# 網絡模式用了host模式,以便訪問內網的機器和域名

docker run -d \
  --name ${name} \
  -v ${data_dir}:/var/lib/athens \
  -v ${user_dir}:/root \
  -e ATHENS_DISK_STORAGE_ROOT=/var/lib/athens \
  -e ATHENS_STORAGE_TYPE=disk \
  --net host \
  --restart always \
  gomods/athens:v0.5.0

# 假設內部域名是git.test.com,可以在主機的/etc/hosts裏面加進去
# go get默認走https協議,如果你的gitlab或者gogs只有http或者ssh兩種訪問方式,用ssh替代https

docker exec ${name} git config --global url."[email protected]:".insteadOf "https://git.test.com"

# 記得進入容器裏面用 ssh-keygen -t rsa 命令生成祕鑰,把公鑰上傳到git服務器
# 公鑰存在容器的/root/.ssh/下

# athens也可以用默認的網絡模式,不過明顯慢了很多
docker run -d \
  --name ${name} \
  -v ${data_dir}:/var/lib/athens \
  -v ${user_dir}:/root \
  -e ATHENS_DISK_STORAGE_ROOT=/var/lib/athens \
  -e ATHENS_STORAGE_TYPE=disk \
  --add-host=git.test.com:192.168.40.131 \
  --restart always \
  gomods/athens:v0.5.0

開啓go proxy

# 假設athens所在的ip是192.168.1.100
export GO111MODULE=on
export GOPROXY=http://192.168.1.100:3000

在你的go代碼裏面

# 依賴的go module是 git.test.com/web/server.git ,在go.mod能看到
import "git.test.com/web/server.git/pkg/utils"

3.不用翻的go proxy

nginx是個好東西,利用它的路由匹配規則,轉發到不同的go proxy處理,這樣就不用翻了
這裏nginx機器是192.168.40.131
(注意利用nginx的緩存,這裏沒寫)

# athens.conf
# 把該文件放到/etc/nginx/conf.d/下並執行重啓 nginx -s reload

server {
    listen 4000;
    
    # 外部的依賴轉發到外面的go proxy
    location / {
        proxy_pass https://goproxy.cn;
    }
    # 內部依賴的go proxy,也就是上面啓動的athens
    # github的依賴也可以走本地的go proxy,可以做緩存
    location ~ /(git\.test\.com|github\.com)/ {
        proxy_pass http://192.168.1.100:3000;
    }
}

然後

export GOPROXY=http://192.168.40.131:4000

4.解決go get包必須帶 .git 後綴的問題

看上面我們知道每次下載都要加上.git後綴

go get git.test.com/web/[email protected]

代碼裏面

import "git.test.com/web/server.git/pkg/utils"

有沒有辦法去掉路徑裏面的 .git 呢,當然有啦。首先你的gitlab或者gitea等先開啓https,自己做CA,CA簽發證書給服務器用,準確來說給git服務器的nginx用,然後客戶端pc導入CA的根證書

先把https裏面的概念理清楚,再去做,理解了才能靈活運用

關於證書生成:
Centos(重點看): 基於OpenSSL自建CA和頒發SSL證書
Ubuntu: Ubuntu使用OpenSSL生成數字證書詳解

ubuntu導入ca根證書注意:

# 假設ca的根證書是cacert.pem,重命名成crt結尾的
cp cacert.pem cacert.crt
mv cacert.crt /usr/local/share/ca-certificates/
update-ca-certificates

curl -v https://git.test.com  #測試

# 如何不成功試試這個格式轉換的,再重新導入
openssl x509 -outform der -in cacert.pem -out cacert.crt

看完上面的文章你應該能生成用於gitlab或者gitea的簽發證書和私鑰了吧
注意: 簽發證書時 Common Name 最好填授予證書的服務器域名或主機名,這裏是 git.test.com,其他情況你也可以試試

不管是gitlab還是gitea,如何利用nginx解決路徑帶.git的問題,看 這篇文章

gitlab開啓https我就不說了,解決路徑帶 .git的問題上面說了

例子
下面說說我用的gitea(gogs的社區版):
gitea安裝
gitlab有配套的nginx組件,gitea沒有,那就自己做一個反向代理好了,直接上nginx的配置

# gitea的默認端口好巧也是3000,自己可以改配置,我改成3333
upstream gitea {
    server 192.168.40.131:3333;
}

# nginx剛好跟gitea在同一臺機器
server {
    listen 192.168.40.131:80;
    server_name git.test.com;   

    # 這裏選擇重定向到https去
    rewrite ^(.*)$ https://${server_name}$1 permanent; 
    
    # 也可以不重定向
    #location / {
    #	proxy_pass http://gitea;
    #}
}

server {
    listen    443;
    server_name  git.test.com;
    
    ssl on;
    ssl_session_cache        shared:SSL:10m;
    ssl_session_timeout      20m;
    ssl_session_tickets       on;
    ssl_certificate /data/gitea/ssl/server.crt;      # 自己ca簽發的
    ssl_certificate_key /data/gitea/ssl/server.key;  # 自己的私鑰
    
    location / {
        proxy_cache off; 
        proxy_pass http://gitea;
    }
    location ~* ^/[^/]+/[^/]+$ {
        if ($http_user_agent ~* '^go.*') {
            return 200 "<!DOCTYPE html><head><meta content='$host$uri git ssh://git@$host:$uri.git' name='go-import'></head></html>";
        }
        proxy_cache off;
        proxy_pass http://gitea;
    }
    location ~* ^/(?<holder>[^/]+)/(?<project>[^/]+)/.*$ {
        set $goRedirect 'https://$host/$holder/$project?$args';
        if ($http_user_agent ~* '^go.*') {
            return 301 $goRedirect;
        }
        proxy_cache off;
        proxy_pass http://gitea;
    }
}

athens也要做改變了,它要導入我們自己製作的CA根證書

base=/home/chen/athens
data_dir=$base/data
user_dir=$base/root
cert_dir=$base/ca   #這裏存放ca的根證書,它是cacert.pem重命名爲cacert.crt的,參考Ubuntu是如何導入ca證書的
name=athens-proxy

docker run -d \
  --name ${name} \
  -v ${data_dir}:/var/lib/athens \
  -v ${user_dir}:/root \
  -v ${cert_dir}:/usr/local/share/ca-certificates \
  -e ATHENS_DISK_STORAGE_ROOT=/var/lib/athens \
  -e ATHENS_STORAGE_TYPE=disk \
  --restart always \
  --net host \
  gomods/athens:v0.5.0
  
docker exec ${name} sh -c 'update-ca-certificates'

# 記得進入容器裏面用 ssh-keygen -t rsa 命令生成祕鑰,把公鑰上傳到git服務器
# 公鑰存在容器的/root/.ssh/下

go代碼裏面

# 路徑裏面沒有.git了,這次舒服了吧
import "git.test.com/web/server/pkg/utils"

總結,go get–>nginx–>go proxy–>nginx–>gitea,一路走下來不容易啊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章