Docker Registry 使用教程

    在開發docker app的時候,爲了共享這個鏡像,導出再分發給團隊成員是比較麻煩的作法。Docker 提供了一個 Registry 給咱們上傳開發好的鏡像(相似 maven 的私有倉庫),這樣須要使用的團隊成員去 registry 上下載便可。redis

下面介紹下如何使用docker

1. 下載官方鏡像 docker pull registryjson

[root@localhost ~]# docker pull registry
Using default tag: latest
latest: Pulling from library/registry
ab7e51e37a18: Pull complete 
c8ad8919ce25: Pull complete 
5808405bc62f: Pull complete 
f6000d7b276c: Pull complete 
f792fdcd8ff6: Pull complete 
Digest: sha256:9d295999d330eba2552f9c78c9f59828af5c9a9c15a3fbd1351df03eaad04c6a
Status: Downloaded newer image for registry:latest
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
registry            latest              177391bcf802        6 days ago          33.3MB
[root@localhost ~]#

 

2. 按照官方說明(傳送門)啓動ubuntu

[root@localhost ~]# docker run -d -p 5000:5000 --name registry registry
acff7e5e012f996a7a03c7b7bf26773755cfa908cde3ae1dbdcd8ec970e2dff1
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
acff7e5e012f        registry            "/entrypoint.sh /e..."   6 seconds ago       Up 6 seconds        0.0.0.0:5000->5000/tcp   registry
[root@localhost ~]#

這樣私有的 docker registry 就建好了。swift

 

接下來做爲 demo 下載一個簡單的 hello-worldapi

[root@localhost ~]# docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
ca4f61b1923c: Pull complete 
Digest: sha256:be0cd392e45be79ffeffa6b05338b98ebb16c87b255f48e297ec7f98e123905c
Status: Downloaded newer image for hello-world:latest
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
registry            latest              177391bcf802        6 days ago          33.3MB
hello-world         latest              f2a91732366c        2 weeks ago         1.85kB
[root@localhost ~]#

重命名鏡像名稱 docker tag <鏡像名> <倉庫地址:端口>/新的鏡像名bash

[root@localhost ~]# docker tag hello-world localhost:5000/my-hello-world
[root@localhost ~]# docker images
REPOSITORY                      TAG                 IMAGE ID            CREATED             SIZE
registry                        latest              177391bcf802        6 days ago          33.3MB
hello-world                     latest              f2a91732366c        2 weeks ago         1.85kB
localhost:5000/my-hello-world   latest              f2a91732366c        2 weeks ago         1.85kB
[root@localhost ~]#

上傳鏡像 docker push <倉庫地址:端口>/新的鏡像名app

[root@localhost ~]# docker push localhost:5000/my-hello-world
The push refers to a repository [localhost:5000/my-hello-world]
f999ae22f308: Pushed 
latest: digest: sha256:8072a54ebb3bc136150e2f2860f00a7bf45f13eeb917cca2430fcd0054c8e51b size: 524
[root@localhost ~]#

刪除本地鏡像dom

[root@localhost ~]# docker rmi localhost:5000/my-hello-world
Untagged: localhost:5000/my-hello-world:latest
[root@localhost ~]# docker rmi hello-world
Untagged: hello-world:latest
Untagged: hello-world@sha256:be0cd392e45be79ffeffa6b05338b98ebb16c87b255f48e297ec7f98e123905c
Deleted: sha256:f2a91732366c0332ccd7afd2a5c4ff2b9af81f549370f7a19acd460f87686bc7
Deleted: sha256:f999ae22f308fea973e5a25b57699b5daf6b0f1150ac2a5c2ea9d7fecee50fdf
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
registry            latest              177391bcf802        6 days ago          33.3MB
[root@localhost ~]#

從倉庫下載鏡像 docker pull <倉庫地址:端口>/鏡像名curl

[root@localhost ~]# docker pull localhost:5000/my-hello-world
Using default tag: latest
latest: Pulling from my-hello-world
ca4f61b1923c: Pull complete 
Digest: sha256:8072a54ebb3bc136150e2f2860f00a7bf45f13eeb917cca2430fcd0054c8e51b
Status: Downloaded newer image for localhost:5000/my-hello-world:latest
[root@localhost ~]# docker images
REPOSITORY                      TAG                 IMAGE ID            CREATED             SIZE
registry                        latest              177391bcf802        6 days ago          33.3MB
localhost:5000/my-hello-world   latest              f2a91732366c        2 weeks ago         1.85kB
[root@localhost ~]#

重命名一下就可使用了

[root@localhost ~]# docker tag localhost:5000/my-hello-world my-hello-world
[root@localhost ~]# docker images
REPOSITORY                      TAG                 IMAGE ID            CREATED             SIZE
registry                        latest              177391bcf802        6 days ago          33.3MB
my-hello-world                  latest              f2a91732366c        2 weeks ago         1.85kB
localhost:5000/my-hello-world   latest              f2a91732366c        2 weeks ago         1.85kB
[root@localhost ~]#

 

基本概念就是這樣,可是還有一些問題。

1. 這樣的啓動方式,上傳的數據都是做爲一個 docker volume 存儲在宿主機上面。若是這個 registry 容器被刪除,那麼容器內的數據也會丟失,即咱們上傳的鏡像。

因此咱們須要將 registry 的鏡像地址映射到宿主機上面,registry 在容器內部的存儲地址是 /var/lib/registry/, 經過添加 -v 映射到宿主機。

[root@localhost ~]# docker rm -f registry
registry
[root@localhost ~]# docker run --name registry -d -p 5000:5000 -v /home/saul/registry:/var/lib/registry registry
a107eda18508d791085ebcec5cbb9378d496239fba0f7347e998eeda5966dc18
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
a107eda18508        registry            "/entrypoint.sh /e..."   4 seconds ago       Up 3 seconds        0.0.0.0:5000->5000/tcp   registry
[root@localhost ~]#

將原來的容器刪除,從新建一個。這裏我映射到了 /home/john/registry 這個目錄下。

再次上傳鏡像

[root@localhost registry]# docker push localhost:5000/my-hello-world
The push refers to a repository [localhost:5000/my-hello-world]
f999ae22f308: Pushed 
latest: digest: sha256:8072a54ebb3bc136150e2f2860f00a7bf45f13eeb917cca2430fcd0054c8e51b size: 524

2. 如何查看鏡像

官網提供了一套操做 registry 的 api (傳送門)

查看倉庫 GET /v2/_catalog

[root@localhost registry]# curl http://127.0.0.1:5000/v2/_catalog
{"repositories":["my-hello-world"]}

查看鏡像標籤 GET /v2/<name>/tags/list

[root@localhost registry]# curl http://127.0.0.1:5000/v2/my-hello-world/tags/list
{"name":"my-hello-world","tags":["latest"]}

如今只有一個 latest 標籤,這裏 run 下 hello-world,而後提交一個新的版本1.0

[root@localhost registry]# docker images
REPOSITORY                      TAG                 IMAGE ID            CREATED             SIZE
registry                        latest              177391bcf802        6 days ago          33.3MB
localhost:5000/my-hello-world   latest              f2a91732366c        2 weeks ago         1.85kB
my-hello-world                  latest              f2a91732366c        2 weeks ago         1.85kB
[root@localhost registry]# docker run -it my-hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://cloud.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/

[root@localhost registry]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                    NAMES
e023cad89c0d        my-hello-world      "/hello"                 6 seconds ago       Exited (0) 5 seconds ago                            determined_keller
a107eda18508        registry            "/entrypoint.sh /e..."   8 minutes ago       Up 8 minutes               0.0.0.0:5000->5000/tcp   registry
[root@localhost registry]# docker commit -m "1.0" e023cad89c0d my-hello-world:1.0
sha256:d9f41037af5b7648d4a1bfb0a95b903f16ebc52a23a0883896ae71d7831ee97c
[root@localhost registry]# docker images
REPOSITORY                      TAG                 IMAGE ID            CREATED             SIZE
my-hello-world                  1.0                 d9f41037af5b        4 seconds ago       1.85kB
registry                        latest              177391bcf802        6 days ago          33.3MB
localhost:5000/my-hello-world   latest              f2a91732366c        2 weeks ago         1.85kB
my-hello-world                  latest              f2a91732366c        2 weeks ago         1.85kB
[root@localhost registry]#

上傳鏡像

[root@localhost registry]# docker tag my-hello-world:1.0 localhost:5000/my-hello-world:1.0
[root@localhost registry]# docker images
REPOSITORY                      TAG                 IMAGE ID            CREATED              SIZE
my-hello-world                  1.0                 d9f41037af5b        About a minute ago   1.85kB
localhost:5000/my-hello-world   1.0                 d9f41037af5b        About a minute ago   1.85kB
registry                        latest              177391bcf802        6 days ago           33.3MB
my-hello-world                  latest              f2a91732366c        2 weeks ago          1.85kB
localhost:5000/my-hello-world   latest              f2a91732366c        2 weeks ago          1.85kB
[root@localhost registry]# docker push localhost:5000/my-hello-world:1.0
The push refers to a repository [localhost:5000/my-hello-world]
f999ae22f308: Layer already exists 
1.0: digest: sha256:69b12f1aeee0355bcf803b5159f96f69738f6b002ea3b6861b802aff337d26cf size: 524
[root@localhost registry]#

再次查看倉庫的標籤

[root@localhost registry]# curl http://127.0.0.1:5000/v2/my-hello-world/tags/list
{"name":"my-hello-world","tags":["latest","1.0"]}

能夠看到有 latest, 1.0 2個標籤

3. 那麼怎麼刪除倉庫裏的鏡像

DELETE /v2/<name>/manifests/<reference>

注:registry 2.3 版本以上 須要在頭部添加 

Accept: application/vnd.docker.distribution.manifest.v2+json

[root@localhost registry]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -X DELETE http://127.0.0.1:5000/v2/my-hello-world/manifests/latest
{"errors":[{"code":"UNSUPPORTED","message":"The operation is unsupported."}]}
[root@localhost registry]#

提示 UNSUPPORTED! 爲何?

查閱資料得知 registry 有個配置文件 config.yml 內容以下

version: 0.1
log:
  accesslog:
    disabled: true
  level: debug
  formatter: text
  fields:
    service: registry
    environment: staging
  hooks:
    - type: mail
      disabled: true
      levels:
        - panic
      options:
        smtp:
          addr: mail.example.com:25
          username: mailuser
          password: password
          insecure: true
        from: sender@example.com
        to:
          - errors@example.com
loglevel: debug # deprecated: use "log"
storage:
  filesystem:
    rootdirectory: /var/lib/registry
    maxthreads: 100
  azure:
    accountname: accountname
    accountkey: base64encodedaccountkey
    container: containername
  gcs:
    bucket: bucketname
    keyfile: /path/to/keyfile
    rootdirectory: /gcs/object/name/prefix
    chunksize: 5242880
  s3:
    accesskey: awsaccesskey
    secretkey: awssecretkey
    region: us-west-1
    regionendpoint: http://myobjects.local
    bucket: bucketname
    encrypt: true
    keyid: mykeyid
    secure: true
    v4auth: true
    chunksize: 5242880
    multipartcopychunksize: 33554432
    multipartcopymaxconcurrency: 100
    multipartcopythresholdsize: 33554432
    rootdirectory: /s3/object/name/prefix
  swift:
    username: username
    password: password
    authurl: https://storage.myprovider.com/auth/v1.0 or https://storage.myprovider.com/v2.0 or https://storage.myprovider.com/v3/auth
    tenant: tenantname
    tenantid: tenantid
    domain: domain name for Openstack Identity v3 API
    domainid: domain id for Openstack Identity v3 API
    insecureskipverify: true
    region: fr
    container: containername
    rootdirectory: /swift/object/name/prefix
  oss:
    accesskeyid: accesskeyid
    accesskeysecret: accesskeysecret
    region: OSS region name
    endpoint: optional endpoints
    internal: optional internal endpoint
    bucket: OSS bucket
    encrypt: optional data encryption setting
    secure: optional ssl setting
    chunksize: optional size valye
    rootdirectory: optional root directory
  inmemory:  # This driver takes no parameters
  delete:
    enabled: false
  redirect:
    disable: false
  cache:
    blobdescriptor: redis
  maintenance:
    uploadpurging:
      enabled: true
      age: 168h
      interval: 24h
      dryrun: false
    readonly:
      enabled: false
auth:
  silly:
    realm: silly-realm
    service: silly-service
  token:
    realm: token-realm
    service: token-service
    issuer: registry-token-issuer
    rootcertbundle: /root/certs/bundle
  htpasswd:
    realm: basic-realm
    path: /path/to/htpasswd
middleware:
  registry:
    - name: ARegistryMiddleware
      options:
        foo: bar
  repository:
    - name: ARepositoryMiddleware
      options:
        foo: bar
  storage:
    - name: cloudfront
      options:
        baseurl: https://my.cloudfronted.domain.com/
        privatekey: /path/to/pem
        keypairid: cloudfrontkeypairid
        duration: 3000s
  storage:
    - name: redirect
      options:
        baseurl: https://example.com/
reporting:
  bugsnag:
    apikey: bugsnagapikey
    releasestage: bugsnagreleasestage
    endpoint: bugsnagendpoint
  newrelic:
    licensekey: newreliclicensekey
    name: newrelicname
    verbose: true
http:
  addr: localhost:5000
  prefix: /my/nested/registry/
  host: https://myregistryaddress.org:5000
  secret: asecretforlocaldevelopment
  relativeurls: false
  tls:
    certificate: /path/to/x509/public
    key: /path/to/x509/private
    clientcas:
      - /path/to/ca.pem
      - /path/to/another/ca.pem
    letsencrypt:
      cachefile: /path/to/cache-file
      email: emailused@letsencrypt.com
  debug:
    addr: localhost:5001
  headers:
    X-Content-Type-Options: [nosniff]
  http2:
    disabled: false
notifications:
  endpoints:
    - name: alistener
      disabled: false
      url: https://my.listener.com/event
      headers: <http.Header>
      timeout: 500
      threshold: 5
      backoff: 1000
      ignoredmediatypes:
        - application/octet-stream
redis:
  addr: localhost:6379
  password: asecret
  db: 0
  dialtimeout: 10ms
  readtimeout: 10ms
  writetimeout: 10ms
  pool:
    maxidle: 16
    maxactive: 64
    idletimeout: 300s
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3
  file:
    - file: /path/to/checked/file
      interval: 10s
  http:
    - uri: http://server.to.check/must/return/200
      headers:
        Authorization: [Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==]
      statuscode: 200
      timeout: 3s
      interval: 10s
      threshold: 3
  tcp:
    - addr: redis-server.domain.com:6379
      timeout: 3s
      interval: 10s
      threshold: 3
proxy:
  remoteurl: https://registry-1.docker.io
  username: [username]
  password: [password]
compatibility:
  schema1:
    signingkeyfile: /etc/registry/key.json
validation:
  enabled: true
  manifests:
    urls:
      allow:
        - ^https?://([^/]+\.)*example\.com/
      deny:
        - ^https?://www\.example\.com/

能夠看到 storage 節點下 delete enabled 默認爲 false

storage:
  delete:
    enabled: false

那麼咱們開啓它,docker 容許經過 -e 傳入環境變量(變量的格式爲 REGISTRY_variable),咱們傳入一個   REGISTRY_STORAGE_DELETE_ENABLED=true 。官網說明(傳送門

那麼刪除原來的 registry 啓動方式改成 

[root@localhost registry]# docker rm -f registry
registry
[root@localhost registry]# docker run --name registry -d -p 5000:5000 -v /home/john/registry:/var/lib/registry -e REGISTRY_STORAGE_DELETE_ENABLED=true registry
8af585efa1914c2354def81eb0cbf3f30bf4fe0d5cab24ba7ce2491cfbc0678b

查看倉庫

[root@localhost registry]# curl  http://127.0.0.1:5000/v2/_catalog
{"repositories":["my-hello-world"]}

剛纔上傳的鏡像還在,並無隨着容器刪除而刪除,證實咱們剛纔將鏡像存在宿主機上的修改是有效的。

再次刪除鏡像

[root@localhost registry]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -X DELETE http://127.0.0.1:5000/v2/my-hello-world/manifests/latest
{"errors":[{"code":"DIGEST_INVALID","message":"provided digest did not match uploaded content"}]}

提示 DISGEST_INVALID,刪除api是 DELETE /v2/<name>/manifests/<reference>,查看官網 For deletes, reference must be a digest or the delete will fail. 必定要是一個 digest。

查閱資料 經過 curl -I 能夠查得

[root@localhost registry]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I -X GET http://localhost:5000/v2/my-hello-world/manifests/latest
HTTP/1.1 200 OK
Content-Length: 524
Content-Type: application/vnd.docker.distribution.manifest.v2+json
Docker-Content-Digest: sha256:8072a54ebb3bc136150e2f2860f00a7bf45f13eeb917cca2430fcd0054c8e51b
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:8072a54ebb3bc136150e2f2860f00a7bf45f13eeb917cca2430fcd0054c8e51b"
X-Content-Type-Options: nosniff
Date: Fri, 08 Dec 2017 08:44:59 GMT

[root@localhost registry]#

Docker-Content-Digest 這個就是咱們須要的 digest

再次調用api 刪除

[root@localhost registry]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -X DELETE http://127.0.0.1:5000/v2/my-hello-world/manifests/sha256:8072a54ebb3bc136150e2f2860f00a7bf45f13eeb917cca2430fcd0054c8e51b
[root@localhost registry]# curl http://127.0.0.1:5000/v2/my-hello-world/tags/list
{"name":"my-hello-world","tags":["1.0"]}
[root@localhost registry]#

能夠看到 lastest 已經沒有了,刪除成功。

其實咱們能夠在文件系統看到tags的信息

[root@localhost tags]# pwd
/home/john/registry/docker/registry/v2/repositories/my-hello-world/_manifests/tags
[root@localhost tags]# ll
total 0
drwxr-xr-x. 4 root root 34 Dec  8 16:21 1.0
[root@localhost tags]#

咱們能夠瀏覽一下這些目錄

[root@localhost v2]# pwd
/home/john/registry/docker/registry/v2
[root@localhost v2]# ll
total 0
drwxr-xr-x. 3 root root 20 Dec  8 11:28 blobs
drwxr-xr-x. 3 root root 28 Dec  8 16:13 repositories
[root@localhost v2]#

在這個目錄下有個blobs目錄

這個目錄在刪除完鏡像也要清理一下,2.4以上registry纔有次功能

docker exec -it <registry_container_id> bin/registry garbage-collect <path_to_registry_config>

 

[root@localhost v2]# docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml
my-hello-world
my-hello-world: marking manifest sha256:69b12f1aeee0355bcf803b5159f96f69738f6b002ea3b6861b802aff337d26cf 
my-hello-world: marking blob sha256:d9f41037af5b7648d4a1bfb0a95b903f16ebc52a23a0883896ae71d7831ee97c
my-hello-world: marking blob sha256:ca4f61b1923c10e9eb81228bd46bee1dfba02b9c7dac1844527a734752688ede

3 blobs marked, 2 blobs eligible for deletion
blob eligible for deletion: sha256:8072a54ebb3bc136150e2f2860f00a7bf45f13eeb917cca2430fcd0054c8e51b
time="2017-12-08T08:56:15Z" level=info msg="Deleting blob: /docker/registry/v2/blobs/sha256/80/8072a54ebb3bc136150e2f2860f00a7bf45f13eeb917cca2430fcd0054c8e51b" go.version=go1.7.6 instance.id=fccb2a78-43b9-4542-9f9d-7bbf0ec0b044 
blob eligible for deletion: sha256:f2a91732366c0332ccd7afd2a5c4ff2b9af81f549370f7a19acd460f87686bc7
time="2017-12-08T08:56:15Z" level=info msg="Deleting blob: /docker/registry/v2/blobs/sha256/f2/f2a91732366c0332ccd7afd2a5c4ff2b9af81f549370f7a19acd460f87686bc7" go.version=go1.7.6 instance.id=fccb2a78-43b9-4542-9f9d-7bbf0ec0b044 
[root@localhost v2]#

這樣刪除就差很少了。

粗暴一點能夠直接(不知道有沒有反作用)

rm -rf /home/john/registry/docker/registry/v2/repositories/<鏡像名>

4. 隨服務啓動

docker run 的時候添加 --restart=always 能夠保證 docker 服務啓動的時候,容器隨服務一塊兒啓動。

docker run --name registry -d -p 5000:5000 --restart=always -v /home/john/registry:/var/lib/registry -e REGISTRY_STORAGE_DELETE_ENABLED=true registry

 

總結

啓動

docker run --name registry -d -p 5000:5000 --restart=always -v /xxx/registry:/var/lib/registry -e REGISTRY_STORAGE_DELETE_ENABLED=true registry

上傳

docker push <registry_ip:port>/<name>

下載

docker pull <registry_ip:port>/<name>

查看 docker registry

GET /v2/_catalog

查看鏡像tags

GET /v2/<name>/tags/list

刪除鏡像

配置config.yml,獲取鏡像 digest

DELETE /v2/<name>/manifests/<reference>
相關文章
相關標籤/搜索