registry

有些时候我们需要在服务器运行docker镜像,可以选择在服务器上配置科学上网,也可以选择自己搭建镜像源。

如果自己开发的镜像体积较大且频繁更新,使用自建镜像源可以提高速度,以及节省科学上网的费用。

搭建镜像源使用docker和podman都可以做到,本文以podman为例。

需要先在服务器安装podman,并在供应商处以及firewalld打开想要搭建镜像源的端口,使其允许外部访问。

获取 registry 镜像

自己电脑打开科学上网,然后:

docker pull registry:2
  • 自己电脑上:docker save registry:2 -o registry.tar
  • scp 到服务器
  • 服务器上:podman load -i registry.tar

启动容器

podman run -d \
  --name registry \
  -p 127.0.0.1:15000:5000 \
  -v ~/registry/data:/var/lib/registry:Z \
  -v ~/registry/auth:/auth:Z \
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
  registry:2
  • –name: 指定容器名称
  • -p: 相当于--publish,端口映射
    • 127.0.0.1: 只接受本地的连接
    • 第一个 15000: 宿主机端口(可以选择不使用默认端口)
    • 第二个 5000: 容器内端口
  • -v: 相当于--volumn,挂载卷,指定容器内的特定目录使用宿主机目录,持久化数据
    • -v ~/registry/data:/var/lib/registry:Z
      • ~/registry/data: 宿主机目录(镜像实际存储位置)
      • /var/lib/registry: 容器内目录(镜像默认存储位置)
      • 结尾的:Z: SELinux 标签,让容器可以读写该目录(Podman/Docker 的 SELinux 安全策略)
    • -v ~/registry/auth:/auth:Z
      • 挂载认证文件目录,包含htpasswd用户名密码文件
  • -e: 相当于--env
    • “REGISTRY_AUTH=htpasswd”,设置身份认证模式为htpasswd
    • “REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm”,设置认证域名称,弹窗提示时会显示
    • “REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd”,指定htpasswd文件在容器内的路径

设置密码

如果没有htpasswd命令,安装 apache 工具包,然后使用其中的 htpasswd 工具追加文件到之前挂载的密码文件

# Debian/Ubuntu
sudo apt install apache2-utils

# CentOS/RHEL/Fedora
sudo dnf install httpd-tools

# 生成
htpasswd -Bbn admin 你的强密码 > ~/registry/auth/htpasswd

验证

curl -u admin:正确密码 http://127.0.0.1:5000/v2/_catalog  # 成功 200
curl -u admin:错密码 http://127.0.0.1:5000/v2/_catalog  # 失败 401

登录

如果是 http 访问,必须显式设置不安全的 registry 列表,否则无法登录

docker desktop

设置-Docker Engine 中添加:

{
"insecure-registries": ["IP:端口"]
}

linux

vim /etc/containers/registries.conf

[[registry]]
location = "your-registry.example.com:5000"
insecure = true

登录

docker login IP:port

然后就可以进行 push 和 pull 操作了

登录状态丢失

在一些老版的 podman 中,登录状态可能会过段时间就掉了

echo 'export REGISTRY_AUTH_FILE="$HOME/.config/containers/auth.json"' >> ~/.bashrc

使用环境变量指定登录状态存储位置,然后 source .bashrc,并重新登录,检查那个文件auth.json是否出现在指定位置

坑注意

  • 推送进去的镜像并不能用 podman image ls 看到,因为它们存在于名为 registry 的容器中,与外面这个 podman 客户端是分开的
  • 如果要推送镜像,镜像必须命名为 host:port/namespace/image:tag,这是规定,docker 会根据镜像里的 host 来决定往哪推,否则就推去 docker.io 了
  • 多次推送同一名称的镜像,不会在 registry 产生 dangling 镜像,但会残留不再引用的 blob,可以用以下命令运行 GC
    podman exec -it registry /bin/registry garbage-collect /etc/docker/registry/config.yml
    

完成

接下来就可以:

  • 把要运行的镜像pull到自己电脑
  • push到自建镜像源
  • 登上服务器从镜像源pull使用(监听新版镜像=>拉取=>重启容器这个过程可以自动化,使用新版podman或者watchtower工具都行)

或者如果镜像是自己开发的,可以搭建自定义的CICD工作流

更多推荐