部署自己的私有Docker仓库 - Harbor配置
随着业务开发,微服务和容器部署已经越来越普及,于是想着自己搭建一个私有的容器镜像仓库,DockerHub不是不能用,但就是慢,之前在个人服务器上部署过官方提供的registry镜像,但实在是太简陋了,没有管理面板,而且如果需要删改仓库里的镜像还得改配置文件打开。业务的私有仓库用的是Harbor,由VMware 公司中国团队为企业用户设计的 Registry server 开源项目,功能强大且齐全,而且有中文支持,故打算整一个
配置
Harbor本身也是由一系列Docker容器组成的服务,安装方式分为离线和在线安装,首先到Github下载最新版本,在Assets可以选择离线版和在线版,我选择先下载离线版传到服务器,省的届时各种网络问题

传输到服务器,解压,可以看到一些脚本,一个配置文件模板和一个打包好的镜像文件,首先需要复制一份harbor.yml.tmpl
模板为harbor.yml
,并进入编辑
容器配置启动之后这个安装目录就不能随便移动了,因此请提前规划好安装位置
按照相关教程,第一个hostname
一般是填Harbor仓库的地址,支持IP和域名,不要填0.0.0.0
,相关注释说明也不要用localhost
或127.0.0.1
,因为面板需要提供外部访问,这个地方经过后续测试,必须填写你最终访问到这个服务器采用的方式,是IP还是域名,因为届时docker调用接口时会引导到该域名底下进行认证,错了无法访问,在这里我填写的就是最终访问镜像仓库的地址,底下的http
指定HTTP端口,https
除了指定端口还需要指定证书地址就不在赘述了
如果你因为是动态IP而无法指定一个固定IP使用,那么建议填写域名并利用域名解析的方式
由于我打算使用反代来访问Harbor,因此在此的https端口必须配置为443,这样才能正确引导到正确的域名和端口,在我的这个场景下http配置端口意义不大,详见下文

底下的harbor_admin_password
指定admin
管理员用户的密码,但是在这里不一定非得要去改,因为这只是初次安装启动时的密码,将密码明文存储至配置文件不安全,建议在安装后再在面板上修改密码
前排剧透:修改密码对强度的要求还不少
datebase
项配置Harbor内部存储数据用的数据库配置,作为企业级仓库,也支持使用外部数据库和Redis,有需求的可以翻到下面找到被注释的external_database
和external_redis
进行配置,但是灵活性好像不是很高,数据库用的是PostgreSQL,可能了定制特殊插件,而Redis一定会占用db0存储核心数据,所以如果要外挂数据库建议还是从提供的镜像里新建
data_volume
是需要关注的配置项,用于指定存储卷的位置,存储了数据库和镜像等数据,因此需要规划好路径,除了本地文件存储外,它实际上还支持对象存储等文件系统,其配置本质上是同docker官方的registry配置是一致的,可以参考官方文档的存储部分
trivy
是配置静态扫描工具,自动检测CVE漏洞啥的,一般个人使用用不到
log
部分配置日志相关的内容,包括记录级别,轮转周期,存储位置和轮转大小,当然也支持外部日志服务器,配置下面的external_endpoint
即可
中间被注释的trace
是Trace related链路跟踪的部分直接跳过,还有一个uaa
和自签名证书相关的没有细究,最底下可以看到upload_purging
上传垃圾的清理,默认是一周,以及cache
layer配置缓存,默认关闭,可以按需配置
安装
如果你不是初次接触或者对自己写的配置很有自信,那么可以跳过下文的
./prepare
阶段直接执行./install.sh
,它会在部署阶段自动执行prepare,但如果用我上面的反代配置,会因为主WEB服务已经占用443端口导致proxy服务无法启动,请继续参照下文说明
写完一大堆配置后,执行./prepare
开始生成配置,由于需要访问docker导入镜像,需要提供root权限,配置完成后,当前目录下生成docker-compose,就可以准备启动了,浏览compose配置,可以得知服务大致分为:日志,仓库,控制台,核心,数据库(SQL和Reids),面板,任务调度服务以及最后的nginx提供的proxy服务
最后以root身份执行./install.sh
,脚本会自动导入所有模块的镜像,并执行一次./prepare
,最后创建一个容器网络,并启动容器,看见installed and started successfully字样即成功启动

然后不出意外应该能看到在对应端口启动监听了,采用的反代配置的会无法启动,接下来配置反代相关设置
主Web服务反代至Harbor
如果你不需要反代配置,请跳过本章节
我之所以要绕这么大一圈,是因为这给服务器跑着主WEB服务占用了80和443,虽然也可以用其他端口但不是很优雅,于是便利用虚拟主机和反代接入主WEB服务
为了达到这个目标,首先需要修改的是在prepare后生成的docker-compose,编辑docker-compose.yml
,往下找到最后一个标签为proxy
的服务,5001:8080
是http暴露的端口,在这里已经不需要了直接删掉,将端口映射443:8443
改为你需要最终映射的内部反代端口,例如我需要内部反代到5000则修改为5000:8443

为什么不使用http端口
- 同时配置了http和https的情况下,直接访问http会被重定向到https
- 经过了一天时间的验证,由于Docker API访问需要使用Header鉴权,直接使用http端口会出现反代透传Authorization出现问题,从而验证失败
- 单独配置http已经是官方不推荐选项,在未来将会被移除
在这个反代环境下,调用路径为主WEB服务(https) -> Proxy(https) -> Core(http),如果将Proxy改为http,会导致Authorization在传递到proxy时因为降级为http导致丢失,因此即使是中途经过了一次无意义的TLS加密加密,也只能作为是一种必要的代价了,或许未来能找到更好地办法
然后用compose启动容器组,就能看到正常启动
docker-compose up -d
注意:每次在变更配置后执行
./prepare
时都会导致新的配置覆盖先前的手动修改,一定要记得重复执行上述操作
随便搓一个nginx配置,划分一个Host,并将/
无脑反代至对应端口,暂时别想着用二级路径,避免一些奇奇怪怪的问题,另外参考生成的内部nginx配置,可以添加client_max_body_size 0;
来关闭文件上传限制避免在上传大镜像时出现问题

其他的诸如头部的配置,第一行HSTS自己按需开,如果不知道是啥不建议开,特别是如果加上了includeSubdomains
那么以后你的所有子域名都要https了

实际反代的部分很简单,也是配置一些头部就行了,这些基本上都是复制粘贴的,但也不要无脑粘贴,有些变量不同版本是不支持的,如果reload报错要记得检查,另外两行是为了关掉buffering
我的这个nginx是没有
x_forwarded_proto
这个变量的,就得删掉这一行
主WEB监听443并正确配置对应证书,reload一下,然后直接输入对应域名,成功以外部https默认端口的方式进行访问

配置系统服务
最后编写服务文件,以便于在系统启动时使用docker-compose拉起容器群,新建/etc/systemd/system/harbor.service
[Unit]
Description=Harbor
After=docker.service systemd-networkd.service systemd-resolved.service
Requires=docker.service
Documentation=http://github.com/vmware/harbor
[Service]
Type=simple
Restart=on-failure
RestartSec=5
#需要注意harbor的安装位置
ExecStart=docker-compose -f [Harbor路径]/docker-compose.yml up
ExecStop=docker-compose -f [Harbor路径]/docker-compose.yml down
[Install]
WantedBy=multi-user.target
然后更新service并启动,同时设置开机自启
systemctl daemon-reload
systemctl start harbor.service
systemctl enable harbor.service
使用
第一步先进面板改密码,顺带一提这密码要求还不少

接下来新建一个用户或者机器人都可以,接下来就可以在客户端发起一次docker登录了,如果你配置了非常规端口也要带上,docker默认是连接https的,如果你配置的是http,需要在daemon.json
配置该域名为insecure-registries
,具体方法不在本文讨论范围内
docker login [仓库地址]
接下来尝试本地制作一个镜像并推送,镜像格式需要[仓库地址]/[项目名]/[镜像名]:[版本号],如果仓库有端口号同样不能漏,在这里直接拉了一个现成的镜像,并打一个别名,推送到私有仓库
docker pull alpine
docker image tag alpine:latest [仓库地址]/library/alpine:latest
docker push [仓库地址]/library/alpine:latest

然后镜像就顺利推送到远程仓库了,在仓库面板就能看到刚刚推送的镜像了

在需要部署的主机上,直接执行pull就能拉取镜像了,当然前提是你这个仓库是公有的可以匿名访问,否则就还是需要登录,Harbor自动生成了一个公有项目library
docker pull [仓库地址]/library/alpine:latest

接下来,尽情享受私有化部署的乐趣吧