Docker仓库
Docker镜像仓库简单来说就是用来存储自己制作的docker镜像,这docker镜像仓库我称为docker-registry,Docker官方给我们提供了公共仓库(Docker Hub)和私有仓库(Docker registry),想要使用Docker Hub我们只需要在Docker Hub上注册自己的docker仓库即可,而Docker registry则需要我们自己来搭建仓库。
Docker仓库的组件:
- registry:保存docker镜像及镜像层次结构和元数据
- repository:由具有某个功能的镜像的所有相关版本构成的集合
- index:管理用户的账号、访问权限、镜像及镜像标签等等相关的
- graph:从registry中下载的docker镜像需要保存在本地,此功能即由graph完成
Docker-registry分为1和2版本,1版本是有Python语言写的,而现在的registry2版本即docker distribution更加安全和快速,并且使用go语言编写,docker1.6后的版本不再支持registry1。
Docker Hub
我们想要使用docker hub就需要我们在docker hub上建立自己的repository,下面演示下这么上传自己制作的docker镜像:
首先登陆docker hub
1
~]# docker login
2
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
3
Username: jusene
4
Password:
5
Login Succeeded
接下来我们去网页docker hub上创建自己的repository
我们重新打标签给需要上传给docker hub的镜像
1
~]# docker tag httpd:v0 docker.io/jusene/test
2
~]# docker images
3
REPOSITORY TAG IMAGE ID CREATED SIZE
4
docker.io/jusene/test latest 09e7250f1e0e 15 hours ago 225.2 MB
5
httpd v0 09e7250f1e0e 15 hours ago 225.2 MB
docker push到docker hub
1
~]# docker push docker.io/jusene/test
2
The push refers to a repository [docker.io/jusene/test]
3
5af69ca6ca17: Pushed
4
latest: digest: sha256:e4b1a4315eab841e7930f96a07bd843be48534c930515c3fed62ba3fd2693257 size: 528
登陆网页docker hub查看下docker repository的信息
Docker registory
基于容器安装运行
基于容器运行十分简单,只需要一条命令:
1 | ~]# docker run -d -p 5000:5000 --restart=always -v /data/registry/conf/config.yml:/etc/docker/registry/config.yml -v /data/registry/data:/var/lib/registry --name registry registry |
本地安装运行
1 | ~]# yum install -y docker-distribution |
2 | ~]# vim /etc/docker-distribution/registry/config.yml |
3 | version: 0.1 |
4 | log: |
5 | fields: |
6 | service: registry |
7 | storage: |
8 | cache: |
9 | layerinfo: inmemory |
10 | filesystem: |
11 | rootdirectory: /var/lib/registry |
12 | http: |
13 | addr: :5000 |
这是默认配置,相信配置文件是没什么难度。
1 | ~]# docker tag httpd:v1 10.211.55.43:5000/httpd |
2 | The push refers to a repository [10.211.55.43:5000/httpd] |
3 | Get https://10.211.55.43:5000/v1/_ping: http: server gave HTTP response to HTTPS client |
4 | 这个原因是docker客户端使用了https协议来上传docker 镜像,而docker registry采用了http的协议来解释客户端协议。 |
解决方案:
1 | 客户端 |
2 | ~]# vim /etc/sysconfig/docker |
3 | ... |
4 | INSECURE_REGISTRY='--insecure-registry 10.211.55.43:5000' |
5 | ... |
6 | ~]# systemctl restart docker |
7 | ~]# docker push 10.211.55.43:5000/httpd |
8 | The push refers to a repository [10.211.55.43:5000/httpd] |
9 | 5af69ca6ca17: Pushed |
10 | latest: digest: sha256:e4b1a4315eab841e7930f96a07bd843be48534c930515c3fed62ba3fd2693257 size: 528 |
查看下:
1 | ~]# curl 10.211.55.43:5000/v2/_catalog |
2 | {"repositories":["httpd"]} |
3 | ~]# curl 10.211.55.43:5000/v2/httpd/tags/list |
4 | {"name":"httpd","tags":["latest"]} |
5 | |
6 | ~]# docker pull 10.211.55.43:5000/httpd |
7 | Using default tag: latest |
8 | Trying to pull repository 10.211.55.43:5000/httpd ... |
9 | latest: Pulling from 10.211.55.43:5000/httpd |
10 | Digest: sha256:e4b1a4315eab841e7930f96a07bd843be48534c930515c3fed62ba3fd2693257 |
这样的仓库基本可以使用了。
如果我门不希望使用http来制作仓库,那么就需要自己制作证书来使用https:
生成私有ca:
1 | [root@node2 ~]# (umask 077;openssl genrsa -out /etc/pki/CA/private/cakey.pem 4096) |
2 | Generating RSA private key, 4096 bit long modulus |
3 | .........................................................................................................++ |
4 | ........................................................................................++ |
5 | e is 65537 (0x10001) |
6 | [root@node2 ~]# openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cacert.pem -days 3655 |
7 | You are about to be asked to enter information that will be incorporated |
8 | into your certificate request. |
9 | What you are about to enter is what is called a Distinguished Name or a DN. |
10 | There are quite a few fields but you can leave some blank |
11 | For some fields there will be a default value, |
12 | If you enter '.', the field will be left blank. |
13 | ----- |
14 | Country Name (2 letter code) [XX]:CN |
15 | State or Province Name (full name) []:ZJ |
16 | Locality Name (eg, city) [Default City]:HZ |
17 | Organization Name (eg, company) [Default Company Ltd]:JU |
18 | Organizational Unit Name (eg, section) []:TE |
19 | Common Name (eg, your name or your server's hostname) []:ca.jusene.com |
20 | Email Address []:ca@1234.com |
21 | [root@node2 ~]# mkdir /etc/pki/CA/{certs,crl,newcerts} |
22 | mkdir: cannot create directory ‘/etc/pki/CA/certs’: File exists |
23 | mkdir: cannot create directory ‘/etc/pki/CA/crl’: File exists |
24 | mkdir: cannot create directory ‘/etc/pki/CA/newcerts’: File exists |
25 | [root@node2 ~]# touch /etc/pki/CA/{serial,index.txt} |
26 | [root@node2 ~]# echo 01 > /etc/pki/CA/serial |
生产证书并请求签署证书:
1 | [root@node2 ssl]# (umask 077;openssl genrsa -out docker.key 2048) |
2 | Generating RSA private key, 2048 bit long modulus |
3 | ............+++ |
4 | ........................+++ |
5 | e is 65537 (0x10001) |
6 | [root@node2 ssl]# openssl req -new -key docker.key -out docker.csr -days 365 |
7 | You are about to be asked to enter information that will be incorporated |
8 | into your certificate request. |
9 | What you are about to enter is what is called a Distinguished Name or a DN. |
10 | There are quite a few fields but you can leave some blank |
11 | For some fields there will be a default value, |
12 | If you enter '.', the field will be left blank. |
13 | ----- |
14 | Country Name (2 letter code) [XX]:CN |
15 | State or Province Name (full name) []:ZJ |
16 | Locality Name (eg, city) [Default City]:HZ |
17 | Organization Name (eg, company) [Default Company Ltd]:JU |
18 | Organizational Unit Name (eg, section) []:TE |
19 | Common Name (eg, your name or your server's hostname) []:docker.jusene.com |
20 | Email Address []:docker@1234.com |
21 | |
22 | Please enter the following 'extra' attributes |
23 | to be sent with your certificate request |
24 | challenge password []: |
25 | ▽n optional company name []: |
26 | [root@node2 ssl]# openssl ca -in docker.csr -out docker.crt -days 365 |
27 | Using configuration from /etc/pki/tls/openssl.cnf |
28 | Check that the request matches the signature |
29 | Signature ok |
30 | Certificate Details: |
31 | Serial Number: 1 (0x1) |
32 | Validity |
33 | Not Before: Aug 6 00:10:43 2017 GMT |
34 | Not After : Aug 6 00:10:43 2018 GMT |
35 | Subject: |
36 | countryName = CN |
37 | stateOrProvinceName = ZJ |
38 | organizationName = JU |
39 | organizationalUnitName = TE |
40 | commonName = docker.jusene.com |
41 | emailAddress = docker@1234.com |
42 | X509v3 extensions: |
43 | X509v3 Basic Constraints: |
44 | CA:FALSE |
45 | Netscape Comment: |
46 | OpenSSL Generated Certificate |
47 | X509v3 Subject Key Identifier: |
48 | 68:93:09:8A:21:AD:44:38:3E:2E:AA:95:45:26:AA:3B:F8:0D:BF:7D |
49 | X509v3 Authority Key Identifier: |
50 | keyid:B4:5E:B1:F9:B0:6D:78:53:90:1B:FB:CB:BF:D1:2E:8A:FB:82:58:EC |
51 | |
52 | Certificate is to be certified until Aug 6 00:10:43 2018 GMT (365 days) |
53 | Sign the certificate? [y/n]:y |
54 | |
55 | |
56 | 1 out of 1 certificate requests certified, commit? [y/n]y |
57 | Write out database with 1 new entries |
58 | Data Base Updated |
修改配置:
1 | ~]# vim /etc/docker-distribution/registry/config.yml |
2 | version: 0.1 |
3 | log: |
4 | fields: |
5 | service: registry |
6 | storage: |
7 | cache: |
8 | layerinfo: inmemory |
9 | filesystem: |
10 | rootdirectory: /var/lib/registry |
11 | http: |
12 | addr: :5000 |
13 | tls: |
14 | certificate: /tmp/ssl/docker.crt |
15 | key: /tmp/ssl/docker.key |
16 | ~]# systemctl restart docker-distribution |
将ca的证书安装在docker client上
1 | ~]# scp cacert.pem 10.211.55.6:/root |
1 | ~]# mkdir /etc/docker/certs.d/docker.jusene.com:5000 |
2 | ~]# mv cacert.pem /etc/docker/certs.d/docker.jusene.com:5000/ca.crt |
3 | ~]# systemctl restart docker |
4 | ~]# docker tag busybox docker.jusene.com:5000/busybox/v1 |
5 | ~]# docker push docker.jusene.com:5000/busybox/v1 |
6 | The push refers to a repository [docker.jusene.com:5000/busybox/v1] |
7 | 6a749002dd6a: Pushed |
8 | latest: digest: sha256:b82b5740006c1ab823596d2c07f081084ecdb32fd258072707b99f52a3cb8692 size: 527 |
容器配置证书:
1 | ~]# docker run -d -p 5000:5000 --restart=always |
2 | -v /data/registry/conf/config.yml:/etc/docker/registry/config.yml \ |
3 | -v /data/registry/data:/var/lib/registry \ |
4 | -v `pwd`/certs:/certs \ |
5 | -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/docker.crt \ |
6 | -e REGISTRY_HTTP_TLS_KEY=/certs/docker.key \ |
7 | --name registry registry |
管理访问权限
docker-distribution本身并没有实现认证访问的功能,但是我们可以使用nginx的反向代理实现:
1 | ~]# vim /etc/nginx/nginx.conf |
2 | upstream docker-registry { |
3 | server localhost:5000; |
4 | |
5 | } |
6 | server { |
7 | listen 15000 ssl; |
8 | server_name docker.jusene.com; |
9 | |
10 | ssl on; |
11 | ssl_certificate /tmp/ssl/docker.crt; |
12 | ssl_certificate_key /tmp/ssl/docker.key; |
13 | |
14 | client_max_body_size 0; #disable any limits to avoid HTTP 413 for large image uploads |
15 | chunked_transfer_encoding on; #requied to avoid HTTP 411 |
16 | |
17 | location /v2/ { |
18 | auth_basic "Docker Registry Auth"; |
19 | auth_basic_user_file /tmp/.htpasswd; |
20 | add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always; |
21 | proxy_pass http://docker-registry; |
22 | proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; |
23 | proxy_redirect off; |
24 | proxy_buffering off; |
25 | proxy_set_header Host $host; |
26 | proxy_set_header X-Real-IP $remote_addr; |
27 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
28 | } |
29 | |
30 | } |
31 | ~]# htpasswd -c -m /tmp/.htpasswd zgx |
32 | New password: |
33 | Re-type new password: |
34 | Adding password for user zgx |
35 | |
36 | |
37 | #测试 |
38 | ~]# docker login docker.jusene.me:15000 |
39 | Username: zgx |
40 | Password: |
41 | Login Succeeded |
42 | ~]# docker push docker.jusene.me:15000/alpine |
43 | The push refers to a repository [docker.jusene.me:15000/alpine] |
44 | 2aebd096e0e2: Layer already exists |
45 | latest: digest: sha256:4b8ffaaa896d40622ac10dc6662204f429f1c8c5714be62a6493a7895f664098 size: 528 |
配置registry
以下是一份详细的docker-distribution配置文件示例:
1 | version: 0.1 |
2 | log: |
3 | level: debug #日志级别 |
4 | formatter: text #日志输出格式,包括text,json,logstash等 |
5 | fields: #增加到日志输出的键值对,可以用来过滤日志 |
6 | service: registry |
7 | environment: development |
8 | hooks: #钩子,当仓库发生异常通过邮件发送 |
9 | - type: mail |
10 | disable: true |
11 | levels: |
12 | - panic |
13 | options: |
14 | smtp: |
15 | addr: mail.example.com:25 |
16 | username: mailuser |
17 | password: password |
18 | insecure: true |
19 | from: sender@example.com |
20 | to: |
21 | - errors@example.com |
22 | storage: #存储选项,默认为本地文件系统 |
23 | delete: #是否开启允许删除镜像功能,默认关闭 |
24 | enabled: true |
25 | cache: #开启对镜像层元数据的缓存功能,默认开启 |
26 | layerinfo: inmemory |
27 | blobdescriptor: redis #缓存文件块 |
28 | filesystem: |
29 | rootdirectory: /var/lib/registry |
30 | maintenance: #配置维护相关的功能,包括对孤立旧文件的清理 |
31 | uploadpurging: |
32 | enabled: enable |
33 | age: 168h |
34 | interval: 24h |
35 | dryrun: false |
36 | |
37 | http: |
38 | addr: 5000 |
39 | secret: admin # 必选项,跟安全相关的随机字符串 |
40 | debug: |
41 | addr: localhost:5001 |
42 | headers: |
43 | X-Content-Type-Options: [nosniff] |
44 | tls: #证书路径相关 |
45 | certificate: /path/to/crt |
46 | key: /path/to/key |
47 | http2: #http2是否开启 |
48 | disabled: false |
49 | redis: #缓存文件块 |
50 | addr: localhost:6379 |
51 | password: password |
52 | db: 0 |
53 | pool: |
54 | maxidle: 16 |
55 | maxactive: 64 |
56 | idletimeout: 300s |
57 | dialtimeout: 10ms |
58 | readtimeout: 10ms |
59 | writetimeout: 10ms |
60 | notifications: # 事件的通知机制 |
61 | endpoints: |
62 | - name: local-5003 |
63 | url: http://localhost:5003/callback |
64 | headers: |
65 | Authorization: [Bearer <an example token>] |
66 | timeout: 1s |
67 | threshold: 10 |
68 | backoff: 1s |
69 | disabled: true |
70 | - name: local-8083 |
71 | url: http://localhost:8083/callback |
72 | timeout: 1s |
73 | threshold: 10 |
74 | backoff: 1s |
75 | disabled: true |
76 | health: # 健康状态监控 |
77 | storagedriver: |
78 | enabled: true |
79 | interval: 10s |
80 | threshold: 3 |
81 | file: |
82 | - file: /path/to/check/file |
83 | interval: 10s |
84 | http: |
85 | - uri: http://server.to.check/must/return/200 |
86 | headers: |
87 | Authorization: [Basic password] |
88 | statuscode: 200 |
89 | timeout: 3s |
90 | interval: 10s |
91 | threshold: 3 |
92 | tcp: |
93 | - addr: localhost:6379 |
94 | timeout: 3s |
95 | interval: 10s |
96 | threshold: 3 |
97 | proxy: #pull时的代理设置 |
98 | remoteurl: https://registry-1.docker.io |
99 | username: [username] |
100 | password: [password] #docker --registry-mirror=https://myrepo.com:5000 daemon |
101 | |
102 | validation: #限定指定的url地址才可以push |
103 | enabled: true |
104 | manifests; |
105 | urls: |
106 | allow: |
107 | - ^https?://([^/]+\.)*example\.com |
108 | deny: |
109 | - ^https?://www\.example\.com |