介绍
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
更新系统
>>> apt-get update && apt-get upgrade -y
>>> reboot
安装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服务
下载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
启动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: 给容器命名一个名称
查看docker registry进程
>>> docker ps
CONTAINER ID IMAGE COMMANDCREATEDSTATUSPORTS NAMES
e60079ce80f9 registry:2 "/bin/registry serve " 57 seconds ago Up 56 seconds 0.0.0.0:5000->5000/tcp registry
验证可用性
打tag
>>> docker tag hello-world 127.0.0.1:5000/hello-world #给hello-world镜像打tag
查看本地镜像
>>> docker images
REPOSITORY TAGIMAGE 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
REPOSITORYTAG 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认证
安装nginx
>>> apt-get install nginx
创建登录用户
安装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
制作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 # 不这样做,会有某些浏览器不支持
配置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_filedocker-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
访问测试
测试直接访问
>>> 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