V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Mush
V2EX  ›  分享发现

如何部署一个 docker registry

  •  1
     
  •   Mush · 2016-03-28 15:51:38 +08:00 · 6605 次点击
    这是一个创建于 3162 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Deploy a secure docker registry

    啊! 部署一个 Docker registry 好麻烦, 所以我部署完之后撸了一个文档, 奈何我的博客太丑不想在上面发(又没有时间撸个新博客), 所以就在这里发出来给大家看看, 希望能帮你们省点时间.

    获取 SSL 证书

    git clone https://github.com/letsencrypt/letsencrypt
    cd letsencrypt
    ./letsencrypt-auto --help
    ./letsencrypt-auto certonly --standalone -d <HOST>
    

    letsencrypt 会将证书生成到/etc/letsencrypt/live/<HOST>/目录下, 我们可以将其复制到一个 docker 数据卷专用的目录下方便挂载.

    letsencrypt 生成的证书是.pem 格式的, docker 文档上给的例子是.crt 的, 但是经我测试直接使用 letsencrypt 生成的证书就可以了.

    生成 http 密码文件

    docker run --entrypoint htpasswd registry -Bbn <username> <password> > auth/htpasswd
    

    或者

    htpasswd -Bbn <USERNAME> <PASSWORD>
    

    Run registry

    #!/bin/bash
    docker run \
        -d --net='host' \
        --restart=always \
        --name registry \
        -v /fs1/dsr/auth/:/auth \
        -e "REGISTRY_AUTH=htpasswd" \
        -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
        -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
        -v /fs1/dsr/crets/:/certs \
        -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/fullchain.pem \
        -e REGISTRY_HTTP_TLS_KEY=/certs/privkey.pem \
        -e REGISTRY_STORAGE_DELETE_ENABLED=true \
        -v /fs1/dsr/registry/:/var/lib/registry registry:2.3.1
    

    这个东西坑太多了, 需要注意一点是, registry 默认没有启用删除镜像的功能, 而且当你上传镜像版本过多的情况下, 会把你硬盘塞满的, 所以需要在启动时增加一个-e REGISTRY_STORAGE_DELETE_ENABLED=true参数来开启删除镜像的功能. 至于怎么删除镜像, 那就更坑了, 放心下面会写的.

    客户机执行的操作

    要想 push 到一个安全的 docker registry 或者上面 pull 下一个 image, 我们需要先 login.

     docker login <HOST>:<PORT>
    

    push 的话, 需要先 tag 一下

    docker tag <image>:<tag> <HOST>:<PORT>/<image>:<tag>
    

    pull 的话, 直接 pull 一个完整的路径

    docker pull <HOST>:<PORT>/<image>:<tag>
    

    HTTP API V2

    docker registry 的管理需要通过 API 进行, 其 API 设计非常规范, 但是巨难用. 下面使用 Python 的 requests 库来简单写下调用方式

    登陆

    import requests
    
    url = "https://<username>:<password>@<registry-host>:<port>/v2/"
    
    headers = {
        'cache-control': "no-cache",
        'postman-token': "83e67d92-5abe-33f0-0f0b-3f887401dbb6"
        }
    
    response = requests.request("GET", url, headers=headers)
    
    print(response.text)
    

    镜像列表

    import requests
    
    url = "https://<HOST>:<PORT>/v2/_catalog"
    
    headers = {
        'cache-control': "no-cache",
        'postman-token': "44940e36-b98a-da5e-daed-935df752f28c"
        }
    
    response = requests.request("GET", url, headers=headers)
    
    print(response.text)
    
    {
      "repositories": [
        "mush/ss-server",
        "solo/dev",
        "solo/jenkins",
        "solo/live-api-runtime",
        "solo/pingstart-runtime",
        "solo/warehouse-runtime",
        "ubuntu"
      ]
    }
    

    获取镜像的 tag

    import requests
    
    url = "https://<HOST>:<PORT>/v2/solo/live-api-runtime/tags/list"
    
    headers = {
        'cache-control': "no-cache",
        'postman-token': "a9bdb73e-6beb-2ca1-44c2-08572054c994"
        }
    
    response = requests.request("GET", url, headers=headers)
    
    print(response.text)
    
    {
      "name": "solo/live-api-runtime",
      "tags": [
        "21",
        "84",
        "20"
      ]
    }
    

    获取 manifests

    import requests
    
    url = "https://<HOST>:<PORT>/v2/solo/live-api-runtime/manifests/6"
    
    headers = {
        'cache-control': "no-cache",
        'postman-token': "2376f1a6-91a3-fc00-1c42-e498ceecfc93"
        }
    
    response = requests.request("GET", url, headers=headers)
    
    print(response.text)
    

    这里, 在响应头里会有Docker-Content-Digest →sha256:fcd95bdae75d558ba53bd6f660003f6ba90d95c18ddb483d2d0ad7d6166034ab, 这个很重要, 是一个 image 的唯一标识.

    删除一个镜像

    import requests
    
    url = "https://<HOST>:<PORT>/v2/solo/live-api-runtime/manifests/sha256:fcd95bdae75d558ba53bd6f660003f6ba90d95c18ddb483d2d0ad7d6166034ab"
    
    headers = {
        'cache-control': "no-cache",
        'postman-token': "edad64ad-38c3-e363-581e-5028ba14c48a"
        }
    
    response = requests.request("DELETE", url, headers=headers)
    
    print(response.text)
    

    response code 为 202 就是 OK 了. 然而这个删除并不能将文件从硬盘上删除掉, 所以我也不造官方是怎么想的, 做了一个如此无用的接口......

    要想将文件从硬盘上删除可以看看burnettk/delete-docker-registry-image

    其他事项

    更新 SSL 证书

    #!/bin/sh
    systemctl stop nginx
    if ! /opt/letsencrypt/letsencrypt-auto renew -nvv --standalone --force-renewal > /var/log/letsencrypt/renew.log 2>&1 ; then
        echo Automated renewal failed:
        cat /var/log/letsencrypt/renew.log
        exit 1
    fi
    systemctl start nginx
    

    注意: 记得将证书复制到你需要的地方

    如何查看 registry 上有哪些镜像

    直接浏览器访问registry 的接口即可

    参考文档

    生成有效的 ssl 证书: letsencrypt

    部署 docker registry: docker 官方文档

    API 文档: Docker Registry HTTP API V2

    7 条回复    2018-05-17 18:02:31 +08:00
    wujunze
        1
    wujunze  
       2016-03-28 16:04:36 +08:00
    沙发 好久不见你在群里冒泡了
    Mush
        2
    Mush  
    OP
       2016-03-28 16:06:54 +08:00
    @wujunze 最近累的要死....
    wujunze
        3
    wujunze  
       2016-03-28 16:08:37 +08:00
    @Mush 你在新公司 还好吧?
    imxieke
        4
    imxieke  
       2016-03-28 17:00:56 +08:00
    我记得官方有直接部署的镜像吧?
    https://hub.docker.com/_/registry/
    Mush
        5
    Mush  
    OP
       2016-03-28 17:06:29 +08:00
    @imxieke 是的, 但是其中有坑, 比如说 https 证书还有日后维护什么的

    @wujunze 很好
    iappled
        6
    iappled  
       2017-11-16 11:02:08 +08:00
    rootcertbundle 这个怎么配置
    huixia0010
        7
    huixia0010  
       2018-05-17 18:02:31 +08:00
    谢谢楼主分享经验
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1716 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:46 · PVG 00:46 · LAX 08:46 · JFK 11:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.