首先需要一台能够访问外网的机器作为部署中转代理的服务器
安装docker 或podman
安装docker或podman来启动代理仓库服务
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
证书准备
不配置证书的话 拉取镜像需要配置skip verify跳过验证, 以下文章均以申请的 xxfrrvw.top
域名及证书为例
ls xxfrrvw.top/
ca_bundle.crt certificate.crt private.key
cat xxfrrvw.top/certificate.crt xxfrrvw.top/ca_bundle.crt > xxfrrvw.top/fullchain.crt
镜像仓库安装脚本
#!/bin/bash
# Configuration
listen_address=0.0.0.0
listen_port_first=5000
data_dir="/root/containers-registry-proxy"
use_tls=false
cert_path=""
key_path=""
# Array with a list of proxied container registries
registries=(
"docker.io=registry-1.docker.io"
"quay.io"
"gcr.io"
"k8s.gcr.io"
"ghcr.io"
"mcr.microsoft.com"
"registry.gitlab.com"
)
# Function to print usage
print_usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " --use-tls Enable TLS"
echo " --cert-path PATH Path to TLS certificate file"
echo " --key-path PATH Path to TLS key file"
echo " --data-dir PATH Path to data directory (default: $data_dir)"
echo " --help Display this help message"
}
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
--use-tls)
use_tls=true
shift
;;
--cert-path)
cert_path="$2"
shift 2
;;
--key-path)
key_path="$2"
shift 2
;;
--data-dir)
data_dir="$2"
shift 2
;;
--help)
print_usage
exit 0
;;
*)
echo "Unknown option: $1"
print_usage
exit 1
;;
esac
done
# Validate TLS configuration
if $use_tls; then
if [ -z "$cert_path" ] || [ -z "$key_path" ]; then
echo "Error: When using TLS, both --cert-path and --key-path must be provided."
exit 1
fi
if [ ! -f "$cert_path" ] || [ ! -f "$key_path" ]; then
echo "Error: Certificate or key file not found."
exit 1
fi
fi
# Get container engine binary
if command -v podman &>/dev/null; then
cre=podman
elif command -v docker &>/dev/null; then
cre=docker
else
>&2 printf '\n%s\n' 'Podman or Docker not installed!'
exit 1
fi
# Start Redis
mkdir -p "$data_dir/redis-data"
$cre run --restart=always --detach --quiet --name registry-cache-redis \
--publish 6379:6379 \
--volume "$data_dir/redis-data:/data" \
docker.io/redis:6 redis-server --appendonly yes >/dev/null
# Start Distribution's
for i in ${registries[@]}; do
: "${port:=$listen_port_first}"
registry="${i/=*/}"
registry_url="${i/*=/}"
mkdir -p "$data_dir/$registry"
# Check if registry is docker.io to add specific environment variables
if [ "$registry" = "docker.io" ]; then
extra_env_vars="--env REGISTRY_PROXY_USERNAME=lingdie \
--env REGISTRY_PROXY_PASSWORD=123456Yy."
else
extra_env_vars=""
fi
# Prepare TLS configuration
tls_config=""
if $use_tls; then
tls_config="--volume $cert_path:/certs/cert.pem:ro \
--volume $key_path:/certs/key.pem:ro \
--env REGISTRY_HTTP_TLS_CERTIFICATE=/certs/cert.pem \
--env REGISTRY_HTTP_TLS_KEY=/certs/key.pem"
fi
$cre run --restart=always --detach --quiet --name "registry-cache-$registry" \
--publish $port:5000 \
--env REGISTRY_HTTP_ADDR=0.0.0.0:5000 \
--env REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/cache \
--env REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR=redis \
--env REGISTRY_PROXY_REMOTEURL=https://$registry_url \
--env REGISTRY_REDIS_ADDR=$(hostname -I | cut -d' ' -f1):6379 \
--env REGISTRY_PROXY_TTL=2h \
--volume "$data_dir/$registry":/cache \
$extra_env_vars \
$tls_config \
docker.io/registry:2 >/dev/null
port=$((port+1))
done
这个脚本用于设置和运行多个容器镜像仓库的代理缓存。它支持多个常用的容器仓库,并可以选择性地启用 TLS 加密。可以看到 5000-5006 端口正常运行中,分别代表不同的仓库地址代理:
“docker.io=registry-1.docker.io” # 5000 “quay.io” # 5001 “gcr.io” # 5002 “k8s.gcr.io” # 5003 “ghcr.io” # 5004 “mcr.microsoft.com” # 5005 “registry.gitlab.com” # 5006
使用方法
- 确保你的系统上安装了 Docker 或 Podman。
- 将脚本保存为可执行文件,例如
registry-proxy.sh
。 - 根据需要修改脚本中的配置部分,特别是
registries
数组。 - 需要停止或删除这些代理容器,你需要手动使用 Docker 或 Podman 命令来完成
- 运行脚本:
./registry-proxy.sh [OPTIONS]
选项
--use-tls
: 启用 TLS 加密--cert-path PATH
: TLS 证书文件的路径--key-path PATH
: TLS 私钥文件的路径--data-dir PATH
: 数据目录的路径(默认:/root/containers-registry-proxy)--help
: 显示帮助信息
执行命令
chmod +x ./registry-proxy.sh && ./registry-proxy.sh --use-tls --cert-path $(pwd)/xxfrrvw.top/fullchain.crt --key-path $(pwd)/xxfrrvw.top/private.key --data-dir $(pwd)/registry-data
查看状态
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7f2156db9def registry:2 "/entrypoint.sh /etc…" 26 seconds ago Up 25 seconds 0.0.0.0:5006->5000/tcp, :::5006->5000/tcp registry-cache-registry.gitlab.com
6b27d1ad7cf0 registry:2 "/entrypoint.sh /etc…" 26 seconds ago Up 26 seconds 0.0.0.0:5005->5000/tcp, :::5005->5000/tcp registry-cache-mcr.microsoft.com
618d9eeee965 registry:2 "/entrypoint.sh /etc…" 26 seconds ago Up 26 seconds 0.0.0.0:5004->5000/tcp, :::5004->5000/tcp registry-cache-ghcr.io
a30afb3bf59e registry:2 "/entrypoint.sh /etc…" 27 seconds ago Up 26 seconds 0.0.0.0:5003->5000/tcp, :::5003->5000/tcp registry-cache-k8s.gcr.io
15a984c5ab4d registry:2 "/entrypoint.sh /etc…" 27 seconds ago Up 27 seconds 0.0.0.0:5002->5000/tcp, :::5002->5000/tcp registry-cache-gcr.io
4aab93c84c50 registry:2 "/entrypoint.sh /etc…" 27 seconds ago Up 27 seconds 0.0.0.0:5001->5000/tcp, :::5001->5000/tcp registry-cache-quay.io
d1bc359dc2a1 registry:2 "/entrypoint.sh /etc…" 28 seconds ago Up 27 seconds 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp registry-cache-docker.io
69874dcd1aa9 redis:6 "docker-entrypoint.s…" 34 seconds ago Up 33 seconds 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp registry-cache-redis
netstat -tuln | grep 500
tcp 0 0 0.0.0.0:5006 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:5004 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:5005 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:5002 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:5003 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:5000 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:5001 0.0.0.0:* LISTEN
tcp6 0 0 :::5006 :::* LISTEN
tcp6 0 0 :::5004 :::* LISTEN
tcp6 0 0 :::5005 :::* LISTEN
tcp6 0 0 :::5002 :::* LISTEN
tcp6 0 0 :::5003 :::* LISTEN
tcp6 0 0 :::5000 :::* LISTEN
tcp6 0 0 :::5001 :::* LISTEN
测试成功代理镜像仓库
docker pull xxfrrvw.top:5000/library/ubuntu:latest
Trying to pull xxfrrvw.top:5000/library/ubuntu:latest...
Getting image source signatures
Copying blob 9c704ecd0c69 done
Copying config 35a8880255 done
Writing manifest to image destination
Storing signatures
35a88802559dd2077e584394471ddaa1a2c5bfd16893b829ea57619301eb3908
docker pull xxfrrvw.top:5001/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
Trying to pull xxfrrvw.top:5001/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0...
Getting image source signatures
Copying blob 3572b831a7ad [--------------------------------------] 0.0b / 204.0b
Copying blob 70c24c20a569 [--------------------------------------] 0.0b / 280.0b
Copying blob c9b1b535fdd9 [--------------------------------------] 0.0b / 2.7MiB
Copying blob 7873cb07ba91 [--------------------------------------] 0.0b / 4.6MiB
Copying blob 45ba4c948320 [--------------------------------------] 0.0b / 49.4MiB
Copying blob 58acda238271 [--------------------------------------] 0.0b / 17.7MiB
配置k8s containerd代理
配置脚本 ## 非证书模式 需要修改skip_verify=true,并且https修改为http
#!/bin/bash
# 默认值
DEFAULT_CERTS_DIR="/etc/containerd/certs.d"
DEFAULT_PROXY_DOMAIN="xxfrrvw.top"
START_PORT=5000
# 解析命令行参数
while [[ $# -gt 0 ]]; do
case $1 in
--certs-dir)
CERTS_DIR="$2"
shift 2
;;
--proxy-domain)
PROXY_DOMAIN="$2"
shift 2
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
# 如果未指定,使用默认值
CERTS_DIR=${CERTS_DIR:-$DEFAULT_CERTS_DIR}
PROXY_DOMAIN=${PROXY_DOMAIN:-$DEFAULT_PROXY_DOMAIN}
# 确保目录存在
mkdir -p "$CERTS_DIR"
# 注册表列表
registries=(
"docker.io"
"gcr.io"
"ghcr.io"
"k8s.gcr.io"
"quay.io"
"registry.k8s.io"
)
# 创建配置文件
create_config() {
local registry="$1"
local port="$2"
local config_dir="$CERTS_DIR/$registry"
local config_file="$config_dir/hosts.toml"
mkdir -p "$config_dir"
cat > "$config_file" <<EOF
server = "https://$registry"
[host."https://$PROXY_DOMAIN:$port"]
capabilities = ["pull", "resolve"]
skip_verify = false
EOF
echo "Created configuration for $registry at $config_file"
}
# 为每个注册表创建配置
port=$START_PORT
for registry in "${registries[@]}"; do
create_config "$registry" "$port"
((port++))
done
echo "Configuration completed."
echo "CERTS_DIR: $CERTS_DIR"
echo "PROXY_DOMAIN: $PROXY_DOMAIN"
运行脚本配置
chmod +x configure_containerd_hosts.sh
./configure_containerd_hosts.sh --proxy-domain xxfrrvw.top