资讯专栏INFORMATION COLUMN

搭建Docker私有仓库

fizz / 3654人阅读

摘要:配置项数据持久化支持登录授权验证测试做代理我的方式和遇到的问题作为一个容器其它方案相关链接官方提供了镜像,可以方便的搭建私有仓库,详细文档参考这里。支持为了使得私有仓库安全地对外开放,需要配置支持。

摘要

这篇文章内容包括搭建docker私有仓库的一些配置项和遇到的问题及解决方案。

1.配置项
1.1. 数据持久化
1.2. TLS 支持
1.3. 登录授权验证
1.4. docker compose
2. 测试
3. NGINX做代理
3.1. 我的方式和遇到的问题
3.2. NGINX 作为一个容器
4. 其它方案
5. 相关链接

Docker官方提供了 registry镜像, 可以方便的搭建私有仓库,详细文档参考这里。

配置项 数据持久化

可以通过采用数据卷挂载或者直接挂载宿主机目录的方式来进行。挂载到容器内默认位置: /var/lib/registry
比如可以像如下方式启动, 这里将容器数据存储在了 /mnt/registry.

$ docker run -d 
  -p 5000:5000 
  --restart=always 
  --name registry 
  -v /mnt/registry:/var/lib/registry 
  registry:2

当然,镜像还提供了其它支持的存储方式,比如OSS等。

官方文档参见这里。

TLS 支持

为了使得私有仓库安全地对外开放,需要配置 TLS 支持。

测试的时候,如果不配置的话TLS,可以在docker客户端中的 "insecure registry" 里添加私有仓库地址,不然默认的都以安全的tsl方式来访问私有仓库,具体更改方式可以参考这里。

我的CA证书是从阿里云获取的(因为域名是在上面注册的,可以提供免费的证书,虽然如果做得很隐蔽)。

registry镜像可以通过 REGISTRY_HTTP_TLS_CERTIFICATEREGISTRY_HTTP_TLS_KEY 环境参数配置TLS支持。
例如下面这样, domain.crtdomain.key 是获得的证书,另外配置容器监听ssl默认的 443 端口。

$ docker run -d 
  --restart=always 
  --name registry 
  -v `pwd`/certs:/certs 
  -e REGISTRY_HTTP_ADDR=0.0.0.0:443 
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt 
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key 
  -p 443:443 
  registry:2

官方文档参见这里。

登录授权验证

可以通过 htpasswd 来配置简单的authentication (注意:验证需要 TLS 支持)。

首先在 auth 目录下通过reistry里的 htpasswd 工具创建 验证文件 auth/htpasswd

$ mkdir auth
$ docker run 
  --entrypoint htpasswd 
  registry:2 -Bbn testuser testpassword > auth/htpasswd

启动的时候通过 REGISTRY_AUTH, REGISTRY_AUTH_HTPASSWD_REALM, REGISTRY_AUTH_HTPASSWD_PATH 来配置:

$ docker run -d 
  -p 5000:5000 
  --restart=always 
  --name registry 
  -v `pwd`/auth:/auth 
  -e "REGISTRY_AUTH=htpasswd" 
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" 
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd 
  -v `pwd`/certs:/certs 
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt 
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key 
  registry:2

这样就启动了一个监听5000端口的、支持TLS和简单登录验证的docker 私有仓库。

官方文档参见这里。

docker compose

"docker compose" 是一个方便定义和运行多个容器的工具, 安装参见这里, 或者通过pip安装: pip install docker-compose

以上配置项通过 docker compose 的方式组织起来如下:

文件命名成 docker-compose.yaml

registry:
  restart: always
  image: registry:2
  ports:
    - 5000:5000
  environment:
    REGISTRY_HTTP_TLS_CERTIFICATE: /certs/domain.crt
    REGISTRY_HTTP_TLS_KEY: /certs/domain.key
    REGISTRY_AUTH: htpasswd
    REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
    REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
  volumes:
    - /path/data:/var/lib/registry
    - /path/certs:/certs
    - /path/auth:/auth

docker-compose.yaml 所在目录运行:

docker-compose up
测试

私有仓库搭建好了如何测试?

# 先拉取官方镜像
$ docker pull ubuntu:16.04

# 打上标签
$ docker tag ubuntu:16.04 myregistrydomain.com/my-ubuntu

# 推到私有仓库
$ docker push myregistrydomain.com/my-ubuntu

# 从私有仓库获取
$ docker pull myregistrydomain.com/my-ubuntu
Nginx做代理 我的方式和遇到的问题

实际配置中,我采用了 nginx 作为代理,来访问 registry服务。我将TLS支持和登录验证都加到了nginx一层。

nginx 配置文件:

upstream docker-registry {
  server localhost:5000;                          # !转发到registry 监听的5000 端口!
}

## Set a variable to help us decide if we need to add the
## "Docker-Distribution-Api-Version" header.
## The registry always sets this header.
## In the case of nginx performing auth, the header is unset
## since nginx is auth-ing before proxying.
map $upstream_http_docker_distribution_api_version $docker_distribution_api_version {
  "" "registry/2.0";
}

server {
  listen 443 ssl;
  server_name domain.com;  # !这里配置域名!

  # SSL
  ssl_certificate /path/to/domain.pem;               # !这里配置CA 证书信息!
  ssl_certificate_key /path/to/domain.key;           # !这里配置CA 证书信息!

  # Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
  ssl_protocols TLSv1.1 TLSv1.2;
  ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
  ssl_prefer_server_ciphers on;
  ssl_session_cache shared:SSL:10m;

  # disable any limits to avoid HTTP 413 for large image uploads
  client_max_body_size 0;

  # required to avoid HTTP 411: see Issue #1486 (https://github.com/moby/moby/issues/1486)
  chunked_transfer_encoding on;

  location /v2/ {
    # Do not allow connections from docker 1.5 and earlier
    # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
    if ($http_user_agent ~ "^(docker/1.(3|4|5(?!.[0-9]-dev))|Go ).*$" ) {
      return 404;
    }

    # To add basic authentication to v2 use auth_basic setting.
    auth_basic "Registry realm";
    auth_basic_user_file /path/to/auth/htpasswd;          # !这里配置auth文件位置!

    ## If $docker_distribution_api_version is empty, the header is not added.
    ## See the map directive above where this variable is defined.
    add_header "Docker-Distribution-Api-Version" $docker_distribution_api_version always;

    proxy_pass                          http://docker-registry;
    proxy_set_header  Host              $http_host;   # required for docker client"s sake
    proxy_set_header  X-Real-IP         $remote_addr; # pass on real client"s IP
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;
  }
}

其中 /path/to/auth/htpasswd 文件是通过 registry 中的或者本地的 htpasswd 工具生成的

$ docker run 
  --entrypoint htpasswd 
  registry:2 -Bbn testuser testpassword > auth/htpasswd

registry的 docker-compose 文件:

version: "2"
services:
  my_registry:
    restart: always
    image: registry:2
    ports:
      - 127.0.0.1:5000:5000
    volumes:
      - ./data:/var/lib/registry

启动后,当我从本地视图login到私有仓库时,发生错误:

➜  ~ docker login domain.com
Username: testuser
Password:
Error response from daemon: login attempt to https://hub.docker.equiz.cn/v2/ failed with status: 500 Internal Server Error

查看日志发现nginx 错误日志里有个编码相关的错误:

# nginx error log

*4 crypt_r() failed (22: Invalid argument)

经过一番研究,发现之前加密时,是采用 Bcrypt 加密方式,看下 htpasswd 的使用说明:

root@data1:~# htpasswd
Usage:
        htpasswd [-cimBdpsDv] [-C cost] passwordfile username
        htpasswd -b[cmBdpsDv] [-C cost] passwordfile username password

        htpasswd -n[imBdps] [-C cost] username
        htpasswd -nb[mBdps] [-C cost] username password
 -c  Create a new file.
 -n  Don"t update file; display results on stdout.
 -b  Use the password from the command line rather than prompting for it.
 -i  Read password from stdin without verification (for script usage).
 -m  Force MD5 encryption of the password (default).
 -B  Force bcrypt encryption of the password (very secure).
 -C  Set the computing time used for the bcrypt algorithm
     (higher is more secure but slower, default: 5, valid: 4 to 31).
 -d  Force CRYPT encryption of the password (8 chars max, insecure).
 -s  Force SHA encryption of the password (insecure).
 -p  Do not encrypt the password (plaintext, insecure).
 -D  Delete the specified user.
 -v  Verify password for the specified user.
On other systems than Windows and NetWare the "-p" flag will probably not work.
The SHA algorithm does not use a salt and is less secure than the MD5 algorithm.

可以看到 -B 会使用 bcrypt 的方式来加密,nginx默认不支持。至于如何让nginx支持bcrypt我暂时还未找到方案,留待以后研究了(TODO)

简单的解决方式是换成默认的MD5加密(因为安全等级问题又不推荐不用bcrypt方式的),

docker run --rm --entrypoint htpasswd registry:2 -bn testuser testpassword > auth/htpasswd   # 这里少了 -B 选项

关于 bcrypt 加密方式,这里 有一篇不错的文章介绍。不过好像对于这个加密方式,网上有一些争论,我就不详究了。

不依赖 "apche tools" 的 nginx 加密方式参考 这里, 比如MD5加密:

printf "testuser:$(openssl passwd -1 testpassword)
" >> .htpasswd # this example uses MD5 encryption
Nginx 作为一个容器

docker 文档也有如何采用nginx容器和registry配合使用的说明,参考这里。

"docker-compose.yaml" 如下:

nginx:
  # Note : Only nginx:alpine supports bcrypt.
  # If you don"t need to use bcrypt, you can use a different tag.
  # Ref. https://github.com/nginxinc/docker-nginx/issues/29
  image: "nginx:alpine"     # !这里一定要采用alpine镜像,因为它里的nginx支持 bcrypt 加密!
  ports:
    - 5043:443
  links:
    - registry:registry
  volumes:
    - ./auth:/etc/nginx/conf.d
    - ./auth/nginx.conf:/etc/nginx/nginx.conf:ro

registry:
  image: registry:2
  ports:
    - 127.0.0.1:5000:5000
  volumes:
    - ./data:/var/lib/registry

这里nginx容器监听的是5043, 所以使用的私有仓库的地址变成了 registrydomain.com:5043,
我不喜欢后面加端口,但本机又存在其他需要nginx监听的443端口的服务(不同doamin下),所以不能让nginx容器直接监听443端口,故没有采用这种方式。

另外在寻找解决方案的时候发现一个镜像 nginx-proxy, 可以方便地监听新添加的容器,留待以后探索。

其它方案

或许你想用letsencrypts免费证书,不妨看看这个工具:acme.sh

或许你不满足的简易方案,你可能还需要web界面来方便查看和管理你的镜像仓库,那么你可以查看下企业级的容器仓库方案: vmware/harbor

相关链接

docker ce ubuntu 安装 文档: https://docs.docker.com/insta...

docker compose 安装文档: https://docs.docker.com/compo...

docker registr 镜像: https://hub.docker.com/_/regi...

deploy 部署步骤文档: https://docs.docker.com/regis...

详细的registry的可配置项参见: https://docs.docker.com/regis...

nginx容器bcrypt问题: https://github.com/docker/dis...

nginx容器bcrypt问题2: https://github.com/nginxinc/d...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/27234.html

相关文章

  • Nexus3私有仓库搭建 docker+maven+npm

    摘要:安装号称是世界上最流行的私服管理软件可以搭建几乎目前所有常见的仓库如等更是增加了对仓库的支持应该是搭建私服的唯一选择有两个版本和其中版本是免费专业版需要收费对于日常的仓库管理已经足够用支持二进制文件安装和安装这里选择安装简单方便运行以下命令 安装 Nexus号称是世界上最流行的私服管理软件(The worlds most popular repository),可以搭建几乎目前所有常见...

    bang590 评论0 收藏0
  • 使用 docker + verdaccio 搭建npm私有仓库

    摘要:本文介绍如何使用搭建私有仓库,以及使用时如何映射到本地目录,方便简单对仓库进行各种操作。其次,创建目录,并添加的配置文件。当需要把某个项目发布到私有库时,直接。使用包名,即可安装私有包了。本文介绍如何使用 verdaccio 搭建私有npm仓库,以及使用 docker 时如何映射到本地目录,方便简单对仓库进行各种操作。系统环境是 Linux。 verdaccio verdacci...

    fantix 评论0 收藏0
  • Docker Registry Server 搭建,配置免费HTTPS证书,及拥有权限认证、TLS

    摘要:上一篇文章搭建了一个具有基础功能的私有仓库,这次来搭建一个拥有权限认证的私有仓库。移动证书到目录。身份验证为用户创建一个带有一个条目的密码文件,密码为创建仓库启动注册表,指示它使用证书。注册表在端口默认的端口上运行。 上一篇文章搭建了一个具有基础功能的私有仓库,这次来搭建一个拥有权限认证、TLS 的私有仓库。 环境准备 系统:Ubuntu 17.04 x64 IP:198.13.48...

    liuchengxu 评论0 收藏0
  • docker搭建私有仓库、自签发证书、登录认证

    摘要:官方文档对如何搭建私有仓库说的已经很详细了,我在这里主要介绍一下使用自签发证书如何搭建私有仓库并认证成功。生成自签发证书。登录成功后再次执行操作,会出现的报错。这是因为认为传输过来的证书的签署方是一个未知的,因此验证失败。 docker官方文档对如何搭建私有仓库说的已经很详细了,我在这里主要介绍一下使用自签发证书如何搭建私有仓库并认证成功。 假设registry的域名为:registr...

    SolomonXie 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<