Cane's Blog

Cane

【Docker】自建 docker 仓库

354
2024-06-18

1. 搭建

NginxProxyManager

version: "3.5"
services:
  nginx:
    image: 'jc21/nginx-proxy-manager:latest'
    container_name: nginx
    ports:
      - "443:443"
      - "80:80"
      - "81:81"
    restart: always
    volumes:
      - /home/nginx/data:/data
      - /home/nginx/letsencrypt:/etc/letsencrypt
    environment:
      - TZ=Asia/Shanghai
    networks:
      - nginx
networks:
  nginx:
    name: nginx

NPM 默认的登录凭证为用户名:admin@example.com,密码:changeme

Docker 自建仓库

version: "3.5"
services:
  registry:
    container_name: docker
    image: registry:latest
    networks:
        - nginx
    environment:
      #- REGISTRY_AUTH=htpasswd  # 鉴权方式
      #- REGISTRY_AUTH_HTPASSWD_PATH=/root/auth/htpasswd  # 帐号密码
      - REGISTRY_AUTH_HTPASSWD_REALM=Auth Required  # 鉴权提示
      - REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io  # 上游源
      - REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR=inmemory # 内存缓存
    volumes:
      - /root/docker:/var/lib/registry
      #- /root/auth:/root/auth  # htpasswd 密码映射
      - /etc/localtime:/etc/localtime:ro
networks:
    nginx:
        external: true

密码生成

docker run --rm --entrypoint htpasswd httpd:2 -Bbn username password > ./auth/htpasswd

注意事项:

当不设置鉴权的时候,通过修改 /etc/docker/daemon.json && systemctl restart docker 可以实现

docker pull halohub/halo:2.19 # 从私有仓库拉取

但是当设置了鉴权,即使登录了(docker login xxx)

也必需添加私有仓库前缀才能从私有仓库拉取文件

docker pull halohub/halo:2.19 # 是从 docker 官方仓库拉取的

docker pull xxxx/halohub/halo:2.19 # 只有这样才能从私有仓库拉取

暂时没有找到原因和解决方案

配置

Docker 仓库只支持 HTTPS 访问,所以需要在域名解析指向服务器后,申请证书。在 NPM 中申请证书,普通的非通配符域名,直接使用 Let's Encrypt 申请即可!(若申请通配符证书则必须使用 DNS Challenge 方式申请)

npm申请证书.png

新建 Proxy Hosts

因为 NPM 和 Docker 仓库在同一个 Docker 网络,所以 IP 直接写 docker 就可以

npm docker.png

屏蔽其他类型操作

如果只是想作为一个代理,加速镜像的拉取的话,可以在 NginxProxyManager 配置中只允许 Get 请求

location / {
    limit_except GET {
        deny all;
    }

    proxy_pass http://docker:5000;  
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

npm高级设置.png

2. 清理缓存

时间长了,会有缓存太多的问题,可以写一个脚本定期清理缓存

清理脚本里面有重启 Docker 仓库的命令,我的路径存放位置是: /root/compose/docker.yaml

如果你修改了存放位置,修改成实际路径即可(脚本15~17行)

#!/bin/bash

THRESHOLD=$((2 * 1024 * 1024 * 1024)) # 大于 2GB 则清理
LOG_FILE="/root/script/rmDockerCache.log"

DIR_SIZE=$(du -sb /root/docker | awk '{print $1}')
DIR_SIZE_GB=$(awk "BEGIN {printf \"%.2f\", $DIR_SIZE / (1024 * 1024 * 1024)}")
CURRENT_DATE=$(date "+%Y-%m-%d %H:%M:%S")

if [ "$DIR_SIZE" -gt "$THRESHOLD" ]; then
  BEFORE_CLEAN_SIZE=$(du -sb /root/docker | awk '{print $1}')
  BEFORE_CLEAN_GB=$(awk "BEGIN {printf \"%.2f\", $BEFORE_CLEAN_SIZE / (1024 * 1024 * 1024)}")
  
  # 执行清理操作
  docker-compose -f /root/compose/docker.yaml down
  rm -rf /root/docker && mkdir /root/docker
  docker-compose -f /root/compose/docker.yaml up -d
  
  AFTER_CLEAN_SIZE=$(du -sb /root/docker | awk '{print $1}')
  AFTER_CLEAN_GB=$(awk "BEGIN {printf \"%.2f\", $AFTER_CLEAN_SIZE / (1024 * 1024 * 1024)}")
  
  echo "$CURRENT_DATE - 缓存总大小为: ${DIR_SIZE_GB}G, 清理后剩余 ${AFTER_CLEAN_GB}G" >> "$LOG_FILE"
else
  echo "$CURRENT_DATE - 缓存总大小为: ${DIR_SIZE_GB}G, 不清理" >> "$LOG_FILE"
fi

添加到 crontab 里定时执行一下,我目前设置的是每天凌晨 4 点检测一下,如果缓存到了 2个G, 就清理一下(主要是我的小主机只有 10GB 空间,其他杂七杂八的已经占了 4GB 了 ...)

crontab -e

0 4 * * * /root/script/rmDockerCache.sh

3. 使用

直接使用

对 aaa/aaa:latest 拉不下来的镜像可以采用,yourdomain.com/aaa/aaa:latest 的方式进行拉取

注意: 有些官方镜像是没有前置仓库名的,比如: python:3.10-slim ,对于这种镜像的拉取,前置仓库名带一个 library 就可以了。

docker pull yourdomain.com/library/python:3.10-slim

修改默认仓库地址

配置文件路径:/etc/docker/daemon.json (没有的话就新建一个)

{
  "registry-mirrors": ["https://xxxxx.com"]
}

然后重启服务

sudo systemctl daemon-reload
sudo systemctl restart docker