容器仓库是容器化管理中非常重要的一环,相当于SVN在程序研发、运维发布中的地位。因此,一个稳定、可靠的容器仓库尤为重要。
目前我知道的的数据仓库有:
- Docker官方的Registry原生仓库
- SuSE团队推出的出的Portus:https://github.com/SUSE/Portus
- VMWare中国团队推出的企业级仓库—Harbor
- 大家熟知的Maven私服:Sonatype Nexus3
本文主要介绍下Sonatype Nexus 3这个功能强大的产品,它不仅能够用于创建Maven私服,还可以用来创建yum、pypi、npm、nuget、rubygems等各种私有仓库。而且,Nexus从3.0版本也开始支持创建Docker镜像仓库了!
因此,在上述几个产品里面我毫不犹豫的选择了Nexus3作为部门的公共数据仓库,一举多得。
一、部署
这里依然使用最简单的Docker化部署,过程非常之简单!在一台有外网的机器上安装好docker之后,执行如下启动脚本即可:
#!/bin/bash
docker run -dti \
--net=host \
--name=nexus \
--privileged=true \
--restart=always \
-e INSTALL4J_ADD_VM_PARAMS="-Xms4g -Xmx4g -XX:MaxDirectMemorySize=8g" \ # 如果不需要限制java内存请删除此行
-v /etc/localtime:/etc/localtime \
-v /data/nexus:/nexus-data \
sonatype/nexus3:latest
大概2分钟左右可以完成启动,此时可以通过浏览器访问 http://IP地址:8081 即可出现nexus的web界面:
二、配置
1、配置Blob存储
点击右上角的Sign in,输入默认账号密码:admin/admin123 登录到管理员身份。
打开控制页面的按钮,默认进入了仓库配置界面,选择Blob Stores开始创建存储空间:
我这边创建了如下Blob,以备后用:
2、创建Docker仓库
回到前面的repository界面,点击repositories打开页面后点击【create repository】打开仓库类型选择界面(真的非常丰富!):
可以看到Docker有三种类型,分别是docker(group),docker(hosted),docker(proxy)。其含义解释如下:
- hosted : 本地存储,即同docker官方仓库一样提供本地私服功能
- proxy : 提供代理其他仓库的类型,如docker中央仓库
- group : 组类型,实质作用是组合多个仓库为一个地址
下面开始创建Docker仓库:
首先,我们创建一个docker代理仓库,点击docker(proxy),如图填写信息:
往下翻页,勾上 “”,允许Docker V1 API请求。
至于代理的对象,我可以选择官方的镜像地址:https://registry-1.docker.io,但是官方的比较慢,所以这里我们可以填写国内的Docker镜像加速器地址,比如阿里云或DaoCloud的容器加速:
我这里选择了DaoCloud的镜像加速,这里为了确保能够拉取DockerHub最新的镜像,我选择了Use DockerHub 这个Index。
接着,再创建一个本地仓库,这里比较简单,只需要填写本地仓库的名称,比如 docker-hosted,然后填写HTTP端口即可,比如8083:
保存之后,最后创建一个聚合仓库(group),将代理仓库和本地仓库聚合到一起使用,这里我命名为docker,然后端口选择8082:
这里成员仓库的顺序可以稍微规划下,一般来说将本地的放前面,代理第三方的放后面,好处就是优先使用本地或小众的镜像仓库。我这边是用了多个第三方仓库,所有有多个:
至此,nexus在docker这一块是部署已经完成了,但是这样并不能很好的使用。因为group仓库并不能推送镜像,因为你推送自己制作的镜像到仓库还得通过本地仓库的端口去推送,很不方便!
下面分享一下我这边原创的解决方法:通过Nginx来判断推镜像还是拉镜像,然后代理到不同端口,解决这个问题,还是非常巧妙的。
3、配置Nginx
在部署Nginx部分,我们先需要生成自签名SSL证书,因为后面不想在docker pull的时候还要带一个端口!这里我们需要2个域名,一个用来展示nexus前台,另一个用做docker仓库,比如:
nexus前台:repo.xxx.com
docker仓库:idocker.io
生成自签名SSL证书的方法网上很多,这里推荐一个一键生成工具,大家可以尝试使用:https://github.com/Fishdrowned/ssl ,使用方法请参考作者说明。
Ps:如果你打算做外网仓库服务,那也可以去申请一个免费SSL证书,我这边是内部oa域名使用,所以只能用自签名证书了。
Nginx的规则如下:
upstream nexus_web {
server 192.168.1.100:8081;
}
upstream nexus_docker_get {
server 192.168.1.100:8082;
}
upstream nexus_docker_put {
server 192.168.1.100:8083;
}
server {
listen 80;
listen 443 ssl;
server_name idocker.io;
access_log /data/wwwlogs/idocker.io.log access_log_json;
# 证书
ssl_certificate /data/wwwroot/ssl/out/idocker.io/idocker.io.crt;
ssl_certificate_key /data/wwwroot/ssl/out/idocker.io/idocker.io.key.pem;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers '!aNULL:kECDH+AESGCM:ECDH+AESGCM:RSA+AESGCM:kECDH+AES:ECDH+AES:RSA+AES:';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
# disable any limits to avoid HTTP 413 for large image uploads
client_max_body_size 0;
# required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
chunked_transfer_encoding on;
# 设置默认使用推送代理
set $upstream "nexus_docker_put";
# 当请求是GET,也就是拉取镜像的时候,这里改为拉取代理,如此便解决了拉取和推送的端口统一
if ( $request_method ~* 'GET') {
set $upstream "nexus_docker_get";
}
# 只有本地仓库才支持搜索,所以将搜索请求转发到本地仓库,否则出现500报错
if ($request_uri ~ '/search') {
set $upstream "nexus_docker_put";
}
index index.html index.htm index.php;
location / {
proxy_pass http://$upstream;
proxy_set_header Host $host;
proxy_connect_timeout 3600;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
proxy_set_header X-Real-IP $remote_addr;
proxy_buffering off;
proxy_request_buffering off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto http;
}
}
server {
listen 80;
listen 443 ssl;
server_name repo.xxx.com;
index index.html index.htm index.php;
ssl_certificate /data/wwwroot/ssl/out/repo.xxx.com/repo.xxx.com.crt;
ssl_certificate_key /data/wwwroot/ssl/out/repo.xxx.com/repo.xxx.com.key.pem;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers '!aNULL:kECDH+AESGCM:ECDH+AESGCM:RSA+AESGCM:kECDH+AES:ECDH+AES:RSA+AES:';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
access_log /data/wwwlogs/repo.xxx.com.log access_log_json;
location /download {
root /data/wwwroot/repo.xxx.com;
}
location / {
proxy_pass http://nexus_web;
proxy_set_header Host $host;
client_max_body_size 512m;
proxy_connect_timeout 3600;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
proxy_buffering off;
proxy_request_buffering off;
}
}
Nginx部署完成之后,我们还需要将自签名的根证书(ca.crt)导入到客户端才可以正常使用,否则会报不信任错误。
在上文介绍的一键生成自签名工具中,会生成一个根证书,名称为ca.crt,我们将这个文件上传到客户端服务器的 /etc/docker/certs.d/idocker.io 目录即可(注意目录需要创建,最后的文件夹名称和仓库域名保持一致:idocker.io)。
为了方便后面的人使用,我将上述部署证书的过程弄成一个在线脚本,实现快速部署:
#!/bin/bash
bakfile=/tmp/hosts_$RANDOM
# 定义仓库域名和nexus前台域名
docker_domain=idocker.io
repo_domain=repo.xxx.com
# 绑定仓库域名解析
cp /etc/hosts $bakfile || exit 1
echo "/etc/hosts is bakcup to $bakfile"
if grep -q "$idocker_domain" /etc/hosts;then
sed -i 's/.*$docker_domain/192.168.1.100 $docker_domain/g' /etc/hosts
else
echo "192.168.1.100 $docker_domain" >> /etc/hosts
fi
echo
# 探测到仓库是否畅通
if which telnet >/dev/null 2>&1;then
echo start trying to connect to $docker_domain:443 ...
if ! echo "e" | telnet -e "e" $docker_domain 443 >/dev/null;then
echo "Can not connect to $docker_domain:443,Plz check!"
else
echo connect success.
fi
fi
echo
# 开始部署证书
mkdir -p /etc/docker/certs.d/$docker_domain
curl -s -o /etc/docker/certs.d/$docker_domain/ca.crt http://$repo_domain/download/cert/ca.crt
echo Docker repository init success, you need login when you want upload docker images.
echo 'Plz Run "docker login --username=idocker $docker_domain"'
脚本保存为 docker_init.sh,上传到nginx服务器的 /data/wwwroot/repo.xxx.com/download/cert 目录即可。
最终,我们可以使用如下命令行一键部署docker证书:
curl -sSL http://repo.xxx.com/download/scripts/docker_init.sh | sh -s
是不是非常方便?
4、关于高可用
相信用心的同学已经注意到了,Nexus3存在一个单点问题。在看完官方文档后,发现Nexus3的免费版本仅支持单点,只有收费版才支持集群模式:
在高可用方面,我前后做了2个尝试:
①、将数据保存到ceph分布式存储:能用,但是push的速度实在不敢恭维!layer文件越小越慢。
②、折中方案:另外部署一个节点,每隔一段时间将主节点数据同步过去,然后备份节点每隔一段时间重启一次(不重启的话数据不会更新),并且数据再同步一份到ceph确保安全。在Nginx中,将备份节点加入到backup,当主节点宕机的时候,备机可以顶上来继续使用。
当然, 觉得这样做还不够的同学也可以参考官方的备份文档进一步优化:https://help.sonatype.com/repomanager3/high-availability/designing-your-cluster-backup-restore-process
三、小结
docker仓库的使用我就不再赘述了,nexus我们使用的是group这个聚合仓库,本地没有的镜像会去外网搜索,如果存在则拉取并缓存到本地,下次再拉取则直接使用缓存数据。所以,在拉取外网的镜像时,第一次会比较慢,第二次就和本地基本一致了。
上文提到,Nexus还有其他很多实用仓库,比如yum、python、npm、maven等等。我所在的部门也全部用到了,非常好用!感兴趣的同学可以自己去尝试配置,都非常直观简单!当然,后面有空我也会整理一下各个种类仓库的最佳实践,比如各种仓库一键初始化的经验,敬请期待!
博主玩儿的是越来越高深了,看的我一脸懵逼!
我以为是手机上玩儿的啥玩意儿呢?好像不是!
不错不错 学到了
水评论???
大佬
[color=blue]这个我虽然看了很久还是没搞懂是做什么的。[/color]
你好,想请教下你文章中的段落大标题和代码背景色是怎么设置的。谢谢
代码段用的Crayon Syntax Highlighter有纯代码版,博主写过相关文章
啥是容器仓啊
咳咳,,努力看了好几分钟,愣是半点没看懂
我也是一脸懵逼,不过还是从头到尾看完了。
老司机的东西,值得一看
请问博主的源站是不是11*.15*.9*.3* :grin:
看不懂啊
大佬,对比docker私有仓库管理,是nexus3好用还是harbor好用啊
harbor应该更专业,但是更重,要部署N个组件,虽然也可以用docker部署。
nexus3覆盖更全面,啥都可以做,混合仓库,一个能抵多个,主要还是看场景吧,我这里用nexus主要是为了一举多得。
nginx 用的很狡猾
哥们,你的80端口配置有误,其实你的配置项下面少了host的配置,造成v2重定向默认走了80,所以改成如下的配置即可去除80的监听:
你说的是docker仓库去掉80吧,这个直接去掉listen 80也不会报错的吧。