Docker官方提供了用于搭建私有registry的镜像,并配有详细文档。

官方Registry镜像:https://hub.docker.com/_/registry

官方文档:https://docs.docker.com/registry

根据文档快速搭建的私有registry,只支持http。但是目前docker客户端的pull、push等命令,默认使用https的方式和registry进行交互,这将导致我们搭建的私有registry无法正常使用。

本文将从两个方面入手解决此问题:

  1. 让客户端以http方式和私有registry交互。
  2. 让私有registry支持https。

当然,第二种方式是本文的重点。此外,本文还介绍了如何使用用户名密码的方式,验证客户端身份。

这里假设我们的服务端的ip为:192.168.0.1,没有专用域名。大家在配置时,内网ip外网ip均可。如果有专用域名,处理方式也类似,只是要在生成证书时,注意命令的配置。

客户端使用Http的方式和私有Registry进行交互

这是常用的一种处理方式,优点是方便快捷,分分钟搞定。只要修改客户端docker守护进程的配置文件,将私有registry配置为一个不安全的registry即可 。此后,客户端都将使用http的方式和这个registry交互。主要步骤如下:

在服务端启动私有registry:

docker run -d -p 5000:5000 --name docker-registry registry:2

这个命令只是作为演示,真实环境下肯定还会配置volume。

配置客户端,和私有registry交互:

客户端的daemon.json配置内容如下:

{
"insecure-registries": ["192.168.0.1:5000"]
}

daemon.json的一般路径为:/etc/docker/daemon.json

配置参考官方文档:https://docs.docker.com/engine/reference/commandline/dockerd

启动(或重启)客户端docker,使用以下命令制作一个自己的busybox镜像,并推送至私有registry:

# 制作自己的busybox镜像
docker tag busybox 192.168.0.1:5000/busybox # 将镜像推送至私有registry
docker push 192.168.0.1:5000/busybox

docker会使用http的方式和registry进行交互,将镜像推送至私有registry。

配置私有Registry,支持Https

下面介绍下如何配置私有Registry,使其支持https访问。

准备证书

跟常见的https站点一样,我们先要弄到一份证书,才能让我们自己的registry支持https。证书都是由CA(数字证书管理机构)签发的,我们可以向CA购买证书。根据CA的不同,证书类型的不同,证书的价格相差悬殊,大家可以自己网上搜搜看。如果有兴趣的话,大家还可以通过浏览器的调试工具,看看各大支持https网站的证书,分别是哪些CA签发的。

各个CA都有一份自己的证书(根证书),CA颁发给我们的证书都是用这份根证书签发出来的,操作系统会内置部分CA的根证书(比如受信任的根证书颁发机构下的证书)。这些内置CA签发出来的证书都将会被操作系统认为是安全的。比如某个网站使用了这些CA颁发的证书,那么你在访问这个网站时,浏览器地址栏就会变成绿色,提示你网站是安全的,否则,浏览器会用明显的红色提醒你正在访问不安全的网站。

举个例子,12306的网站:https://kyfw.12306.cn/otn,你在访问时会提示不安全。通过浏览器调试工具查看其证书,发现是一个叫 SRCA 的CA颁发证书给它的。继续百度,得知 SRCA 的全称为:Sinorail Certification Authority(可翻译为中铁数字证书认证中心)。相当于是中铁自己作为CA,给自己旗下的一个网站签发了一份证书。SRCA 的CA资质是肯定不会被国际认可的,道理你懂的,所以 SRCA 也不会被操作系统收录为受信任的CA。结果就是你在访问12306的网站时,浏览器会提示你正在访问不安全的网站。

这个问题的一种处理方式(也是12306网站目前在用的方式),就是把 SRCA 这个CA的根证书安装到系统中,操作系统就会认为由这个CA签发出的证书都是可信的,这样,访问12306的网站就不会再提示证书错误了。12306网站首页上有安装根证书的操作说明,大家可以自行查看。

向知名CA购买证书无疑是最好的选择,这里我们处于学习和个人使用的目的,将采用类似12306的方式,自己作为CA,为自己签发一份证书。

首先,我们自己把自己视为CA,生成一份根证书

# 生成CA私钥
openssl genrsa -out ca.key 2048 # 生成CA证书
openssl req -new -x509 -days 365 -key ca.key -out ca.crt -subj "/C=CN/CN=name"

参数说明:

  • CN=name 指证书的颁发者和使用者均为name(自己给自己签发根证书,颁发者和使用者当然都是自己,没毛病)。建议更改为你的姓名或公司名称。尝试了下中文,出现了乱码,所以建议使用英文。

第二个命令生成的证书(ca.crt文件),就是所谓的CA根证书,到时候要交给客户端安装,否则客户端默认会认为,由这个CA签发出来的证书是不安全的。

再用这份根证书,为我们的registry生成一份证书

# 生成私钥文件
openssl genrsa -out server.key 2048 # 生成证书签名请求文件
openssl req -new -key server.key -out server.csr -subj "/C=CN/CN=192.168.0.1" # 生成证书
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -extfile <(printf "subjectAltName=IP:192.168.0.1") -out server.crt

参数说明:

  • CN=192.168.0.1 指证书的使用者为192.168.0.1,可更改为任意字符串。在私有registry没有域名的情况下,建议更改为私有registry的ip;有域名的情况下,建议更改为域名。此配置不影响证书的正常使用。
  • subjectAltName=IP:192.168.0.1 指明证书使用者的ip必须为192.168.0.1。如果证书颁发给的是域名而非ip,则使用 subjectAltName=DNS:你的域名 作为配置。当然也可以两者使用,比如 subjectAltName=IP:192.168.0.1,DNS:你的域名 ,这种配置应该是同时限制使用者的ip和域名的作用,没有深究。注意,此配置是X509 Version 3的新特性,配置后一份证书可供一个或多个ip(或域名)使用。此配置是必须有,并且是配置正确的,否则https请求会报错。

启动私有registry

命令如下:

docker run -d -p 5000:5000 --name docker-registry \
-v /home/docker-registry:/home/docker-registry \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/home/docker-registry/server.crt \
-e REGISTRY_HTTP_TLS_KEY=/home/docker-registry/server.key \
registry:2

参数说明如下:

  • REGISTRY_HTTP_TLS_CERTIFICATE 证书文件路径
  • REGISTRY_HTTP_TLS_KEY 私钥路径

参考官方文档中的http章节:https://docs.docker.com/registry/configuration/#http

注意,文档中有说明,如果一个配置A是可选的,但它又存在必选的子配置B和C,你可以整个A及其子配置B、C都不配置,否则B和C都必须配置。原文如下:

In some instances a configuration option is optional but it contains child options marked as required. In these cases, you can omit the parent with all its children. However, if the parent is included, you must also include all the children marked required.

配置客户端,安装CA根证书

以下指令用于将证书安装至客户端:

# 备份
cp /etc/pki/tls/certs/ca-bundle.crt{,.backup} # 导入CA根证书
cat ca.crt >> /etc/pki/tls/certs/ca-bundle.crt

如果使用的是window系统,直接双击证书,导入至受信任的根证书颁发机构下的证书目录下即可。运行certmgr.msc命令可打开证书管理器,删除本证书。

客户端和私有Registry交互

注意,如果之前在daemon.json文件中配置过insecure-registries,则必须去掉此配置并重启docker,否则客户端会使用http方式和registry交互,导致交互失败。

推送镜像至私有registry:

# 制作自己的busybox镜像
docker tag busybox 192.168.0.1:5000/busybox # 将镜像推送至私有registry
docker push 192.168.0.1:5000/busybox

docker会使用https的方式和registry进行交互,将镜像推送至私有registry。

配置Registry,使用用户名密码的方式,验证客户端身份

私有registry支持通过使用htpasswd工具生成的用户名密码配置文件,来验证客户端身份。

不同linux发行版的中的htpasswd工具安装方式可能存在不同,这里以CentOS为例:

yum install -y httpd-tools

生成用户名密码配置文件

# 创建用户名密码配置文件.passwd,并新增用户user1,密码手工输入
htpasswd -cB .passwd user1

htpasswd工具的参考文档:https://httpd.apache.org/docs/2.4/programs/htpasswd.html

注意命令中的-B参数,配置后,htpasswd将以bcrypt加密方式加密密码,安全性更高。bcrypt也是docker指定的唯一一种加密方式,其他加密方式均不被支持,详见官方文档中的htpasswd章节:https://docs.docker.com/registry/configuration/#htpasswd

这里再列几个命令用于维护用户:

# 新增用户user2:
htpasswd -B .passwd user2 # 删除用户user2:
htpasswd -D .passwd user2

注意:htpasswd工具并未提供修改密码功能,如需修改密码,可以先删除用户,再新增用户实现。

启动私有registry:

docker run -d -p 5000:5000 --name docker-registry \
-v /home/docker-registry:/home/docker-registry \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/home/docker-registry/server.crt \
-e REGISTRY_HTTP_TLS_KEY=/home/docker-registry/server.key \
-e REGISTRY_AUTH=htpasswd \
-e REGISTRY_AUTH_HTPASSWD_REALM=basic-realm \
-e REGISTRY_AUTH_HTPASSWD_PATH=/home/docker-registry/.passwd \
registry:2

文档中没有对REGISTRY_AUTH_HTPASSWD_REALM这个必选配置有比较详细的说明,自己百度了些资料,大概是用于和silly、token这两种身份验证方式配合使用,没做深究。因为我们这里只用到了htpasswd这种身份验证方式,所以就用文档里的默认配置了。哪位如果比较了解这部分内容,希望不吝赐教。

此后,我们就可以使用用户名密码登录私有registry了,没有登录的客户端将被拒绝访问:

# 登录私有registry
docker login 192.168.0.1:5000 -u user1 -p 你的密码 # 将镜像推送至私有registry
docker push 192.168.0.1:5000/busybox

注意:用户名密码的验证方式只建议在https的方式下使用,因为用户名密码是通过http请求头发送的,如果使用http的方式会很不安全,原文如下:

Only use the htpasswd authentication scheme with TLS configured, since basic authentication sends passwords as part of the HTTP header.

户名密码的验证方式还有个缺点,私有registry只在启动的时候读取htpasswd生成的用户名密码配置文件,所以任何对该配置文件的修改,必须重启registry才能生效,原文如下:

The htpasswd file is loaded once, at startup.

其他私有Registry搭建方式

网上也有很多资料介绍其他私有registry搭建方式,其中一种是在registry前端架设nginx服务器。这种方式也是很值得推荐的,很多公共的registry提供商应该也是扩展这种方式提供服务。

这种方式的其优点有:

  1. nginx会处理https相关内容。
  2. 可以使用nginx配置负载均衡,搭建registry集群,提高registry服务的可靠性。

当然缺点也有:

  1. 配置较繁琐,需要对nginx和registry有比较深入的了解,特别是在涉及到负载均衡和集群时。
  2. 如果涉及到负载均衡和集群,registry的运维工作量也不可小觑。

搭建私有Docker Registry的更多相关文章

  1. Docker系列08—搭建使用私有docker registry

    本文收录在容器技术学习系列文章总目录 1.了解Docker Registry 1.1 介绍 registry 用于保存docker 镜像,包括镜像的层次结构和元数据. 启动容器时,docker dae ...

  2. 搭建私服-docker registry

    Docke官方提供了Docker Hub网站来作为一个公开的集中仓库.然而,本地访问Docker Hub速度往往很慢,并且很多时候我们需要一个本地的私有仓库只供网内使用.Docker仓库实际上提供两方 ...

  3. 搭建企业级Docker Registry -- Harbor

    Harbor 是一个企业级的 Docker Registry,可以实现 images 的私有存储和日志统计权限控制等功能,并支持创建多项目(Harbor 提出的概念),基于官方 Registry V2 ...

  4. 温故知新,基于Nexus3和Docker搭建私有Docker Mirrors镜像库

    前言 接着上一篇文章关于基于Nexus3和Docker搭建私有Nuget服务的探索,我们可以进一步利用Nexus3来创建一个私有的Docker镜像库满足内部需求. 仓库类型 hosted: 本地存储, ...

  5. 部署私有Docker Registry

    安装部署一个私有的Docker Registry是引入.学习和使用Docker这门技术的必经之路之一.尤其是当Docker被所在组织接受,更多人.项目和产品开始接触和使用Docker时,存储和分发自制 ...

  6. docker 搭建私有 docker hub

    查找registry 镜像 meiya@meiya:/etc/docker$ clear meiya@meiya:/etc/docker$ docker search registry NAME DE ...

  7. 搭建私有docker仓库

    安装docker yum install docker 启动docker systemctl start docker 拉取registry镜像 docker pull registry 创建仓库配置 ...

  8. 搭建私有Docker镜像仓库

    安装Docker yum install docker -y 配置阿里镜像加速网址 sudo tee /etc/docker/daemon.json << EOF { "regi ...

  9. docker+Nexus Repository Manager 搭建私有docker仓库

    使用容器安装Nexus3 1.下载nexus3的镜像: docker pull sonatype/nexus3 2.使用镜像启动一个容器: docker run -d -p 8081:8081 -p ...

随机推荐

  1. python基础操作_文件读写操作

    #文件读写# r只能读不能写,且文件必须存在,w只能写不能读,a只能写不能读# w+是写读模式,清空原文件内容# r+是读写模式,没有清空原文件内容,# 只要有r,文件必须存在,只要有w,都会清空原文 ...

  2. 关于cas server无法通过session持久化方式实现集群的问题

    最近在搭建cas单点登录系统 ,在建立集群时发生一个问题. 搭建的环境是tomcat+tomcat-redis-session-manager+redis+cas 在对tomcat的session进行 ...

  3. [转] 传说中的WCF(2):服务协定的那些事儿

    上一篇文章中,我们抛出了N个问题:WCF到底难不难学?复杂吗?如果复杂,可以化繁为简吗? 其实,这些问题的答案全取决于你的心态,都说“态度决定一切”,这句话,不知道各位信不信,反正我是信了.首先,敢于 ...

  4. [转] (CQRS)命令和查询责任分离架构模式(一) 之 什么是CQRS

    什么是CQRS? 这个问题网上可以找到很多资料,未接触过的童鞋请先查看Udi Dahan, Grey Young, Rinat Abdullin,园子里dax.net,以及Jdon社区上的相关文章. ...

  5. 中学之Vim实践课程

    今天转发娄老师的一篇VIM编辑器的文章,很赞哦!(值得收藏)文后的参考资料记得看一看,也很棒!                               原文地址:http://www.cnblog ...

  6. CoolBlog开发笔记第4课:数据库模型设计

    教程目录 1.1 CoolBlog开发笔记第1课:项目分析 1.2 CoolBlog开发笔记第2课:搭建开发环境 1.3 CoolBlog开发笔记第3课:创建Django应用 前言 我新书<Py ...

  7. java 读取excel

    1. 需要下载jxl.jar包 自己研究了一下,代码如下 package file;import java.io.File;import java.io.IOException;import java ...

  8. ES6中的export以及import的使用多样性

    模块功能主要由两个命令构成:export和import.export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能. 一.export导出模块使用部分的几种方式 一个模块就是一 ...

  9. PHP中几个输出函数echo,print(),print_r(),sprintf(),var_dump()的区别

    1:echo:是语句不是函数,没有返回值,可输出多个变量值,不需要圆括号.不能输出数组和对象,只能打印简单类型(如int,string). 2:print:是语句不是函数,有返回值 1 ,只能输出一个 ...

  10. Docker 的两类存储资源 - 每天5分钟玩转 Docker 容器技术(38)

    我们从本章开始讨论 Docker 存储. Docker 为容器提供了两种存放数据的资源: 由 storage driver 管理的镜像层和容器层. Data Volume. 我们会详细讨论它们的原理和 ...