跳至主要內容

私有Docker仓库

言午日尧耳总大约 8 分钟运维视频Docker

私有Docker仓库

  • 由于众所周不知的原因,Docker国内镜像被禁用
  • 个人电脑可以使用魔法上网解决,但在多服务器的情况下不方便,提供了如下解决方案
    • 其中一台电脑设置代理(魔法上网),从Docker公共库拉取镜像(docker pull)
    • 转换镜像标签(docker tag)
    • 推送到内网私有仓库(docker push)
    • 其他内网服务器都可以从私有仓库拉取镜像使用了(docker pull)

仓库方案

魔法环境

  • 本文章使用的是"Clash",请求转发到7890端口就能魔法上网
  • 这台可上魔法环境的电脑/服务器,当做"代理节点"

配置

# 编辑Docker配置
vim /etc/docker/daemon.json

# 如下配置后,重启服务
systemctl restart docker
  • 代理配置如下
    • "127.0.0.1:7890" 为VPN代理地址,要修改为自己的代理地址
{
    "proxies": {
        "http-proxy": "http://127.0.0.1:7890",
        "https-proxy": "http://127.0.0.1:7890"
    }
}

下载镜像

  • 先从公共仓库先下载使用到的镜像
  • 以下版本是当前最新的稳定版(当前时间:2024-11-03)
docker pull registry:2.8.3
docker pull klausmeyer/docker-registry-browser:1.7.4
  • 镜像打包成文件
docker save registry:2.8.3 > registry_2.8.3.image
docker save klausmeyer/docker-registry-browser:1.7.4 > docker-registry-browser_1.7.4.image
  • 文件上传到要部署仓库的服务器
  • docker加载镜像
docker load < registry_2.8.3.image
docker load < docker-registry-browser_1.7.4.image

部署(无鉴权)

  • 部署仓库的服务器在内网中,且不会开放外网访问,可以不需要鉴权
    • 如果服务器在公网,或者会开放公网访问,看下面的有鉴权版本
  • 服务组件:registry + docker-registry-browser
  • 下面是博主的环境信息,大家根据自己的环境,替换为自己的
    • 内网IP:192.168.1.3
    • 仓库端口:8000
    • 仓库UI端口:8001

使用Docker

  • 部署仓库服务
  • 验证
    • 访问"http://IP:8000/v2/"
    • 返回"{}",则成功
# 删除下面命令的注释才能运行
docker run --name registry-server \
  --restart always \
  -p 8000:5000 \
  -v ./data:/var/lib/registry  \                # 替换为自己的持久化地址,无持久化需求去掉这个参数
  -e REGISTRY_STORAGE_DELETE_ENABLED=true \     # 是否允许删除镜像
  -d registry:2.8.3
  • 部署仓库UI
  • 验证
    • 浏览器访问"http://IP:8001"
# 删除下面命令的注释才能运行
docker run --name registry-ui \
  --restart always \
  -p 8001:8080 \
  -e DOCKER_REGISTRY_URL=http://192.168.1.3:8000/v2 \   # 仓库地址,替换为自己仓库的IP及端口号
  -e SECRET_KEY_BASE=$(openssl rand -hex 64) \          # 密钥使用"openssl rand -hex 64"生成
  -e PUBLIC_REGISTRY_URL=192.168.1.3:8000 \             # 复制PULL命令的地址,将IP改为自己的IP/域名和宿主机端口号
  -e ENABLE_DELETE_IMAGES=true \                        # 是否显示删除镜像按钮
  -d klausmeyer/docker-registry-browser:1.7.4

使用Docker Compose

  • 生成密钥
# openssl生成随机密钥
openssl rand -hex 64
# 复制打印的密钥,手动替换yaml中的"SECRET_KEY_BASE"的值
  • 创建"docker-compose.yaml"文件,内容如下
version: '1.0'

services:
  registry-server:
    container_name: registry-server
    image: registry:2.8.3
    restart: always
    ports:
      - 8000:5000
    environment:
      - REGISTRY_STORAGE_DELETE_ENABLED=true    # 是否允许删除镜像
    volumes:
      - ./data:/var/lib/registry                # 替换为自己的持久化地址,无持久化需求去掉这个参数

  retistry-ui:
    container_name: registry-ui
    image: klausmeyer/docker-registry-browser:1.7.4
    restart: always
    ports:
      - 8001:8080
    environment:
      - DOCKER_REGISTRY_URL=http://registry-server:5000/v2  # registry端口号,不是宿主机端口号,所以不要改
      - PUBLIC_REGISTRY_URL=192.168.1.3:8000                # 复制PULL命令的地址,将IP改为自己的IP/域名和宿主机端口号
      - SECRET_KEY_BASE=手动替换生成的密钥                   # 修改密钥,使用"openssl rand -hex 64"命令生成一个
      - ENABLE_DELETE_IMAGES=true                           # 是否显示删除镜像按钮

  • 启动命令
# 启动服务
docker compose -f docker-compose.yaml up -d

# 关闭服务
docker compose -f docker-compose.yaml down
  • 验证结果
    • 浏览器访问"http://IP:8001"

部署(简单鉴权)

  • 使用账号密码的简单鉴权
    • pull/push命令前,先"docker login"登录
    • 仓库UI访问需输入账号密码(配置了默认账号密码,不需要输入)
  • 在上面无鉴权版本的基础上加几个配置就能实现鉴权
  • 服务组件:registry + docker-registry-browser
  • 下面是博主的环境信息,大家根据自己的环境,替换为自己的
    • 内网IP:192.168.1.3
    • 仓库端口:8000
    • 仓库UI端口:8001

htpasswd密码文件

  • 使用htpasswd生成密码文件
htpasswd -Bbn username password > /path/to/file

# 示例
# htpasswd -Bbn xxc 123456 > ./htpasswd

使用Docker

  • 部署仓库服务
  • 验证
    • 访问"http://IP:8000/v2/"
    • 返回"{}",则成功
# 删除下面命令的注释才能运行
docker run --name registry-server \
  --restart always \
  -p 8000:5000 \
  -v ./data:/var/lib/registry  \                # 替换为自己的持久化地址,无持久化需求去掉这个参数
  -v ./htpasswd:/auth/htpasswd \                # 替换为自己的htpasswd文件(上个步骤生成)
  -e REGISTRY_STORAGE_DELETE_ENABLED=true \     # 是否允许删除镜像
  -e REGISTRY_AUTH=htpasswd \
  -e REGISTRY_AUTH_HTPASSWD_REALM=basic-realm \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  -d registry:2.8.3
  • 部署仓库UI
  • 验证
    • 浏览器访问"http://IP:8001"
    • 如果设置了"BASIC_AUTH_USER"和"BASIC_AUTH_PASSWORD"参数,则与无鉴权感觉没有差别
    • 如果未设置了,则需要输入账号密码才能查看仓库
# 删除下面命令的注释才能运行
docker run --name registry-ui \
  --restart always \
  -p 8001:8080 \
  -e DOCKER_REGISTRY_URL=http://192.168.1.3:8000/v2 \   # 仓库地址,替换为自己仓库的IP及端口号
  -e SECRET_KEY_BASE=$(openssl rand -hex 64) \          # 密钥使用"openssl rand -hex 64"生成
  -e PUBLIC_REGISTRY_URL=192.168.1.3:8000 \             # 复制PULL命令的地址,将IP改为自己的IP/域名和宿主机端口号
  -e ENABLE_DELETE_IMAGES=true \                        # 是否显示删除镜像按钮
  -e BASIC_AUTH_USER=xxc \                              # 配置默认账号(htpasswd生成的),删除该参数则需要手动输入账号
  -e BASIC_AUTH_PASSWORD=123456 \                       # 配置默认密码(htpasswd生成的),删除该参数则需要手动输入密码
  -d klausmeyer/docker-registry-browser:1.7.4

使用Docker Compose

  • 生成密钥
# openssl生成随机密钥
openssl rand -hex 64
# 复制打印的密钥,手动替换yaml中的"SECRET_KEY_BASE"的值
  • 创建"docker-compose.yaml",当前目录结构如下
registry
    ├─ htpasswd
    └─ docker-compose.yml
  • "docker-compose.yaml"内容如下
version: '2.0'

services:
  registry-server:
    container_name: registry-server
    image: registry:2.8.3
    restart: always
    ports:
      - 8000:5000
    environment:
      - REGISTRY_STORAGE_DELETE_ENABLED=true    # 是否允许删除镜像
      - REGISTRY_AUTH=htpasswd
      - REGISTRY_AUTH_HTPASSWD_REALM=basic-realm
      - REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
    volumes:
      - ./data:/var/lib/registry                # 替换为自己的持久化地址,无持久化需求去掉这个参数
      - ./htpasswd:/auth/htpasswd               # 挂载htpasswd命令生成的密码文件

  retistry-ui:
    container_name: registry-ui
    image: klausmeyer/docker-registry-browser:1.7.4
    restart: always
    ports:
      - 8001:8080
    environment:
      - DOCKER_REGISTRY_URL=http://registry-server:5000/v2  # registry端口号,不是宿主机端口号,所以不要改
      - PUBLIC_REGISTRY_URL=192.168.1.3:8000                # 复制PULL命令的地址,将IP改为自己的IP/域名和宿主机端口号
      - SECRET_KEY_BASE=手动替换生成的密钥                   # 修改密钥,使用"openssl rand -hex 64"命令生成一个
      - ENABLE_DELETE_IMAGES=true                           # 是否显示删除镜像按钮
      - BASIC_AUTH_USER=xxc                                 # 配置默认账号(htpasswd生成的),删除该参数则需要手动输入
      - BASIC_AUTH_PASSWORD=123456                          # 配置默认密码(htpasswd生成的),删除该参数则需要手动输入

  • 启动命令
# 启动服务
docker compose -f docker-compose.yaml up -d

# 关闭服务
docker compose -f docker-compose.yaml down
  • 验证结果
    • 浏览器访问"http://IP:8001"

代理节点

配置

  • 该节点使用了代理,私有仓库IP被代理导致无法访问,所以禁用部分IP的代理
  • 修改配置
    • 增加 "proxies.no-proxy" 禁止代理私有仓库的IP
    • 增加 "insecure-registries" ,将私有仓库地址添加到信任列表
  • 重启Docker
{
    "proxies": {
        "http-proxy": "http://127.0.0.1:7890",
        "https-proxy": "http://127.0.0.1:7890",
        "no-proxy": "localhost,127.0.0.1,192.168.1.3"
    },
    "insecure-registries": [
        "192.168.1.3:8000"
    ]
}
# 编辑Docker配置
vim /etc/docker/daemon.json

# 如下配置后,重启服务
systemctl restart docker

使用

# 从公共库拉取镜像
docker pull alpine:latest

# 修改Tag
docker tag alpine:latest 192.168.1.3:8000/alpine:latest

# 登录(有鉴权的话)
docker login -u username -p password 192.168.1.3:8000

# 镜像推送到私有仓库
docker push 192.168.1.3:8000/alpine:latest

服务器节点

允许私有仓库

  • 增加 "insecure-registries" ,将私有仓库地址添加到信任列表
{
    "insecure-registries": [
        "192.168.1.3:8000"
    ]
}
# 编辑Docker配置
vim /etc/docker/daemon.json

# 如下配置后,重启服务
systemctl restart docker

使用

  • 运行直接带上私有仓库地址
    • 镜像必须提前使用代理节点上传
# 登录(有鉴权的话)
docker login -u username -p password 192.168.1.3:8000

# 拉取镜像,命令可以从UI界面复制
docker pull 192.168.1.3:8000/alpine:latest

# 使用(和正常命令一样使用,只是前面加了私有可的地址和端口号)
docker run -d 192.168.1.3:8000/alpine:latest
  • 如果是Dockerfile打包镜像
  • tag名称加上私有仓库地址
# 在执行build命令
docker build -t 192.168.1.3:8000/xxx:latest .

# 登录(有鉴权的话)
docker login -u username -p password 192.168.1.3:8000

# 上传私有仓库
docker push 192.168.1.3:8000/xxx:latest

常见异常

EOF

  • 原因:仓库地址错误
  • 解决方法:确认仓库IP及端口号是否正确
# 推送私有仓库镜像
docker push 192.168.1.3:8000/alpine:latest
# The push refers to repository [192.168.1.5:8000/alpine]
# Get "https://192.168.1.5:8000/v2/": EOF

server gave HTTP response to HTTPS client

  • 原因:未设置私有仓库
  • 解决方法:修改/etc/docker/daemon.json,将仓库地址加入信任列表
docker push 192.168.1.3:8000/alpine:latest
# 报错如下
The push refers to repository [192.168.1.3:8000/alpine]
Get "https://192.168.1.3:8000/v2/": http: server gave HTTP response to HTTPS client

no basic auth credentials

  • 原因:未登录
  • 解决方法:使用"docker login"登录
docker push 192.168.1.3:8000/alpine:latest
# 报错如下
The push refers to repository [192.168.1.3:8000/alpine]
63ca1fbb43ae: Preparing 
no basic auth credentials

参考文章

  • https://baijiahao.baidu.com/s?id=1803388229356954283
  • https://www.cnblogs.com/netcore3/p/16982828.html
  • https://www.cnblogs.com/chen2ha/p/14787695.html
  • https://developer.aliyun.com/article/1094892
上次编辑于:
贡献者: XuXiaoCong