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 镜像仓库,完成身份验证后才能进行镜像的推送和拉取操作。以下是详细解释:
核心功能
- 身份验证:通过提供用户名和密码,向镜像仓库证明你的身份。
- 生成认证凭证:登录成功后,Docker 会在本地生成一个认证文件(通常位于
~/.docker/config.json
),其中包含加密的凭证信息。 - 权限访问:凭证会在后续的
docker push
或docker 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
后,再用
:5001/postgres:v1123.57.154.22
docker images
命令查看,就会发现除了原本镜像自带的标签外,还多了
这个标签,后续就能将其推送到指定私有仓库,或者在本地基于这个标签进行其他操作。
:5001/postgres:v1123.57.154.22
补充:docker tag
执行以后,新标签的镜像id 并没有变化呢 ? 不用这个tag命令先打标签, 也可以直接push 私有仓库吗?
为什么打标签后镜像 ID 不变?
镜像 ID是 Docker 根据镜像内容(包括文件系统层、元数据等)计算的哈希值,标签只是给这个固定 ID 起的 “别名”。因此:
- 打标签不会改变镜像内容,所以镜像 ID 不变。
- 同一个镜像可以有多个标签(如
postgres:latest
和
指向同一个 ID)。
:5001/postgres:v1123.57.154.22
不打标签能否直接 push 私有仓库?
不能直接 push,必须使用带仓库地址的标签。原因如下:
Docker push 的工作机制
docker push
命令需要知道:
- 推送到哪个仓库(通过标签中的域名 / IP: 端口指定)。
- 镜像在仓库中的名称和版本(通过标签中的路径和标签名指定)。
docker push 123.57.154.22:5001/postgres:v1
:目标仓库地址。
:5001123.57.154.22
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。