前言
在前面的一篇博客在 ubuntu 搭建 docker registry 私有仓库介绍了一种简单的搭建 docker 私有仓库了的方法但是当时使用的是修改 --insecure-registry 参数的办法, 这种办法在局域网中使用, 还勉强合适但如果要搭建一个生产环境的私有仓库服务器, 就存在很大的安全风险了所以, 这里介绍一种使用签名认证的实现方式, 主要通过 nginx 的反向代理, 将不受信任的客户端请求都拒绝, 以达到安全的目的
实验环境
服务端系统: ubuntu 16.04
docker 17.12.0-ce
客户端系统: ubuntu 14.04
docker 17.12.0-ce
如果想升级自己系统中的 docker 版本, 请参考这篇文章: Ubuntu Docker 版本的更新与安装
或者参考: Docker ubuntu 16.04 安装稳定版本, 社区版版本
开始实验
因为我们使用的是 nginx 服务作为安全认证的服务器, 所以我们还需要安装 apache2-utils , 这个是用来生成用户和用户密码我们这里使用 docker-compse, 用来定义和运行多个 docker 容器我们还需要使用 curl 工具, 这个主要用于测试实验结果
开始做实验前, 请确认已经安装好 docker-ce 的版本了
下面开始做实验
1 安装必要的工具
apt-get install -y docker-compose apache2-utils curl
2 创建一些文件目录
- mkdir /docker-registry
- mkdir /docker-registry/data
- mkdir /docker-registry/nginx
- chown root:root /docker-registry
- cd /docker-registry
3 创建 docker-compose.yml 文件 (用于定义 docker container properties)
- root@ubuntu:/docker-registry# cat docker-compose.yml
- nginx:
- image: "nginx:1.9"
- ports:
- - 443:443
- links:
- - registry:registry
- volumes:
- - /docker-registry/nginx/:/etc/nginx/conf.d
- registry:
- image: registry:2
- ports:
- - 127.0.0.1:5000:5000
- environment:
- REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
- volumes:
- - /docker-registry/data:/data
说明:
docker-compose.yml 文件首先会创建一个 registry 容器, 它的 5000 端口和宿主机的 5000 端口映射它存储镜像的目录是 /data 目录, 与宿主机的 /docker-registry/data 绑定
然后, nginx 容器也会被创建, nginx 容器通过 -link 参数, 与 registry 容器连接, 这样 nginx 容器就知道怎么和 registry 容器通信了 (其实, registry 容器的 IP 会被绑定在 nginx 容器的 /etc/hosts 文件)
4 启动容器
docker-compose up
说明: 这条命令 docker-compose 会通过刚刚写好的 docker-compose.yml 脚本, 生成两个容器, 正常会是以下的输出
如果要停止, 只能使用 (Ctrl + C ) 了
如果想在后台运行, 可以使用
docker-compose up -d
创建 docker-registry.service 文件
因为 ubuntu 在 14.01 之前的版本都只支持 upstart 的方式, 所以, 如果你想使用 systemd 的管理方式, 则需要使用 ubuntu 15.01 以上的版本了因此, 我这里使用了 ubuntu 16.04 的系统版本, 自带了 systemd 服务
- vi /etc/systemd/system/docker-registry.service :
- [Unit]
- Description=Starting docker registry
- [Service]
- Environment= MY_ENVIRONMENT_VAR = /docker-registry/docker-compose.yml
- WorkingDirectory=/docker-registry
- ExecStart=/usr/bin/docker-compose up
- Restart=always
- [Install]
- WantedBy=multi-user.target
说明: 现在, 我们就能使用 service docker-registry start/stop/restart 的命令来管理 nginx 和 registry 容器了, 非常方便
测试:
说明一切正常
好吧, 从这里开始, 我们就可以使用 service docker-registry restart 来重启容器了
5 设置 nginx 服务的配置文件
- vi /docker-registry/nginx/registry.conf
- upstream docker-registry {
- server registry:5000;
- }
- server {
- listen 443;
- server_name myregistrydomain.com;
- # SSL
- # ssl on;
- # ssl_certificate /etc/nginx/conf.d/domain.crt;
- # ssl_certificate_key /etc/nginx/conf.d/domain.key;
- # 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;
- location /v2/ {
- # Do not allow connections from docker 1.5 and earlier
- # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
- if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
- return 404;
- }
- # To add basic authentication to v2 use auth_basic setting plus add_header
- # auth_basic "registry.localhost";
- # auth_basic_user_file /etc/nginx/conf.d/registry.password;
- # add_header Docker-Distribution-Api-Version registry/2.0 always;
- proxy_pass http://docker-registry;
- proxy_set_header Host $http_host; # required for docker clients sake
- proxy_set_header X-Real-IP $remote_addr; # pass on real clients IP
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
- proxy_read_timeout 900;
- }
- }
测试
- service docker-registry restart
- curl http://localhost:5000/v2/
结果会是这样:
{}root@ubuntu:/docker-registry#
6 设置安全权限认证, 创建用户
- cd /docker-registry/nginx
- htpasswd -c registry.password mydocker
- New password:
- Re-type new password:
- Adding password for user mydocker
说明: 利用 apache2-utils 的 htpasswd 工具, 创建一个包含用户名和用户密码的文件
再次打开 registry.conf 文件
vi /docker-registry/nginx/registry.conf
将下面几行的注释去掉
- auth_basic "registry.localhost";
- auth_basic_user_file /etc/nginx/conf.d/registry.password;
- add_header Docker-Distribution-Api-Version registry/2.0 always;
再测试
- service docker-registry restart
- curl http://localhost:443/v2/
- root@ubuntu:~/docker-registry/nginx# curl http://localhost:5043/v2/401 Authorization Required
- 401 Authorization Required
- nginx/1.9.15
用用户名和用户密码再测试一次
- curl http://mydocker:123456@localhost:443/v2/
- {}root@ubuntu:~/docker-registry/nginx#
说明: 到这里, 其实我们就完成了一个局域网的认证功能了, 但是还不能作为一个服务器使用因为, 还需要设置 ssl 安全认证
7 设置 SSL 安全认证
7.1 再次打开 registry.conf 文件
vi /docker-registry/nginx/registry.conf
将下面的几行取消注释并且修 域名:
- upstream docker-registry {
- server registry:5000;
- }
- server {
- listen 443;
- server_name docker-server.com;
- # SSL
- ssl on;
- ssl_certificate /etc/nginx/conf.d/domain.crt;
- ssl_certificate_key /etc/nginx/conf.d/domain.key;
7.2 创建 Certification Authority
cd /docker-registry/nginx
创建新的 root key:
openssl genrsa -out dockerCA.key 2048
创建 root certificate
在 Common Name 里填入 docker-server.com 就可以了, 其他内容随便填
openssl req -x509 -new -nodes -key dockerCA.key -days 10000 -out dockerCA.crt
创建 server key (这个是被 nginx ssl_certificate_key 引用的)
openssl genrsa -out domain.key 2048
再创建一个新的 certificate
Common Name 继续填 docker-server.com, 不用设置密码
openssl req -new -key domain.key -out docker-registry.com.csr
最后, 进行签名:
openssl x509 -req -in docker-registry.com.csr -CA dockerCA.crt -CAkey dockerCA.key -CAcreateserial -out domain.crt -days 10000
复制 dockerCA.crt
- cd /docker-registry/nginx
- cp dockerCA.crt /usr/local/share/ca-certificates/
为了让服务器信任我们的 Certification Authority 认证, 我们需要
update-ca-certificates && service docker restart && service docker-registry restart
测试
- curl https://mydocker:123456@docker-server.com/v2/
- #output should be
- {}root@ubuntu:/docker-registry/nginx#
8 将 dockerCA.crt 复制到客户端
- scp dockerCA.crt root@192.168.188.112:/usr/local/share/ca-certificates
- root@192.168.0.59s password:
- dockerCA.crt 100% 1302 1.3KB/s 00:00
如果客户端没有 /usr/local/share/ca-certificates 目录, 则需要创建
9 客户端登录服务器仓库
- update-ca-certificates && service docker restart
- #test login to fresh created repository:
- docker login https://docker-server.com
- Username: mydocker
- Password:
- Login Succeeded
需要在 /etc/hosts 文件中添加
192.168.188.113 docker-server.com #(这是我做实验的服务端的 IP 地址)
9.1 在客户端推送镜像
- docker pull ubuntu # 尝试在 docker hub 下载镜像
- docker tag ubuntu docker-server.com/test-ubuntu # 将镜像打标签, 作为区别
- docker push docker-server.com/test-ubuntu # 推送到 私有 docker registry 仓库
确认测试
在客户端将 docker-server.com/test-ubunt 镜像删除:
docker image rm -f ubuntu
从 docker-server.com 仓库下载 test-ubnutn 镜像:
docker pull docker-server.com/test-ubuntu
过程截图:
ok, 成功了
如果在实验的过程中遇到什么问题, 请查找 docker 的日志文件
- journalctl -u docker # for docker logs in the systemd journal
- journalctl | grep docker # for system logs that mention docker
总结
主要利用里 nginx 的反向代理服务器的功能, 实现了安全认证管理, 加强了访问私有仓库的安全权限管理
参考文章:
Private Docker Registry in Ubuntu Server 16.04
来源: http://www.bubuko.com/infodetail-2504703.html