author: zqh
date: 2016-5-11

介绍

Docker仓库实际上提供两方面的功能,一个是镜像管理,一个是认证。前者主要由docker-registry项目来实现,通过http服务来上传下载;后者可以通过docker-index(闭源)项目或者利用现成认证方案(如nginx)实现http请求管理。

环境

  • 实体机

    机房openstack服务器

  • 宿主机

以ubuntu vivid 15.04镜像创建的虚拟机
  • 网络
能连接到公网
  • dns
10.68.7.142上的dnsmasq
  • 权限
有root权限或者可以执行sudo

基本结构

前端使用nginx的https协议进行basic authentication;
nginx使用http协议代理docker registry的5000端口。

安装docker

  1. 更新系统
>>> apt-get update && apt-get upgrade -y
>>> reboot
  1. 安装docker
  • 检查curl包
>>> which curl
  • 安装curl包(已安装跳过此步骤)
>>> apt-get install curl
  • 安装docker
>>> curl -sSL https://get.docker.com/ | sh

Note

https://get.docker.com/内容为一个安装脚本,如果失败多试几次。

  • 测试 docker
>>> docker version #查看版本
Client:
Version:      1.9.1
API version:  1.21
Go version:   go1.4.2
Git commit:   a34a1d5
Built:        Fri Nov 20 13:16:54 UTC 2015
OS/Arch:      linux/amd64
Server:
Version:      1.9.1
API version:  1.21
Go version:   go1.4.2
Git commit:   a34a1d5
Built:        Fri Nov 20 13:16:54 UTC 2015
OS/Arch:      linux/amd64
>>> docker pull hello-world #下载镜像测试
Using default tag: latest
latest: Pulling from library/hello-world
79112a2b2613: Pull complete
4c4abd6d4278: Pull complete
Digest: sha256:4f32210e234b4ad5cac92efacc0a3d602b02476c754f13d517e1ada048e5a8ba
Status: Downloaded newer image for hello-world:latest

启动docker registry服务

  1. 下载registry镜像
>>> docker pull registry:2
2: Pulling from library/registry
3059b4820522: Pull complete
ff978d850939: Pull complete
5a85aa5e7c2b: Pull complete
8c597b986e48: Pull complete
ebf4ce6dfdd0: Pull complete
c45dd354ad24: Pull complete
bfc3f550ff55: Pull complete
279b06747fae: Pull complete
06552075e36c: Pull complete
Digest: sha256:f8cd74689f55009ad08359688c61054099cc28c90ecc7eaceb83ada0bb69ca75
Status: Downloaded newer image for registry:2
  1. 启动docker registry
>>> docker run -idt -v /opt/registry:/var/lib/registry -p 5000:5000 --restart=always --name registry egistry:2
e60079ce80f9170c46cc1df722e2ef47eeb0395da7123d693c54a82ecd5b1253
i: 保持sdtin开放状态
d: 使容器以守护进程方式后台运行,并打印容器id
t: 分配一个tty(虚拟终端设备)
v: 绑定挂载一个容器内的路径到宿主机路径
p: 映射一个容器的端口到宿主机端口
restart: 当容器退出时的重启策略
name: 给容器命名一个名称
  1. 查看docker registry进程
>>> docker ps
CONTAINER ID IMAGE      COMMAND                CREATED        STATUS        PORTS                  NAMES
e60079ce80f9 registry:2 "/bin/registry serve " 57 seconds ago Up 56 seconds 0.0.0.0:5000->5000/tcp registry
  1. 验证可用性
  • 打tag
>>> docker tag hello-world 127.0.0.1:5000/hello-world #给hello-world镜像打tag
  • 查看本地镜像
>>> docker images
REPOSITORY                   TAG        IMAGE ID         CREATED         VIRTUAL SIZE
registry                     2          06552075e36c     6 days ago      171.2 MB
hello-world                  latest     4c4abd6d4278     2 weeks ago     967 B
127.0.0.1:5000/hello-world   latest     4c4abd6d4278     2 weeks ago     967 B
  • push镜像到私有仓库
>>> docker push 127.0.0.1:5000/hello-world
The push refers to a repository [127.0.0.1:5000/hello-world] (len: 1)
4c4abd6d4278: Pushed
79112a2b2613: Pushed
latest: digest: sha256:986c84e32ef73f64fb974588427dec5ff6ed699a8ac59c2414a2300c0d12528a size: 2740
  • 查看宿主机映射目录
>>> ll /opt/registry/docker/registry/v2/repositories/
total 12
drwxr-xr-x 3 root root 4096 May 12 01:09 ./
drwxr-xr-x 4 root root 4096 May 12 01:09 ../
drwxr-xr-x 5 root root 4096 May 12 01:09 hello-world/
  • 查看docker registry中的镜像
>>> curl http://127.0.0.1:5000/v2/_catalog
{"repositories":["hello-world"]}
  • 在docker registry中下载镜像
>>> docker rmi hello-world
Untagged: hello-world:latest
>>> docker rmi 127.0.0.1:5000/hello-world
Untagged: 127.0.0.1:5000/hello-world:latest
Deleted: 4c4abd6d4278af717a47c150383e04fae287f9843466e9e30133fb43a3cff7f7
Deleted: 79112a2b26135c67d7be9e976d2a0a42ebcc9467a99c8583ec8918400a39516b
>>> docker images
REPOSITORY    TAG     IMAGE ID          CREATED          VIRTUAL SIZE
registry      2       06552075e36c      6 days ago       171.2 MB
>>> docker pull 127.0.0.1:5000/hello-world
Using default tag: latest
latest: Pulling from hello-world
79112a2b2613: Pull complete
4c4abd6d4278: Pull complete
Digest: sha256:986c84e32ef73f64fb974588427dec5ff6ed699a8ac59c2414a2300c0d12528a
Status: Downloaded newer image for 127.0.0.1:5000/hello-world:latest
>>> docker images
REPOSITORY                   TAG         IMAGE ID         CREATED          VIRTUAL SIZE
registry                     2           06552075e36c     6 days ago       171.2 MB
127.0.0.1:5000/hello-world   latest      4c4abd6d4278     2 weeks ago      967

添加nginx认证

  1. 安装nginx
>>> apt-get install nginx
  1. 创建登录用户
  • 安装apache2-utils
>>> apt-get install apache2-utils
  • 创建用户
>>> htpasswd -c /etc/nginx/docker-registry.htpasswd zhuqh
New password:
Re-type new password:
Adding password for user zhuqh
>>> htpasswd /etc/nginx/docker-registry.htpasswd liusc #再创建一个,注意去掉-c参数
New password:
Re-type new password:
Adding password for user liusc
  1. 制作https自签名证书

Tip

https的ssl证书不允许使用ip地址,我们通过142的dns服务器设置宿主机域名为:ubuntu.vsct.io

  • 制作CA证书
>>> openssl genrsa -des3 -out ca.key 2048 # 生成私钥,后面这个2048是密钥长度
Generating RSA private key, 2048 bit long modulus
...............................................+++
...+++
e is 65537 (0x10001)
Enter pass phrase for ca.key:
Verifying - Enter pass phrase for ca.key:
>>> openssl req -new -x509 -days 7305 -key ca.key -out ca.crt # 生成公钥
Enter pass phrase for ca.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:
  • 生成服务端证书并用CA签名认证
>>> openssl genrsa -des3 -out ubuntu.vsct.io.key 2048 #生成ubuntu.vsct.io.key证书私钥
Generating RSA private key, 2048 bit long modulus
..........................................................................+++
....+++
e is 65537 (0x10001)
Enter pass phrase for ubuntu.vsct.io.key:
Verifying - Enter pass phrase for ubuntu.vsct.io.key:
>>> openssl req -new -key ubuntu.vsct.io.key -out ubuntu.vsct.io.csr # 生成签名请求,common name填写域名
Enter pass phrase for ubuntu.vsct.io.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:*.vsct.io
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
>>> openssl ca -policy policy_anything -days 1460 -cert ca.crt -keyfile ca.key -in ubuntu.vsct.io.csr -out  ubuntu.vsct.io.crt # 使用CA进行签名
Using configuration from /usr/lib/s sl/openssl.cnf
Enter pass phrase for ca.key:
Check that the request matches the signature
Signature ok
Certificate Details:
       Serial Number: 1 (0x1)
       Validity
           Not Before: May 12 03:07:03 2016 GMT
           Not After : May 11 03:07:03 2020 GMT
       Subject:
           countryName               = AU
           stateOrProvinceName       = Some-State
           organizationName          = Internet Widgits Pty Ltd
           commonName                = *.vsct.io
       X509v3 extensions:
           X509v3 Basic Constraints:
               CA:FALSE
           Netscape Comment:
               OpenSSL Generated Certificate
           X509v3 Subject Key Identifier:
               46:84:2B:25:52:71:02:58:5D:12:3F:30:E1:CC:BC:AC:0D:BE:24:64
           X509v3 Authority Key Identifier:
               keyid:67:5B:A7:2B:A9:4E:6C:06:1F:5A:06:5E:C7:80:DF:6C:43:00:99:68
Certificate is to be certified until May 11 03:07:03 2020 GMT (1460 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
签名时出现“I am unable to access the ./demoCA/newcerts directory”的解决方法:
1.mkdir ./demoCA
2.mkdir demoCA/newcerts
3.touch demoCA/index.txt
4.touch demoCA/serial
5.echo "01" > demoCA/serial
6.重新执行签名
>>> cat ca.crt >> ubuntu.vsct.io.crt # 不这样做,会有某些浏览器不支持
  1. 配置nginx
  • 修改配置文件
>>> vim /etc/nginx/nginx.conf
upstream docker {
       server localhost:5000;
   }

server {
       listen       80 default_server;
       listen       [::]:80 default_server;
       listen  443 ssl;
       listen  [::]:443 ssl;
       server_name  _;
       root         /usr/share/nginx/html;

       ssl on;
       ssl_certificate /opt/ubuntu.vsct.io.crt;
       ssl_certificate_key /opt/ubuntu.vsct.io.key;
       ssl_protocols TLSv1.1 TLSv1.2;

       add_header "Docker-Distribution-Api-Version" "registry/2.0";
       # Load configuration files for the default server block.
       include /etc/nginx/default.d/*.conf;

       location / {
           #add_header 'Docker-Distribution-Api-Version' $docker_distribution_api_version always;
           auth_basic              "Restricted";
           auth_basic_user_file    docker-registry.htpasswd;
           proxy_pass http://docker;

           client_max_body_size 0;
           chunked_transfer_encoding on;
           proxy_set_header "Docker-Distribution-Api-Version" "registry/2.0";
       }
       location /_ping {
           auth_basic off;
           proxy_pass http://docker/v2;

       }
       location /v1/_ping {
           auth_basic off;
           proxy_pass http://docker/v2;

       }
       }
  • 测试配置
>>> nginx -t
Enter PEM pass phrase:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
  • 重新加载
>>> nginx -s reload
查看nginx状态显示:
Enter PEM pass phrase:
May 12 03:53:41 ubuntu nginx[30431]: nginx: [emerg] SSL_CTX_use_PrivateKey_file("/opt/ubuntu.vsct.io.key") failed (SSL: er...EM lib)
解决方案:
openssl rsa -in ubuntu.vsct.io.key -out ubuntu.vsct.io.key.unsecure
然后在nginx配置里把ssl_certificate_key指向ubuntu.vsct.io.key.unsecure
  1. 访问测试
  • 测试直接访问
>>> curl -k https://ubuntu.vsct.io/v2/_catalog
<html>
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.6.2 (Ubuntu)</center>
</body>
</html>
  • 客户端安装证书
把生成的客户端证书放到 /etc/docker/certs.d/ubuntu.vsct.io/ca.crt下
  • 登录后下载镜像
>>> docker login ubuntu.vsct.io
Username: zhuqh
Password:
Email: zhuqinghua@victorysoft.com.cn
Login Succeeded
>>> docker pull ubuntu.vsct.io/hello-world
Using default tag: latest
Trying to pull repository ubuntu.vsct.io/hello-world ... latest: Pulling from hello-world
79112a2b2613: Pull complete
4c4abd6d4278: Pull complete
Digest: sha256:986c84e32ef73f64fb974588427dec5ff6ed699a8ac59c2414a2300c0d12528a
Status: Downloaded newer image for ubuntu.vsct.io/hello-world:latest

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐