不一样的go语言-athens私仓安装
前言
本系列文章曾多次提及go的依赖管理,提到了私仓,构件系统等概念,也曾提及当前流行的go构件系统,如athens,jfrog artifactory。鉴于jfrog的收费特性,本文只选择athens着重介绍。包括安装、使用、踩坑、源码分析等。
简要介绍
在依赖管理方面,go相较于其他语言,其提供了从开放的源码仓库(github、bitbucket等)动态获取源码的工具,最早是go get,go1.11后又新增了go mod。而像java,其本身并没有提供类似的命令,因而才诞生了maven、gradle这样的构建系统。它们的构件则来源于公共仓库或者自行搭建的私有仓库。go的创造者估计是想回避掉这些问题,而直接由官方来提供,这样更便利于开发人员。但其短板则在于私仓,因为私仓在网络、权限、安全等方面会有诸多的限制,并不能像github那样公开,在这样的情况下,go get或者go mod也只能是心有由而力不足。鉴于此,go提出了GOPROXY的概念,通过vgo download protocol协商软件包的获取。剩下的网络、权限等问题就交由proxy server来解决了。
go软件包协议
Defining Go Modules,协议的开头,Russ Cox就指明了go modules的设计目标,只要包括以下六点:
- 希望约定以tag的方式发布软件包,同时又能支持获取指定commit的软件包;
- 希望不借助其他版本管理工具为实现软件包的获取;
- 希望支持软件包的多版本管理;
- 希望在获取软件包时拥有前置个人或公司的代理仓库或私有仓库的能力;
- 希望支持在未来扩展实现公有仓库,同时又能在没有公有仓库的情况下正常运作;
- 希望废弃vendor文件夹。
协议的主体内容主要包括:
项 | 内容 | 描述 |
---|---|---|
软件包版本 | 遵循语义版本2.0(Semantic Versioning) | 同时支持tag与commit方式 |
go mod | go.mod | 定义go.mod文件的内容 |
软件包 | 定义软件包在源码库的组织方式 | 支持分支方式、子目录方 |
发布方式 | 定义软件包的发布方式 | 软件包仓库需支持go-get=1参数获取软件包meta |
打包方式 | 定义软件包的打包方式 | 在构件系统中以zip格式保存 |
下载协议 | 定义软件包如何从构件系统获取 | 实现四个或六个http请求接口 |
代理服务 | 定义GOPROXY服务系统的概念 | 如goproxy.io, gocenter.io |
download protocol约定以下四个http请求接口:
- GET baseURL/module/@v/list: 获取指定软件包的所有已知版本信息,每个版本一行。
- GET baseURL/module/@v/version.info: 获取指定软件包特定版本的json格式元数据。
- GET baseURL/module/@v/version.mod: 获取指定软件包特定版本的mod文件。
- GET baseURL/module/@v/version.zip: 获取指定软件包特定版本的zip源码包。
其中version.info响应定义如下:
type RevInfo struct {
Version string // version string
Name string // complete ID in underlying repository
Short string // shortened ID, for use in pseudo-version
Time time.Time // commit time
}
以下两个请求为可选实现:
- GET baseURL/module/@t/yyyymmddhhmmss:获取与指定时间戳最近的一个版本,响应数据与version.json接口一致
- GET baseURL/module/@t/yyyymmddhhmmss/branch: 获取指定分支下,与指定时间戳最近的一个版本,响应数据与version.json接口一致。
athens私仓搭建
依前文所述,go的构件系统其实是由两部分组成的,一是实现了vgo download protocol的服务;二是软件包仓库。前者是纯代理模式,比如goproyx.io,gocenter.io,其本身并不存储软件包,而只是转发请求从指定仓库(github等)获取所需软件包。后者真的就只是一个软件包仓库(如github,github目前并不是GOPROXY,虽然它可以是)。而athens则既是代理又是软件包仓库(类似于nexus,属于本地缓存仓,原始软件包仍然在公共仓库或私有仓库)。接下来的篇幅,着重于介绍如何安装并使用athens。
athens本身使用go语言编写,除了通过常规运行方式之外,还支持docker、k8s的方式运行,本文介绍的方式为第一种。常规的运行方式遇到问题或者踩到深坑,可较快速找到问题所在,不需要再去考虑装载容器的因素。
系统与网络环境说明:
项 | 说明 |
---|---|
操作系统 | linux, centos 7 |
gitlab | 内网ip, 192.168.197.26,http端口10080,ssh端口10022,域名git.example.com |
athens宿主机 | 内网ip, 192.168.197.205 |
go | go 1.12 |
git client | git-bash |
前方高能预警,为避免不必要的踩坑行为,特提醒如下。
- 务必为gitlab配置域名
- 务必使用https
以上两点,已经可以避免ip、域名、端口诸多烦人的问题。比如go get指令是不支持这样的指令的:
[eventer@localhost]# go get github.com:8080/gomods/athens
go get github.com:8080/gomods/athens: malformed module path "github.com:8080/gomods/athens": invalid char ':'
当然如果gitlab满足以上两点, 同时http与ssh端口又是默认80与443端口,那么athens体验过程应更为轻松。
安装步骤:
- 下载&编译athens
[eventer@localhost]# pwd
[eventer@localhost]# /home/eventer
[eventer@localhost]# git clone https://github.com/gomods/athens.git
[eventer@localhost]# cd athens
[eventer@localhost]# make build-ver VERSION="0.2.0"
- 运行athens
[eventer@localhost]# pwd
[eventer@localhost]# /home/eventer/athens
[eventer@localhost]# ./athens -config_file=./config.dev.toml
到这一步,默认配置的情况下,go的构件系统已经搭建好了,只需要将自己开发环境的go环境变量GOPROXY指向这里即可。IP地址:192.168.197.205:3000。其中192.168.197.205是athens安装机器ip。
- 修改默认配置
打开config.dev.toml,可能要修改的配置项说明如下。
配置项 | 说明 |
---|---|
Port | 端口号,默认3000 |
StorageType | memory, disk, mongo, gcp, minio, s3。本安装过程选择disk |
FilterFile | 过滤策略,与GlobalEndpoint配合使用。 |
GlobalEndpoint | 全局代理,即athens的GOPROXY,可设置为https://goproxy.io |
NETRCPath | 自动登录脚本,放在当前用户home目录下,文件名.netrc此处可用于访问git |
GithubToken | github访问令牌,用于访问github |
HGRCPath | Mercurial自动登录脚本,放在当前用户home目录下,文件名.hgrc |
Stogage->Storage.Disk | 当StorageType为disk时,需要修改此处 |
FileterFile
athens约定的软件包过滤策略,当前可用策略包括D、-、+三种。D必须存在且放在第一行;-表示禁止下载此软件包,若请求,报403;+表示不从指定的GlobalEndpoint下载,而直接从域名指定的仓库获取软件包。-与+对软件包的策略可指定至版本,多个版本用,号分隔,甚至可使用版本修饰符(~, ^, >)。此外#开头的行表示注释,会被忽略。
D
# 内网的gitlab不需要通过GlobalEndpoint下载
+ git.example.com
+ github.com/gomods/athens v0.1,v0.2,v0.4.1
修饰符 | 说明 |
---|---|
~ | ~1.2.3表示激活所有大于等于3的patch版本,在语义化版本方案中,最后一位的3表示补丁版本。如1.2.3, 1.2.4, 1.2.5 |
^ | ^1.2.3表示激活所有大于等于2的minor与大于等于3的patch版本。如1.2.3, 1.3.0 |
< | <1.2.3表示激活所有小于1.2.3的版本。如1.2.2, 1.0.0, 0.1.1 |
这个过滤策略主要用于API兼容或者软件包license改变时使用。
NETRCPath
自动登录脚本,即遇到指定machine需要输入用户名密码时,则从登录脚本中寻找是否有匹配的配置项。示例如下:
# filename: .netrc
machine 192.168.197.26
login eventer
password 123456
- gitlab访问配置
前文已经讲述vgo download protocol,因此当athens接收到go get或go mod的指令时,需要做出正确的回应。这四个接口是依次执行下去的,后一个接口依赖于前一个接口的响应。而这其中的关键在于两个地方,其中一个是软件包仓库支持的获取元数据的接口(GET baseURL/module?go-get=1),第二个是获取软件包(GET baseURL/module/@v/version.zip)。当athens收到GET baseURL/module/@v/version.info指令时,如果本地没有,会直接调用go mod命令去指定的软件包仓库下载。而这个命令的第一步就是获取软件包元数据,即向软件包仓库发起请求GET baseURL/module?go-get=1,按照协议,软件包仓库应该返回如下类似响应:
<!DOCTYPE html><html><head><meta content='git.example.net/module git https://git.example.net/module.git' name='go-import'></head></html>
之后go会使用git clone命令下载zip软件包至本地,至此go mod的使命完成。然后athens将软件包加上版本号,改名后放至本地仓库中,等待GET baseURL/module/@v/version.zip。
可以看到关键的两步,第一步要返回准确的git地址,第二步要能访问git并clone下来。
对于第一步,低版本的gitlab可能会返回不正确的meta,这里提供的方案是使用nginx来处理。方案如下(不同gitlab环境可能nginx的配置会有所不同,比如路径匹配):
if ($args ~* "^go-get=1") {
set $condition goget;
}
if ($uri ~ ^/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)) {
set $condition "${condition}path";
}
if ($condition = gogetpath) {
return 200 "<!DOCTYPE html><html><head><meta content='git.example.net/$1 git http://git.example.net/$1.git' name='go-import'></head></html>";
}
对于第二步,其实有两个方案可用,一是使用前文所说的.netrc文件,二是使用ssh。本文选择的是ssh。
ssh方案要处理两件事情,一是go调用git clone命令,使用的是https协议,需要替换为ssh协议,这可以通过gitconfig文件完成,示例如下:
[eventer@localhost]# pwd
[eventer@localhost]# /home/eventer
[eventer@localhost]# touch .gitconfig
.gitconfing内容如下:
# filename: .gitconfig
[url "ssh://git@192.168.197.26:10022"]
insteadOf = https://git.example.com
[url "ssh://git@192.168.197.26:10022"]
insteadOf = https://192.168.197.26:10080
[url "ssh://git@192.168.197.26:10022"]
insteadOf = git://git@git.example.com
二是https协议替换成ssh后,需要生成及指定ssh所用的私钥。这个通过.ssh目录做文章。
[eventer@localhost]# pwd
[eventer@localhost]# /home/eventer
[eventer@localhost]# cd .ssh
[eventer@localhost]# ssh-keygen -t rsa -C "your.email@example.com" -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/data/rfchina/.ssh/id_rsa): git_id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in aaaa.
Your public key has been saved in aaaa.pub.
The key fingerprint is:
SHA256:0/jCNSuQ5vuOl/URiFH466dm+B+dgVSaVi3T5eSKs1Q your.email@example.com
The key's randomart image is:
+---[RSA 4096]----+
| o. oo+|
| o =o+o|
| + .= Eoo|
| ..ooo.+ . |
| + S +.=.o |
| o o +o+.+ o |
| . +=o.o.o |
| o+o+ o. |
| o+o+o+. |
+----[SHA256]-----+
RSA秘钥对生成之后,将公钥放置到gitlab的ssh keys中,私钥放在home目录下的.ssh目录中。
然后配置config文件,指定哪个host使用哪个私钥。
[eventer@localhost]# pwd
[eventer@localhost]# /home/eventer
[eventer@localhost]# cd .ssh
[eventer@localhost]# touch config
config内容如下:
# filename: config
Host 192.168.197.26
HostName 192.168.197.26
Port 10022
StrictHostKeyChecking no
IdentityFile /home/eventer/.ssh/git_id_rsa
FilterFile文件用于指引athens哪些域名不从外网获取,其内容如下:
D
+ git.example.com
鉴于国内的网络环境,还需要配置DownloadMode文件,内容如下
downloadURL = "https://goproxy.io"
mode = "async_redirect"
download "git.example.com/*" {
mode = "sync"
}
download "github.com/gomods/*" {
mode = "sync"
}
download "golang.org/x/*" {
mode = "none"
}
download "github.com/pkg/*" {
mode = "redirect"
downloadURL = "https://gocenter.io"
}
配置完成之后,可在athens宿主机上尝试运行git clone命令,如果能顺序获取到源码,则配置正确。否则需要根据athens的log并在宿主机上尝试运行go mod或go get指令来检查问题。
至此,athens可以访问私有的gitlab源码库了。go私仓安装教程毕。
如果采用docker方式安装,athens的环境变量已在config.dev.toml中的注释中给出。简略安装步骤如下:
[eventer@localhost]# pwd
[eventer@localhost]# /home/eventer
[eventer@localhost]# mkdir -p athens/storage
[eventer@localhost]# cd athens/storage
[eventer@localhost]# mkdir gitconfig
[eventer@localhost]# mkdir ssh-keys
[eventer@localhost]# export $ATHENS_STORAGE=/home/eventer/athens/storage
[eventer@localhost]# docker run -d -v $ATHENS_STORAGE:/var/lib/athens \
> -v $ATHENS_STORAGE/gitconfig/.gitconfig:/root/.gitconfig \
> -v $ATHENS_STORAGE/ssh-keys:/root/.ssh \
> -e ATHENS_DISK_STORAGE_ROOT=/var/lib/athens \
> -e ATHENS_FILTER_FILE=/var/lib/athens/FilterFile \
> -e ATHENS_GLOBAL_ENDPOINT=https://goproxy.io \
> -e ATHENS_STORAGE_TYPE=disk \
> --name athens-proxy \
> --restart always \
> -p 3000:3000 \
> gomods/athens:latest
在执行docker run命令之前,将前文所述的.gitconfig拷贝至/home/eventer/athens/storage/gitconfig目录下,同时将config与git_id_rsa文件拷贝至/home/eventer/athens/storage/ssh-keys目录下。
#查看docker日志
[eventer@localhost]# docker logs -f athens-proxy
#进入docker
[eventer@localhost]# docker exec -it athens-proxy /bin/sh
#重启docker
[eventer@localhost]# docker restart athens-proxy
#停止docker
[eventer@localhost]# docker stop athens-proxy
#删除docker
[eventer@localhost]# docker rm athens-proxy
欢迎关注个人公众号
不一样的go语言-athens私仓安装的更多相关文章
- 不一样的go语言-athens源码概览
前言 上一篇文章介绍了athens私服的安装以及vgo download protocol的简要介绍.本文着重介绍go proxy sever的实现原理以及athens是如何实现的. go get ...
- 如何搭建自己的Maven远程私仓
1.首先,配置好Maven,jdk等必备环境 2.配置好环境后,下载最新版本的nexus 下载地址:http://www.sonatype.org/nexus/go 3.打开目录nexus-***\b ...
- Maven deploy部署jar包到远程私仓
Maven deploy部署jar包到远程私仓 maven deploy介绍 maven中的仓库分为两种,snapshot快照仓库和release发布仓库.snapshot快照仓库用于保存开发过程中的 ...
- kubernetes配置secret拉取私仓镜像
2017.05.10 19:48* 字数 390 阅读 5216评论 0喜欢 8 对于公司内部的项目, 我们不可能使用公有开放的镜像仓库, 一般情况可能会花钱买docker私仓服务, 或者说自己在服务 ...
- Maven私仓配置
<?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://mav ...
- 纯净CentOS搭建harbor镜像私仓
物理宿主机IP: 192.168.1.4 在官网下载 CentOS-7-x86_64-DVD-1810 用Hyper-v建立一代虚机,安装时遇分辨率问题无法继续,需要在选择启动界面按TAB键以编辑启 ...
- maven私仓搭建——nexus3
maven私仓搭建——nexus3本文主要介绍maven私仓在windows下的搭建.本文主要参考:http://www.cnblogs.com/bingyeh/p/5913486.html好,下面上 ...
- 04使用harbor配置私仓
安装harbor之前,需要安装好Python,Docker,DockerCompose.Python需要2.7以上的版本,Docker需要1.10以上的版本:Docker Compose 需要1.6. ...
- scala语言简介及其环境安装
scala语言简介及其环境安装 简介: 1.运行在JVM 上,兼容java语言 Scala的代码,都需要经过编译为字节码,然后交由Java虚拟机来运行.所以Scala和Java是可以无缝互操作的.Sc ...
随机推荐
- Python 3.5安装 pymysql 模块
原文链接: http://www.maiziedu.com/article/8272/ 事情是这样的,使用python3.4,django1.8,mysql5.5搭建一个web开发环境,由于pytho ...
- Django学习手册 - 初识自定义分页
核心: <a href='http://127.0.0.1:8000/index-%s'>%s<a> 自定义分页 1.前端处理字符 后端的字符 return render(r ...
- Android数据存储五种方式
1 使用SharedPreferences存储数据:常用于做本地缓存 2 文件存储数据:(1)data/data/<package name>/files目录内 (2)SDCard内 ...
- 【TensorFlow】tf.nn.softmax_cross_entropy_with_logits的用法
在计算loss的时候,最常见的一句话就是 tf.nn.softmax_cross_entropy_with_logits ,那么它到底是怎么做的呢? 首先明确一点,loss是代价值,也就是我们要最小化 ...
- swift计算 switch case
var year = var month = var day = ; let daysOfFeb = year % == && year% != || year % == ?: var ...
- 使用Groovy的sql模块操作mysql进行多种查询
连接数据库,这里要创建一个sql实例来操作数据库,必须加载jdbc驱动包,使用两个注解,否则会报错: import groovy.sql.Sql url='jdbc:mysql://localhost ...
- JavaScript中Function的拓展
Function 是什么东西,就是JavaScript中的顶级类,系统级别的类.我们平时写的函数方法例如下. function Animal() { } Animal就是Function的实例,但是在 ...
- 【Python】多线程-线程池使用
1.学习目标 线程池使用 2.编程思路 2.1 代码原理 线程池是预先创建线程的一种技术.线程池在还没有任务到来之前,创建一定数量的线程,放入空闲队列中.这些线程都是处于睡眠状态,即均为启动,不消耗 ...
- BN讲解(转载)
本文转载自:http://blog.csdn.net/shuzfan/article/details/50723877 本次所讲的内容为Batch Normalization,简称BN,来源于< ...
- AT91RM9200---定时器简介
1.前言 系统定时器模块集成了3个不同的定时器 一个周期性间隔的定时器,用来为操作系统设置时基 一个看门狗定时器,可用于软件死锁时进行系统复位 一个实时时钟计数器用来记录流逝的时间 系统定时器时钟 这 ...