1、创建 Docker 存储空间

点击导航栏设置按钮,进入仓库配置默认界面,选择 Blob Stores 进入储空间管理界面:

点击 “Create blob store”,创建新的存储空间:

Name属性指定为docker;Path根据你的情况进行指定(如挂载的磁盘目录)

Type: File
Name: docker
Path:www/nexus/sonatype-work/nexus3/blobs/docker

2、创建 Docker 仓库

点击导航栏设置按钮,进入 Repositories 界面

点击 “Create repository”,创建新的仓库:

可以看到Docker有三种类型,分别是docker(group),docker(hosted),docker(proxy)。其含义解释如下:

  • hosted : 本地存储,即同docker官方仓库一样提供本地私服功能
  • proxy : 提供代理其他仓库的类型,如docker中央仓库
  • group : 组类型,实质作用是组合多个仓库为一个地址
2.1、创建 Docker 代理仓库

创建一个docker代理仓库,点击docker(proxy),如图填写信息:

勾选 “Allow clients to use the V1 API to interact with this Repository”,允许 Docker V1 API 请求。

官方的镜像地址:https://registry-1.docker.io ,因为网速的原因,访问速度比较慢;所以这里推荐使用国内的Docker镜像加速器地址,如:阿里云、DaoCloud的容器加速;

推荐Docker仓库:

Name Romote Sotrage URL
docker-aliyun https://7bezldxe.mirror.aliyuncs.com
docker-daocloud http://f1361db2.m.daocloud.io

为了确保能够拉取DockerHub最新的镜像,选择了 Use DockerHub 这个Index。并分别配置了 阿里云和DaoCloud的容器加速:

阿里云容器加速:

DaoCloud容器加速:

选择前面已经创建好的Docker存储空间,作为存储目标:

完成后,在仓库地址管理列表可看到新增的厂库:

2.2、创建 Docker 本地仓库

为了能上传Docker镜像到Nexus的Docker镜像私服,需要添加一个本地Docker仓库,这里比较简单,只需要填写本地仓库的名称,比如 docker-hosted,然后填写HTTP端口即可,比如8182:

2.3、创建 Docker 聚合仓库

前面已经创建好了代理厂库和本地仓库,为方便对外提供统一的访问地址,需要创建一个聚合仓库(group),将代理仓库和本地仓库聚合到一起使用,名称可命名为 docker-public,然后端口选择 8183:

将左侧可用成员仓库移动到右侧的列表中,顺序可根据访问速度进行调整,优先将本地的放前面,代理第三方的放后面,好处就是优先使用本地或小众的镜像仓库。

至此,nexus3 配置 docker 镜像仓库已经配置完成了,但是这样并不能很好的使用。因为group仓库并不能推送镜像,因为你推送自己制作的镜像到仓库还得通过本地仓库的端口去推送,很不方便!

3、配置 Nginx

在部署Nginx部分,我们先需要生成自签名SSL证书,因为后面不想在docker pull的时候还要带一个端口!这里我们需要2个域名,一个用来展示nexus前台,另一个用做docker仓库,比如:

nexus前台:repo.xxx.com

docker仓库:idocker.io

生成自签名SSL证书的方法网上很多,这里推荐一个一键生成工具,大家可以尝试使用:https://github.com/Fishdrowned/ssl ,使用方法请参考作者说明。

Ps:如果你打算做外网仓库服务,那也可以去申请一个免费SSL证书,我这边是内部oa域名使用,所以只能用自签名证书了。

Nginx的规则如下:

upstream nexus_web {
    server 192.168.1.100:8181;
}

upstream nexus_docker_get {
    server 192.168.1.100:8182;
}

upstream nexus_docker_put {
    server 192.168.1.100:8183;
}

server {
    listen 80;
    listen 443 ssl;
    server_name idocker.io;
    access_log /data/wwwlogs/idocker.io.log access_log_json;

    # 证书
    ssl_certificate /data/wwwroot/ssl/out/idocker.io/idocker.io.crt;
    ssl_certificate_key /data/wwwroot/ssl/out/idocker.io/idocker.io.key.pem;
    ssl_protocols TLSv1.1 TLSv1.2;
    ssl_ciphers '!aNULL:kECDH+AESGCM:ECDH+AESGCM:RSA+AESGCM:kECDH+AES:ECDH+AES:RSA+AES:';
    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/docker/docker/issues/1486)
    chunked_transfer_encoding on;

    # 设置默认使用推送代理
    set $upstream "nexus_docker_put";
    # 当请求是GET,也就是拉取镜像的时候,这里改为拉取代理,如此便解决了拉取和推送的端口统一
    if ( $request_method ~* 'GET') {
        set $upstream "nexus_docker_get";
    }
    # 只有本地仓库才支持搜索,所以将搜索请求转发到本地仓库,否则出现500报错
    if ($request_uri ~ '/search') {
        set $upstream "nexus_docker_put";
    }

    index index.html index.htm index.php;
    location / {
        proxy_pass http://$upstream;
        proxy_set_header Host $host;
        proxy_connect_timeout 3600;
        proxy_send_timeout 3600;
        proxy_read_timeout 3600;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_buffering off;
        proxy_request_buffering off;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto http;
    }
}

server {
    listen 80;
    listen 443 ssl;
    server_name repo.xxx.com;
    index index.html index.htm index.php;
    ssl_certificate /data/wwwroot/ssl/out/repo.xxx.com/repo.xxx.com.crt;
    ssl_certificate_key /data/wwwroot/ssl/out/repo.xxx.com/repo.xxx.com.key.pem;
    ssl_protocols TLSv1.1 TLSv1.2;
    ssl_ciphers '!aNULL:kECDH+AESGCM:ECDH+AESGCM:RSA+AESGCM:kECDH+AES:ECDH+AES:RSA+AES:';
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    access_log /data/wwwlogs/repo.xxx.com.log access_log_json;
    location /download {
        root /data/wwwroot/repo.xxx.com;
    }

    location / {
        proxy_pass http://nexus_web;
        proxy_set_header Host $host;
        client_max_body_size 512m;
        proxy_connect_timeout 3600;
        proxy_send_timeout 3600;
        proxy_read_timeout 3600;
        proxy_buffering off;
        proxy_request_buffering off;
    }
}

Nginx部署完成之后,还需要将自签名的根证书(ca.crt)导入到客户端才可以正常使用,否则会报不信任错误。

在上文介绍的一键生成自签名工具中,会生成一个根证书,名称为ca.crt将这个文件上传到客户端服务器的 /etc/docker/certs.d/idocker.io 目录即可(注意目录需要创建,最后的文件夹名称和仓库域名保持一致:idocker.io)。

为了方便后面的人使用,这里将上述部署证书的过程弄成一个在线脚本,实现快速部署:

#!/bin/bash
bakfile=/tmp/hosts_$RANDOM

# 定义仓库域名和nexus前台域名
docker_domain=idocker.io
repo_domain=repo.xxx.com

# 绑定仓库域名解析
cp /etc/hosts $bakfile || exit 1
echo "/etc/hosts is bakcup to $bakfile"
if grep -q "$idocker_domain" /etc/hosts;then
    sed -i 's/.*$docker_domain/192.168.1.100 $docker_domain/g' /etc/hosts
else
    echo "192.168.1.100 $docker_domain" >> /etc/hosts
fi
echo

# 探测到仓库是否畅通
if which telnet >/dev/null 2>&1;then
    echo start trying to connect to $docker_domain:443 ...
    if ! echo "e" | telnet -e "e" $docker_domain 443 >/dev/null;then
       echo "Can not connect to $docker_domain:443,Plz check!"
    else
       echo connect success.
    fi
fi
echo

# 开始部署证书
mkdir -p /etc/docker/certs.d/$docker_domain
curl -s -o /etc/docker/certs.d/$docker_domain/ca.crt http://$repo_domain/download/cert/ca.crt
echo Docker repository init success, you need login when you want upload docker images.
echo 'Plz Run "docker login --username=idocker $docker_domain"'

脚本保存为 docker_init.sh,上传到nginx服务器的 /data/wwwroot/repo.xxx.com/download/cert 目录即可。

最终,我们可以使用如下命令行一键部署docker证书:

curl -sSL http://repo.xxx.com/download/scripts/docker_init.sh | sh -s

4、使用 Docker 私有仓库

参考资料

https://zhang.ge/5139.html

作者:Jeebiz  创建时间:2019-10-13 17:39
 更新时间:2024-01-08 11:42