天天看点

搭建docker内网私服(docker-registry with nginx&ssl on centos)

关于如何创建和使用本地仓库,其实已经有很多文章介绍了。因为docker技术正处于发展和完善阶段,所以有些文章要么内容已经过时,要么给出了错误的配置,导致无法正常创建仓库。本文记录的是个人完整的搭建过程,<code>docker version</code>为1.1.2。

docker-registry既然也是软件应用,自然最简单的方法就是使用官方提供的已经部署好的镜像registry。官方文档中也给出了建议,直接运行<code>sudo docker run -p 5000:5000 registry</code>命令。这样确实能启动一个registry服务器,但是所有上传的镜像其实都是由docker容器管理,放在了/var/lib/docker/....某个目录下。而且一旦删除容器,镜像也会被删除。因此,我们需要想办法告诉docker容器镜像应该存放在哪里。registry镜像中启动后镜像默认位置是<code>/tmp/registry</code>,因此直接映射这个位置即可,比如到本机的<code>/opt/data/registry</code>目录下。

方法有多种,直接运行下面的命令:

如果本地没有拉取过docker-registry,则首次运行会pull registry,运行时会映射路径和端口,以后就可以从<code>/opt/data/registry</code>下找到私有仓库都存在哪些镜像,通过主机的哪个端口可以访问。

要从私服上获取镜像或向私服提交镜像,现在变得非常简单,只需要在仓库前面加上私服的地址和端口,形如<code>172.29.88.222:5000/centos6</code>。注意,这里可以选择不使用ip,而是用hostname,如registry.domain.com:5000,但不能仅用不带<code>.</code>的主机名registry,docker会认为registry是用户名,建议使用带域名的hostname加port来表示。

于是在另外一台要使用docker的主机上就可以通过这台私服拉取和推送镜像了:

第一次push到私服上时会提示用户名、密码和邮箱,创建即可。也可以在docker私服端加入认证机制。

(请在实际操作以前,先阅读完本节,再确定是否在前端加入nginx)

从上面的过程可以看到,除非防火墙限制,否则任何主机可以创建账号并想私服推送镜像,更安全的做法是在外层加入登录认证机制。

为了让nginx使用这个密码文件,并且转发8080端口的请求到docker registry,新增nginx配置文件

<code>vi /etc/nginx/sites-enabled/docker-registry</code>:

此时主机的5000端口应该通过防火墙禁止访问(或者在<code>docker run</code>端口映射时只监听回环接口的ip <code>-p 127.0.0.1:5000:5000</code>)。

如果直接访问访问将得到未授权的信息:

带用户认证的docker-registry:

不出意外的话,上面的<code>docker pull</code>会失败:

本文后的第1篇参考文档没有出现这个问题,但评论中有提及。

目前的办法三个:

撤退,这就是为什么先说明在操作前线查看到这的原因了

换成<code>v0.9.1</code>及以下版本。现在都<code>v1.3.1</code>了,我猜你不会这么做

安装ssl证书,使用https传输。这是明智的选择,新版本docker也推荐我们这么做,往下看。

首先打开nginx配置文件中ssl的三行注释

保存之后,nginx会分别从<code>/etc/nginx/ssl/nginx.crt</code>和<code>/etc/nginx/ssl/nginx.key</code>读取ssl证书和私钥。如果你自己愿意花钱买一个ssl证书,那就会变得非常简单,把证书和私钥拷贝成上面一样即可。关于ssl以及签署ssl证书,请参考其他文章。

这里我们自签署一个ssl证书,把当前系统作为(私有)证书颁发中心(ca)。

创建存放证书的目录

确认ca的一些配置文件

(1) 生成根密钥

为了安全起见,修改cakey.pem私钥文件权限为600或400,也可以使用子shell生成<code>( umask 077; openssl genrsa -out private/cakey.pem 2048 )</code>,下面不再重复。

(2) 生成根证书

会提示输入一些内容,因为是私有的,所以可以随便输入,最好记住能与后面保持一致。上面的自签证书<code>cacert.pem</code>应该生成在<code>/etc/pki/ca</code>下。

(3) 为我们的nginx web服务器生成ssl密钥

我们的ca中心与要申请证书的服务器是同一个,否则应该是在另一台需要用到证书的服务器上生成。

(4) 为nginx生成证书签署请求

同样会提示输入一些内容,其它随便,除了<code>commone name</code>一定要是你要授予证书的服务器域名或主机名,challenge password不填。

(5) 私有ca根据请求来签发证书

上面签发过程其实默认使用了<code>-cert cacert.pem -keyfile cakey.pem</code>,这两个文件就是前两步生成的位于<code>/etc/pki/ca</code>下的根密钥和根证书。

到此我们已经拥有了建立ssl安全连接所需要的所有文件,并且服务器的crt和key都位于配置的目录下,唯有根证书<code>cacert.pem</code>位置不确定放在centos6下的哪个地方。

<code>/etc/pki/ca-trust/source/anchors</code>、<code>/etc/pki/ca-trust/source</code>、<code>/etc/pki/ca-trust/extracted</code>、

<code>/etc/pki/ca-trust/extracted/pem/</code>、<code>/etc/pki/tls/certs/cacert.crt</code>

都会报错:

(6) 目前让根证书起作用的只发现一个办法:

将<code>cacert.pem</code>根证书追加到<code>ca-bundle.crt</code>后一定要重启docker后台进程才行。

这个地方挣扎了很久,重点关注一下这个下面几个issue:

<a href="https://github.com/docker/docker-registry/issues/82" target="_blank">https://github.com/docker/docker-registry/issues/82</a>

<a href="https://github.com/docker/docker/pull/2687" target="_blank">https://github.com/docker/docker/pull/2687</a>

<a href="https://github.com/docker/docker/pull/2339" target="_blank">https://github.com/docker/docker/pull/2339</a>

(7) 最终搞定:

但还有一个小问题没解决,虽然已经可以正常使用,但每次请求在nginx的error.log中还是会有<code>[error] 8299#0: *27 no user/password was provided for basic authentication</code>,应该是这个版本docker暂未解决的bug。

(1) docker后台进程意外中断后,重新<code>docker start &lt;container_id&gt;</code>报错

能想到的另外一个办法是,启动docker后台进程时,重定向输出<code>docker -d &gt; /dev/null 2&gt;&amp;1</code>(/var/log/docker已自动记录了一份日志)。

(2) 配置完nginx的docker-registry.conf后启动报错

原因是nginx版本太低,一些配置指令不兼容,使用<code>yum install nginx</code>默认安装了1.0.x,卸载重新下载<code>nginx-1.4.7-1.el6.ngx.x86_64.rpm</code>安装解决。

(3) 网络设置代理问题

<code>pull, push</code>官网的镜像时由于gfw的原因需要设置代理,但不是<code>http_proxy</code>而是<code>http_proxy</code>,对于docker来说同时设置这两个值就会出问题,有时出于安装软件包的需要设置<code>http_proxy</code>,就会导致冲突。在docker-registry中如果忘记了当前哪一个在起作用,找遍所有问题都发现不了原因,而docker返回给我们的错误也难以判断。切记~

to-do

如何删除docker-registry的里的镜像

继续阅读