容器

部署 Docker Registry 并配置认证登录

Registry私有镜像仓库


Docker Hub作为Docker默认官方公共镜像仓库,如果想要自己搭建私有镜像仓库,官方也提供了Registry镜像,使得我们搭建私有仓库变得非常简单。

所谓私有仓库,也就是在本地(局域网)搭建的一个类似公共仓库的东西,搭建好之后,我们可以将镜像提交到私有仓库中。这样我们既能使用 Docker 来运行我们的项目镜像,也避免了商业项目暴露出去的风险。

搭建镜像仓库


1、拉取私有仓库镜像

docker pull registry:2

2.创建 Docker Registry 认证文件目录 和 data目录

mkdir /mnt/registry/auth
mkdir /mnt/registry/data

3.创建 Docker Registry 认证文件

使用 Apache 的 htpasswd 来创建加密文件

yum install -y httpd-tools
htpasswd -Bbn testuser testpassword > /mnt/registry/auth/htpasswd

4.启动带认证的 Docker Registry

  • REGISTRY_AUTH=htpasswd # 以 htpasswd 的方式认证
  • REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm # 注册认证
  • REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd # 认证的用户密码
docker run -p 5001:5000 \
--restart=always \
--name registry \
-v /mnt/registry/data:/var/lib/registry \
-v /mnt/registry/auth/:/auth/ \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
-d registry:2

5.云服务器放行5001端口

6.测试私有仓库

在浏览器中输入http://<your-server-ip>:5001/v2/_catalog,将<your-server-ip>替换为你的服务器IP地址,如果能够正常访问,说明私有仓库搭建成功。

也可以在客户端查看私有镜像仓库中的所有镜像:这里返回的json数据代表仓库中暂无镜像,因为我们还没有上传任何镜像。

curl http://<your-server-ip>:5001/v2/_catalog

登录 Docker Registry


docker login ip:端口 命令的作用是让你登录到指定地址的 Docker 镜像仓库,完成身份验证后才能进行镜像的推送和拉取操作。以下是详细解释:

核心功能

  1. 身份验证:通过提供用户名和密码,向镜像仓库证明你的身份。
  2. 生成认证凭证:登录成功后,Docker 会在本地生成一个认证文件(通常位于~/.docker/config.json),其中包含加密的凭证信息。
  3. 权限访问:凭证会在后续的docker pushdocker pull操作中自动使用,允许你访问受保护的镜像仓库。

登录可以是免交互式,也可以是交互式的

  • docker login -u 用户名 -p 密码 ip:端口 # 一般不建议使用明文密码
  • docker login -u 用户名 -p ip:端口 # 不输入密码,回车后,使用交互式输入密码(输入的密码不会显示)
  • docker login ip:端口 # 不输入密码和用户名,回车后,使用交互式输入用户名和密码(输入的密码不会显示)
# docker login ip:端口
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

Docker 允许你同时登录到多个不同的镜像仓库(包括公共和私有仓库),每个仓库的认证信息会被独立存储在本地配置文件中。

你可以依次执行 docker login 命令登录不同的仓库,例如:

# 登录第一个仓库(例如私有仓库)
docker login 123.57.154.22:5001
Username: user1
Password: ********

# 登录第二个仓库(例如 Docker Hub)
docker login
Username: dockerhub_user
Password: ********

# 登录第三个仓库(例如阿里云 ACR)
docker login registry.cn-hangzhou.aliyuncs.com
Username: aliyun_user
Password: ********

认证信息存储位置: 每次登录成功后,认证信息会被加密存储在本地的 ~/.docker/config.json 文件中。例如:

{
  "auths": {
    "123.57.154.22:5001": {
      "auth": "dXNlcjE6cGFzc3dvcmQx"  // user1:password1 的 Base64 编码
    },
    "https://index.docker.io/v1/": {
      "auth": "ZG9ja2VyaHViX3VzZXI6cGFzc3dvcmQy"  // dockerhub_user:password2 的 Base64 编码
    },
    "registry.cn-hangzhou.aliyuncs.com": {
      "auth": "YWxpeXVuX3VzZXI6cGFzc3dvcmQz"  // aliyun_user:password3 的 Base64 编码
    }
  }
}

当你执行 docker push 或 docker pull 时,Docker 会根据镜像标签中的域名自动选择对应的认证信息:

# 推送到第一个仓库(123.57.154.22:5001)
docker push 123.57.154.22:5001/myimage:tag

# 推送到 Docker Hub
docker push dockerhub_user/myimage:tag

# 推送到阿里云 ACR
docker push registry.cn-hangzhou.aliyuncs.com/myrepo/myimage:tag

退出登录

# docker logout ip:端口

修改本地docker守护进程配置文件


Docker 默认要求所有远程仓库使用 HTTPS 加密连接,如果 远程仓库 没有配置 https,则本地连接远程仓库push镜像时,会报错。

例如 执行下面命令,123.57.133.22 这个dock仓库没有配置https

docker push 123.57.133.22:5001/nginx:v2

报错:

docker push 123.57.133.22:5001/nginx:v2
The push refers to repository [123.57.133.22:5001/nginx]
Get "https://123.57.133.22:5001/v2/": http: server gave HTTP response to HTTPS client

解决方法是 修改docker守护进程配置文件,如果文件不存在,直接创建个新的就行。

vim /etc/docker/daemon.json

加上下面这一句,让 Docker 认为该地址是安全的,这里的 “your-server-ip” 请替换为你的服务器外网IP地址:

{
    "insecure-registries": [
        "your-server-ip:5001"
    ]
}

“insecure-registries”:不安全的注册表,用来配置 Docker 可以通过 HTTP 而非 HTTPS 连接的不安全镜像仓库地址,即:配置可信任地址。如果配置为0.0.0.0/0,则表示信任所有地址的所有私有仓库。

例如

{
    "insecure-registries": [
        "123.57.133.22:5001"
    ]
}

保存成功后,重新加载配置并重启Docker服务:

sudo systemctl daemon-reload
sudo systemctl restart docker

Docker Registry


给镜像打上 Docker Registry 的仓库标签

docker tag <image-id> <your-server-ip>:5000/<image-name>:<image-version>
或
docker tag your-image-name:tagname your-server-ip:5000/your-image-name:tagname

其中将替换为你要上传的镜像的ID,替换为你的服务器IP地址,和分别替换为镜像的名称和版本号(标签名)。

docker tag nginx:latest 192.168.4.250:5000/nginx:v1
或
docker tag 39286ab8a5e1 192.168.4.250:5000/nginx:v1

将新打标签的镜像上传镜像到仓库

docker push <your-registry-server-ip>:5000/<your-image-name>:<tagname>
docker push ip:端口/centos:7

docker push 192.168.4.250:5000/nginx:v1

查看镜像,可以看到我们上传的 centos 7 这个镜像了

curl ip:端口/v2/_catalog -u admin
Enter host password for user 'admin':
{"repositories":["centos"]}

查看镜像包含的tag,需要先使用_catalog查看镜像的名称

curl ip:端口/v2/centos/tags/list -u admin
Enter host password for user 'admin':
{"name":"centos","tags":["8","7","7.1"]}

补充:docker tag 命令的作用


docker tag 这条命令的作用是为本地已有的 Docker 镜像添加一个新的标签(tag) ,方便后续对镜像进行识别、管理以及与私有镜像仓库进行交互。具体解释如下:

docker tag 54ae7e6e096b 123.57.154.22:5001/postgres:v1 
  • docker tag:是 Docker 提供的用于操作镜像标签的命令。
  • 54ae7e6e096b:这是本地 Docker 镜像的镜像 ID 。通过 docker images 命令可以查看到本地所有镜像及其对应的镜像 ID ,就像你提供的图片中展示的那样。镜像 ID 是 Docker 镜像的唯一标识,用于定位和区分不同的镜像。
  • 123.57.154.22:5001/postgres:v1:这是新的镜像标签,它由三部分组成:
    • 镜像仓库地址123.57.154.22:5001 ,表示该镜像准备推送到的私有镜像仓库的地址,这里的 5001 是仓库服务监听的端口。
    • 镜像名称postgres ,表明这个镜像是基于 PostgreSQL 数据库的。
    • 镜像标签v1 ,用于标识镜像的版本,方便区分同一镜像的不同迭代版本。

实际应用场景

  • 推送镜像到私有仓库:当你在本地构建或者获取到一个镜像后,比如从官方镜像仓库拉取的 PostgreSQL 镜像 ,如果想将它推送到私有镜像仓库中进行保存和共享,就需要先为它添加符合私有仓库规范的标签。添加标签后,使用 docker push 123.57.154.22:5001/postgres:v1 命令,就能把带有新标签的镜像推送到指定的私有仓库。
  • 版本管理:在开发和测试过程中,同一应用的镜像可能会有多个版本,通过不同的标签来标记不同版本,便于管理和使用。例如,开发团队可以根据开发进度和功能更新,给镜像打上不同的版本标签,像 v1 、v2 等,方便后续进行版本回退、升级等操作。

假设你本地有一个镜像,镜像 ID 为 54ae7e6e096b ,原本它可能没有合适的标签来对应私有仓库。执行 docker tag 54ae7e6e096b 123.57.154.22:5001/postgres:v1 后,再用 docker images 命令查看,就会发现除了原本镜像自带的标签外,还多了 123.57.154.22:5001/postgres:v1 这个标签,后续就能将其推送到指定私有仓库,或者在本地基于这个标签进行其他操作。

补充:docker tag执行以后,新标签的镜像id 并没有变化呢 ? 不用这个tag命令先打标签, 也可以直接push 私有仓库吗?


为什么打标签后镜像 ID 不变?

镜像 ID是 Docker 根据镜像内容(包括文件系统层、元数据等)计算的哈希值,标签只是给这个固定 ID 起的 “别名”。因此:

  • 打标签不会改变镜像内容,所以镜像 ID 不变。
  • 同一个镜像可以有多个标签(如postgres:latest123.57.154.22:5001/postgres:v1指向同一个 ID)。

不打标签能否直接 push 私有仓库?

不能直接 push,必须使用带仓库地址的标签。原因如下:

Docker push 的工作机制

docker push命令需要知道:

  • 推送到哪个仓库(通过标签中的域名 / IP: 端口指定)。
  • 镜像在仓库中的名称和版本(通过标签中的路径和标签名指定)。
docker push 123.57.154.22:5001/postgres:v1
  • 123.57.154.22:5001:目标仓库地址。
  • postgres:仓库中的镜像名称。
  • v1:版本标签。

没有标签会发生什么?

如果直接 push 镜像 ID:

docker push 54ae7e6e096b  # 错误!

Docker 会尝试推送到默认仓库(Docker Hub),但由于:

  • 你可能未登录 Docker Hub。
  • 镜像 ID 没有包含仓库路径信息。
    最终会报错:
Error: No such image: 54ae7e6e096b

正确流程示例

  • 1. 从 Docker Hub 拉取镜像
docker pull postgres:14  # 拉取带标签的镜像
  • 2. 添加私有仓库标签
docker tag postgres:14 123.57.154.22:5001/postgres:v1
  • 3. 推送到私有仓库
docker push 123.57.154.22:5001/postgres:v1

总结

  • 打标签不改变镜像 ID,因为标签只是别名。
  • 必须使用带仓库地址的标签才能 push 到私有仓库。
  • 流程顺序:拉取镜像 → 添加私有仓库标签 → push