一、配置软件仓库并安装docker-ce







cpp
#利用阿里云部署软件仓库
[root@docker-node1 ~]# cat > /etc/yum.repos.d/docker.repo << EOF
[docker]
name = docker
baseurl = https://mirrors.aliyun.com/docker-ce/linux/rhel/9.6/x86_64/stable/
gpgcheck = 0
EOF
[root@docker-node1 ~]# dnf makecache
正在更新 Subscription Management 软件仓库。
无法读取客户身份
本系统尚未在权利服务器中注册。可使用 "rhc" 或 "subscription-manager" 进行注册。
docker 7.3 kB/s | 46 kB 00:06
AppStream 3.1 MB/s | 3.2 kB 00:00
BaseOS 2.7 MB/s | 2.7 kB 00:00
元数据缓存已建立。
[root@docker-node1 ~]# dnf search docker
正在更新 Subscription Management 软件仓库。
无法读取客户身份
本系统尚未在权利服务器中注册。可使用 "rhc" 或 "subscription-manager" 进行注册。
上次元数据过期检查:0:00:13 前,执行于 2026年03月14日 星期六 14时55分07秒。
==================================== 名称 和 概况 匹配:docker =====================================
docker-buildx-plugin.x86_64 : Docker Buildx plugin for the Docker CLI
docker-ce-rootless-extras.x86_64 : Rootless support for Docker
docker-compose-plugin.x86_64 : Docker Compose plugin for the Docker CLI
docker-model-plugin.x86_64 : Docker Model Runner plugin for the Docker CLI
pcp-pmda-docker.x86_64 : Performance Co-Pilot (PCP) metrics from the Docker daemon
podman-docker.noarch : Emulate Docker CLI using podman
======================================== 名称 匹配:docker =========================================
docker-ce.x86_64 : The open-source application container engine
docker-ce-cli.x86_64 : The open-source application container engine
[root@docker-node1 ~]# dnf install docker-ce -y
[root@docker-node1 ~]# vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true
[root@docker-node1 ~]# echo br_netfilter > /etc/modules-load.d/docker_mod.conf
[root@docker-node1 ~]# modprobe -a br_netfilter
[root@docker-node1 ~]# cat > /etc/sysctl.d/docker.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
[root@docker-node1 ~]# sysctl --system
[root@docker-node1 ~]# systemctl enable --now docker
二、docker的常规使用方法
1.配置docker加速器


cpp
[root@docker-node1 ~]# cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://docker.1ms.run"]
}
EOF
[root@docker-node1 ~]# systemctl restart docker
[root@docker-node1 ~]# docker info
Registry Mirrors:
https://docker.1ms.run/
2.docker核心常用命令
Docker 命令可分为环境管理 、镜像管理 、容器管理 、网络 / 数据卷四大类,以下是高频使用的命令及实操示例,所有示例均可直接在配置好的环境中执行。
🔹 第一类:Docker 环境管理(基础状态 / 信息)
用于检查 Docker 服务状态、版本、配置等,是日常排障的基础。
| 命令 | 作用 | 示例 |
|---|---|---|
docker version |
查看 Docker 客户端 / 服务端版本 | docker version(输出 Client 和 Server 版本、内核等信息) |
docker info |
查看 Docker 系统详细信息(镜像源、驱动、容器数等) | docker info(验证镜像加速器、存储驱动、内核参数等) |
systemctl status docker |
查看 Docker 服务状态(Linux 系统) | systemctl status docker(确认服务是否 running) |
docker system df |
查看 Docker 磁盘使用情况(镜像 / 容器 / 卷占用) | docker system df(类似 df -h,显示各资源占用) |
docker system prune |
清理无用资源(停止的容器、悬空镜像、未使用网络) | docker system prune -f(-f 免确认,谨慎使用) |
🔹 第二类:镜像管理(拉取 / 查看 / 构建 / 删除)
镜像是容器的模板,核心操作围绕镜像的获取、管理、清理。
| 命令 | 作用 | 示例 |
|---|---|---|
docker pull |
拉取镜像(从仓库 / 加速器) | docker pull nginx:1.25(拉取 nginx 1.25 版本,不加 tag 则拉 latest)docker pull redis(拉取 redis 最新版) |
docker images |
查看本地已下载的镜像 | docker images(列出所有镜像的名称、标签、ID、大小)docker images -q(仅输出镜像 ID,用于批量操作) |
docker search |
搜索镜像(仓库中的镜像) | docker search mysql(搜索 mysql 相关镜像)docker search --filter=stars=1000 mysql(筛选星数≥1000 的镜像) |
docker rmi |
删除本地镜像 | docker rmi nginx:1.25(删除指定标签的镜像)docker rmi -f $(docker images -q)(强制删除所有本地镜像,-f 强制) |
docker build |
从 Dockerfile 构建镜像 | docker build -t my-nginx:v1 .(-t 打标签,. 表示 Dockerfile 所在目录) |
docker commit |
从修改后的容器创建新镜像(内容提交) | docker commit -a "user@example.com" -m "add file" test busybox-file:lates(-a 指定作者信息,-m 添加提交备注信息,test 是容器名,busybox-file:latest 是新镜像名 + 标签) |
docker save |
导出镜像为压缩包(备份) | docker save -o nginx-1.25.tar nginx:1.25(-o 指定输出文件) |
docker load |
导入镜像压缩包(恢复) | docker load -i nginx-1.25.tar(-i 指定导入文件) |
🔹 第三类:容器管理(创建 / 启动 / 停止 / 进入 / 删除)
容器是镜像的运行实例,这是 Docker 最核心的操作模块。
1. 容器创建 / 启动(高频)
| 命令 | 示例 | 关键参数说明 |
|---|---|---|
docker run(创建 + 启动) |
docker run -d --name my-nginx -p 80:8080 nginx:1.25 |
-d:后台运行容器,脱离终端--name:指定容器名(my-nginx)-p:端口映射(宿主机 80: 容器 8080) |
docker run -it --rm centos:7 /bin/bash |
-it:-i(交互式,保持 STDIN 打开)+ -t(分配伪终端),进入交互式终端 --rm:容器停止后自动删除 |
|
docker run -d --network my-net --name web -v /host/data:/container/data nginx:1.25 |
--network:指定容器使用的自定义网络(my-net)-v:数据卷挂载(宿主机目录:容器目录),持久化数据-e MYSQL_ROOT_PASSWORD=123456:设置环境变量(示例拓展) |
|
docker start(启动已停止容器) |
docker start my-nginx(按容器名启动)docker start abc123(按容器 ID 启动) |
- |
docker restart(重启容器) |
docker restart my-nginx |
- |
2. 容器状态查看 / 日志
| 命令 | 示例 | 作用 |
|---|---|---|
docker ps |
docker ps(查看运行中的容器) docker ps -a(查看所有容器,包括停止的) |
列出容器 ID、名称、状态、端口等 |
docker logs |
docker logs my-nginx(查看日志) docker logs -f my-nginx(实时跟踪日志,类似 tail -f) |
查看容器运行日志,排障必备 |
docker inspect |
docker inspect my-nginx |
查看容器 / 镜像的详细配置(JSON 格式) |
3. 进入容器 / 执行命令
| 命令 | 示例 | 适用场景 |
|---|---|---|
docker exec(推荐) |
docker exec -it my-nginx /bin/bash |
进入运行中的容器,不中断容器进程 |
docker exec my-nginx ls /usr/share/nginx/html |
在容器中执行单条命令(无需进入) | |
docker attach |
docker attach my-nginx |
进入容器的主进程终端(退出会停止容器,慎用) |
| #若进入到容器中,按<ctrl>+<d>退出并停止容器,按<ctrl>+<p>+<q>退出但不停止容器 |
4. 容器停止 / 删除
| 命令 | 示例 | 说明 |
|---|---|---|
docker stop |
docker stop my-nginx(停止单个容器)docker stop $(docker ps -q)(停止所有运行中的容器) |
优雅停止容器(发送 SIGTERM 信号) |
docker kill |
docker kill my-nginx 使用特殊信号的用法:docker kill -s <信号名/信号编号> <容器名/ID> |
强制停止容器(发送 SIGKILL 信号,紧急情况用) |
docker rm |
docker rm my-nginx(删除已停止容器)docker rm -f my-nginx(强制删除运行中的容器)docker rm -f $(docker ps -aq)(删除所有容器) |
- |
5. 容器文件复制
| 命令 | 示例 | 作用 |
|---|---|---|
docker cp |
docker cp test:/root/file /mnt(容器→宿主机) |
跨宿主机 / 容器复制文件 / 目录 |
docker cp /tmp/test.txt test:/root/(宿主机→容器) |
- | |
docker cp test:/root/data /mnt/(复制目录) |
复制整个目录(无需额外参数) |
🔹 第四类:网络 / 数据卷管理(进阶)
用于容器网络配置、数据持久化。
| 命令 | 作用 | 示例 |
|---|---|---|
docker network |
管理 Docker 网络 | docker network create my-network(创建自定义网络)docker network ls(查看所有网络)docker run --network my-network -d nginx(容器加入自定义网络) |
docker volume |
管理数据卷(持久化数据) | docker volume create my-volume(创建数据卷)docker volume ls(查看数据卷)docker run -v my-volume:/data -d mysql(挂载数据卷到容器) |
三、docker镜像构建
通过 Dockerfile 进行构建 ,使用 docker build -t 镜像名:标签 . 命令 ,必须编写 Dockerfile这个文件,上面命令的 . 代表使用当前目录下的Dockerfile文件中的参数进行docker镜像的构建。
下面来熟悉一下镜像构建要用到的参数。
Dockerfile 核心指令大全
| 指令 | 作用 | 示例写法 | 实际效果解释 |
|---|---|---|---|
| FROM | 指定基础镜像(必须第一条) | FROM busybox:latest | 基于 busybox 最新版构建镜像,所有层都依赖这个基础镜像 |
| LABEL | 添加镜像元数据(作者、说明等) | LABEL Creater=lee | 给镜像打标签,可通过 docker inspect 查看,不占磁盘空间 |
| MAINTAINER | 声明作者(已废弃) | MAINTAINER lee@timinglee.org | 旧版用法,现在推荐用 LABEL author=xxx |
| COPY | 把宿主机文件复制到镜像 | COPY timinglee /root | 将当前目录下的 timinglee 文件复制到镜像内 /root 下,不解压 |
| ADD | 复制文件 + 自动解压 + 支持 URL | ADD bin.tar.gz /mnt | 复制并自动解压压缩包到 /mnt;也支持下载网络文件 |
| ENV | 设置容器环境变量 | ENV NAME=timinglee | 容器内可直接用 $NAME,构建阶段 RUN/CMD 也能识别 |
| RUN | 构建镜像时执行命令 | RUN touch /root/$NAME | 构建时创建 /root/timinglee 文件,结果会打包进镜像 |
| EXPOSE | 声明容器要暴露的端口 | EXPOSE 8080 | 仅声明容器会用 8080 端口,不会自动映射,需配合 -p 使用 |
| VOLUME | 声明匿名数据卷 | VOLUME "/mnt" | 容器启动时自动挂载匿名卷到 /mnt,宿主机 /var/lib/docker/volumes 下可见,数据持久化 |
| WORKDIR | 设置工作目录(相当于 cd) | WORKDIR "/mnt" | 后续 RUN/CMD/ENTRYPOINT 都在此目录执行;容器进入时默认就在这里 |
| CMD | 容器启动默认命令(可被覆盖) | CMD ["/bin/sh","-c","echo $NAME"] | 启动容器自动执行 echo $NAME;如果 docker run 后面跟命令,会覆盖 CMD |
| ENTRYPOINT | 容器入口命令(不会被覆盖) | ENTRYPOINT echo $NAME | 启动容器一定执行此命令;run 后面跟的内容会作为参数传给它,不会替换它 |
易混指令对比(重点)
1. COPY vs ADD
| 指令 | 复制本地文件 | 自动解压 tar.gz | 支持网络 URL | 推荐场景 |
|---|---|---|---|---|
| COPY | ✅ | ❌ | ❌ | 普通文件复制(安全、清晰) |
| ADD | ✅ | ✅ | ✅ | 需要解压或下载文件时 |
2. CMD vs ENTRYPOINT(必考)
| 指令 | 执行时机 | docker run 带命令 | 典型用途 |
|---|---|---|---|
| CMD | 容器启动 | 会被覆盖 | 设置默认启动命令 |
| ENTRYPOINT | 容器启动 | 不会被覆盖,只当参数 | 固定容器主程序 |
实操效果验证
docker run --rm test→ 执行 CMD/ENTRYPOINT 命令docker run --rm test echo haha- CMD:会变成执行
echo haha,原 CMD 被覆盖 - ENTRYPOINT:仍然执行原命令,
echo haha变成参数传给它
- CMD:会变成执行
3. RUN vs CMD / ENTRYPOINT
- RUN:构建镜像时执行(只执行一次,写进镜像层)
- CMD / ENTRYPOINT:容器启动时执行(每次 run 都跑)
关键效果总结
-
VOLUME "/mnt"→ 自动在宿主机生成匿名卷,宿主机写文件容器里立刻可见,实现持久化。 -
WORKDIR /mnt→ 进入容器直接就在/mnt目录,不用再 cd。 -
ADD 压缩包会自动解压,COPY只复制不解压。 -
EXPOSE 8080只是声明,是端口暴露,不是端口映射,真正映射要用-p 主机端口:8080。 -
ENV NAME=xxx整个 Dockerfile 后续都能用$NAME。
四、构建centos可用仓库





因为centos7的官方软件仓库停止更新,所以我们可以自己去阿里云镜像站复制CentOS7 阿里云源的地址进行构建一个软件仓库进行使用,可以看到能够成功安装gcc。
五、镜像构建的优化方案
方法一:缩减镜像层
优化前:

优化后:

例如:上面RUN里面的命令可以写成很多个RUN分别执行,但现在把编译、安装、清理写在同一条 RUN,减少层,就会减少镜像的大小。

webserver:v1是使用优化前的Dockerfile文件创建的,而webserver:v2是使用优化后的Dockerfile文件创建的,可以看到减少镜像层后,构建的镜像大小也变小了。
方法二:多阶段构建


可以看到用多阶段构建的webserver:v3的体积更小了。
方法三:使用最精简镜像
这是生产环境最顶级的镜像精简方案 ,用的就是 Google distroless 极致最小化构建。
使用google提供的最精简镜像
**下载地址:**https://github.com/GoogleContainerTools/distroless
下载镜像:
docker pull gcr.io/distroless/base


1、这个 Dockerfile 到底在做什么?
它是标准的「多阶段 + 超精简 distroless 镜像」构建 ,目标:只保留 Nginx 能运行的最小内容,删掉所有多余文件!
2、Dockerfile逐行解释
# 第一阶段:用官方 nginx 镜像当「依赖提取机」
FROM nginx:1.23 AS base
# 时区参数(可选)
ARG TIME_ZONE
# 核心:把 Nginx 运行需要的 所有文件、库、配置 复制到 /opt
RUN mkdir -p /opt/var/cache/nginx && \
cp -a --parents /usr/lib/nginx /opt && \ # nginx 模块
cp -a --parents /usr/share/nginx /opt && \ # 页面文件
cp -a --parents /var/log/nginx /opt && \ # 日志
cp -aL --parents /var/run /opt && \ # 进程文件
cp -a --parents /etc/nginx /opt && \ # 配置
cp -a --parents /etc/passwd /opt && \ # 用户
cp -a --parents /etc/group /opt && \ # 用户组
cp -a --parents /usr/sbin/nginx /opt && \ # 主程序
cp -a --parents /usr/sbin/nginx-debug /opt && \
cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \ # 系统加载器
cp -a --parents /usr/lib/x86_64-linux-gnu/libpcre* /opt && \ # 正则库
cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \ # 压缩库
cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \ # C标准库
cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \ # 动态加载
cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \ # 线程库
cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \ # 加密库
cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \ # SSL
cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \ # 加密
cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime # 时区
# 第二阶段:使用 Google 最精简镜像(空系统,无shell、无命令)
FROM gcr.io/distroless/base-debian11
# 只把刚才提取的 /opt 下的最小依赖复制进去
COPY --from=base /opt /
EXPOSE 80 443
ENTRYPOINT ["nginx", "-g", "daemon off;"] # 让 Nginx 在 Docker 容器中【前台运行】,保证容器不退出。
3、核心原理(最重要)
(1) 第一阶段:nginx:1.23
作用:提取 Nginx 运行必需的文件 + 所有依赖库不是为了运行,只是当 "材料库"。
(2)第二阶段:gcr.io/distroless/base-debian11
Google 官方最安全、最小的空镜像
- 没有 bash
- 没有 yum /apt
- 没有任何命令
- 没有多余文件
- 只有 linux 最小运行环境
(3)最终镜像里有什么?
只有:nginx 二进制 + 依赖库 + 配置 = 极小体积 + 极高安全
4、这个镜像的优势(生产环境最强)
| 项目 | 效果 |
|---|---|
| 大小 | 仅 30~40MB |
| 安全 | 无法进入容器、无法执行命令、攻击面几乎为 0 |
| 速度 | 启动极快、拉取极快 |
| 干净 | 无冗余文件、无缓存、无编译工具 |

可以看到使用最精简镜像构建的webserver:v4的镜像体积已经变得很小。
六、Docker仓库的工作原理
Docker 仓库(Registry)是Docker 镜像的集中存储与分发服务 ,核心作用是实现镜像的上传(push)、下载(pull)和管理,是 Docker 镜像生命周期中「存储 - 分发」的核心环节,Docker Hub、本地私有 registry、阿里云镜像仓库等均遵循统一的Registry V2 核心协议 (目前主流版本,替代老旧的 V1 协议),工作原理可从核心架构、镜像存储、推拉镜像流程、核心组件交互四方面拆解,同时区分公共仓库(如 Docker Hub)和私有仓库(如本地 registry)的差异适配。
1、Docker 仓库的核心架构(Registry V2 标准)
无论公共还是私有仓库,均采用客户端 - 服务端(C/S)架构 ,且服务端遵循标准化设计,分为核心层 和扩展层,轻量私有仓库(如官方 registry)仅实现核心层,公共仓库(如 Docker Hub)在核心层基础上增加权限、计费、镜像扫描等扩展功能。
1. 客户端层
即本地 Docker Daemon(Docker 守护进程),负责与仓库服务端通信,处理镜像的分层打包、标签管理、请求发送、数据校验,是用户操作(docker pull/push/tag)的实际执行者,无需单独安装其他组件。
2. 服务端层(Registry 核心)
核心为标准化的 Registry 服务端程序(如官方 registry 镜像、Harbor),包含 3 个核心模块,所有镜像操作均基于这 3 个模块完成:
- 索引模块(Index) :负责镜像元数据管理,包括镜像名、标签、分层 ID、作者、创建时间、权限控制等,不存储实际镜像文件,仅存储「镜像分层与标签的映射关系」,相当于仓库的「目录 / 索引表」;
- 存储模块(Storage) :负责实际镜像分层文件的存储,Docker 镜像采用「分层存储」机制,仓库仅存储各分层的二进制文件(以 sha256 哈希值命名,唯一标识),支持本地文件、云存储(S3/OSS)等多种存储方式;
- API 接口层 :基于 HTTP/HTTPS 提供标准化的 RESTful API,是客户端与服务端的通信桥梁,所有 docker pull/push 操作最终都会转化为对 API 接口的调用(如
/v2/_catalog查看仓库镜像、/v2/镜像名/blobs/sha256:xxx拉取镜像分层)。
2、Docker 镜像的「分层存储」是仓库工作的基础
Docker 仓库的所有操作均基于镜像分层机制,这是仓库能实现「增量传输、高效存储、共享分层」的核心原因,也是理解仓库工作原理的关键:
- 镜像分层 :一个 Docker 镜像由多个只读层(Layer) 组成,每层对应 Dockerfile 中的一条指令(如 FROM、RUN、COPY),每层有唯一的sha256 哈希值,仓库以「分层」为单位存储和传输镜像,而非整包镜像;
- 分层共享 :不同镜像若包含相同的分层(如多个镜像均基于 alpine:3.19 构建),仓库仅存储该分层一次,所有镜像共享此分层,大幅节省存储资源;
- 增量传输 :执行 docker pull/push 时,仓库会先对比「本地镜像分层的 sha256 哈希值」与「服务端分层的哈希值」,仅传输本地缺失 / 不一致的分层,而非整个镜像,大幅提升传输效率(比如本地已有基础层,仅拉取业务层即可);
- 标签映射 :镜像的「标签(Tag)」(如 v4、latest)并非独立镜像,而是指向某一组分层哈希值的「别名 / 指针」 ,由仓库的索引模块管理,比如
webserver:v4实际指向一组分层的 sha256 哈希值组合。
3、Docker 仓库核心操作:拉取(pull)/ 推送(push)镜像完整流程
仓库中的三个角色:
index docker 索引服务,负责并维护有关用户帐户、镜像的校验以及公共命名空间的信息。
registry docker 仓库,是镜像和图表的仓库,它不具有本地数据库以及不提供用户认证,通过 Index
Auth service 的 Token 的方式进行认证
Registry Client Docker 充当 registry 客户端来维护推送和拉取,以及客户端的授权
以本地私有 registry(172.25.254.100:5000) 为例,结合 Docker Hub 的差异补充,拆解最核心的 pull/push 流程,所有操作均由Docker Daemon 自动完成,用户仅需执行命令。
1. 推送(docker push):本地镜像 → 仓库服务端

镜像上传的步骤:
1.client向index发送上传请求并完成用户认证
2.index会发方token给client来证明client的合法性
3.client携带index提供的token连接Registry
4.Registry向index合适token的合法性
5.index证实token的合法性
6.Registry开始接收客户端上传过来的镜像
核心:分层校验 → 增量上传 → 元数据注册 ,以docker push 172.25.254.100:5000/webserver:v4为例:
- 本地预处理:Docker Daemon 解析镜像标签,拆分出仓库地址、镜像名、标签,同时将本地镜像拆分为各分层,获取每一层的 sha256 哈希值;
- 建立连接 :通过 HTTP/HTTPS 向仓库服务端的
/v2/接口发送请求,完成身份校验(公共仓库如 Docker Hub 需登录验证,私有仓库若配置 insecure 则免密); - 分层校验 :向服务端发送「本地镜像各分层的哈希值」,服务端通过索引模块 查询该分层是否已存在:
- 若分层已存在:跳过该分层,无需重复上传;
- 若分层不存在:进入上传流程;
- 增量上传 :将本地缺失的分层二进制文件,通过服务端
/v2/webserver/blobs/接口上传至存储模块,上传完成后服务端返回分层校验成功; - 元数据注册 :所有分层上传完成后,向服务端发送「镜像标签(v4)与分层哈希值的映射关系」,服务端将该元数据写入索引模块,完成推送;
- 结果返回:服务端返回推送成功,本地 Docker Daemon 更新本地镜像元数据。
Docker Hub 差异 :多了镜像安全扫描、权限校验、分层缓存步骤,推送后会自动扫描镜像是否存在 CVE 漏洞,同时验证用户是否有该仓库的推送权限。
2. 拉取(docker pull):仓库服务端 → 本地

镜像拉取分为以下几步:
1.docker客户端向index发送镜像拉去请求并完成与index的认证
2.index发送认证token和镜像位置给dockerclient
3.dockerclient携带token和根据index指引的镜像位置取连接registry
4.Registry会根据client持有的token跟index核实身份合法性
5.index确认此token合法性
6.Registry会根据client的请求传递镜像到客户端
核心:标签解析 → 分层校验 → 增量下载 → 本地组装 ,以docker pull 172.25.254.100:5000/webserver:v4为例:
- 标签解析 :Docker Daemon 向仓库服务端
/v2/webserver/tags/list接口发送请求,获取v4标签对应的所有分层哈希值; - 分层校验:本地对比服务端返回的分层哈希值,检查哪些分层本地已存在、哪些缺失;
- 增量下载 :向服务端
/v2/webserver/blobs/sha256:xxx接口请求下载本地缺失的分层,下载完成后本地验证分层哈希值(防止传输损坏); - 本地组装:所有缺失分层下载完成后,Docker Daemon 根据服务端返回的「分层顺序」,将各只读层组装为完整镜像,同时在本地注册镜像标签;
- 结果返回 :拉取成功,本地可通过
docker images查看镜像。
Docker Hub 差异 :国内访问会通过镜像加速器 (如https://docker.1ms.run)做「分层缓存」,加速器会将 Docker Hub 的镜像分层缓存到国内节点,本地拉取时实际从国内加速器下载,而非直接访问 Docker Hub,解决网络超时问题。
3. 关键补充:为什么需要「镜像打标签(docker tag)」?
仓库识别镜像的唯一标准是「仓库地址 / 镜像名:标签」 ,本地镜像(如 webserver:v4)无仓库地址,Docker Daemon 无法识别要推送到哪个仓库,因此需要通过docker tag为本地镜像添加「仓库地址前缀」,本质是为本地镜像绑定「仓库服务端地址 + 镜像名 + 标签」的完整元数据,让 Docker Daemon 能找到对应的仓库服务端。
4、公共仓库(Docker Hub)vs 私有仓库(本地 registry)工作原理差异
二者遵循完全相同的 Registry V2 核心协议 ,核心工作流程(pull/push、分层存储、元数据管理)一致,差异仅在于服务端的扩展功能和部署环境,具体对比如下:
| 维度 | Docker Hub(公共仓库) | 本地 registry(私有仓库) |
|---|---|---|
| 部署环境 | 云端官方托管,公网访问 | 本地 / 内网服务器部署,仅内网访问 |
| 身份校验 | 强制账号密码 / PAT 登录,细粒度权限控制(仓库所有者 / 协作者) | 默认无校验(可配置),仅基础 insecure/HTTPS 校验 |
| 扩展功能 | 镜像安全扫描、自动构建、计费、镜像搜索、团队管理 | 仅实现核心的镜像存储 / 分发,无扩展功能 |
| 存储机制 | 分布式云存储,分层多节点缓存,高可用 | 本地文件存储(默认),单节点,无高可用 |
| 网络适配 | 国内公网访问慢,需镜像加速器做分层缓存 | 内网访问,速度快,无网络限制,无需加速器 |
| 核心模块 | 索引 + 存储 + API + 安全扫描 + 权限管理 | 仅索引 + 存储 + API 核心模块 |
5、Docker Hub 专属:Personal Access Token(PAT)登录原理
Docker Hub 推荐使用PAT(个人访问令牌) 替代密码登录,核心是提升安全性的同时实现细粒度权限控制,其工作原理为:
- PAT 是用户账号的「有限权限令牌」,由用户在 Docker Hub 后台创建,可指定有效期(如 7 天)、权限范围(仅读 / 可写 / 可删除),本质是「替代密码的临时身份凭证」;
- 执行
docker login输入 PAT 时,Docker Daemon 将「用户名 + PAT」加密后发送至 Docker Hub 认证接口; - Docker Hub 验证 PAT 的有效性(是否过期、权限是否匹配),验证通过后返回临时会话令牌 ,本地 Docker Daemon 将该令牌缓存至
~/.docker/config.json,后续 pull/push 无需重复验证; - 若 PAT 泄露,可直接在 Docker Hub 后台删除该令牌,不会影响用户账号密码,实现「令牌失效,账号安全」。
6、核心总结:Docker 仓库工作的 3 个关键核心
- 协议标准化 :所有仓库均遵循Registry V2 协议,通过 HTTP/HTTPS 的 RESTful API 实现客户端与服务端的通信,保证了不同仓库(Docker Hub/registry/Harbor)的兼容性;
- 存储分层化:以「分层」为单位存储和传输镜像,通过 sha256 哈希值实现分层唯一标识、增量传输和共享,是仓库高效存储和传输的基础;
- 架构客户端 - 服务端化:本地 Docker Daemon 作为客户端,负责所有预处理和本地操作,仓库服务端仅负责「分层存储」和「元数据管理」,解耦了镜像操作和存储,让仓库可独立部署和扩展。
七、Docker镜像仓库的管理
1、官方镜像仓库(非加密仓库构建---公开的)
Docker Hub 是官方的公共 Docker 镜像仓库,支持镜像上传、下载、私有仓库、镜像构建等核心功能,也是最常用的镜像管理平台



docker hub 的使用方法:
#登陆官方仓库
[root@docker ~]# docker login
Log in with your Docker ID or email address to push and pull images from Docker
Hub. If you don't have a Docker ID, head over to https://hub.docker.com/ to
create one.
You can log in with your password or a Personal Access Token (PAT). Using a
limited-scope PAT grants better security and is required for organizations using
SSO. Learn more at https://docs.docker.com/go/access-tokens/
Username: liangmoumou
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/#credential-stores
Login Succeeded
#登陆信息保存位置
[root@docker ~]# cd .docker/
[root@docker .docker]# ls
config.json
[root@docker .docker]# cat config.json
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "dGltaW5nbGVlOjY3NTE1MTVtaW5nemxu"
}
}
[root@docker ~]# docker tag gcr.io/distroless/base-debian11:latest
timinglee/base-debian11:latest
[root@docker ~]# docker push timinglee/base-debian11:latest
The push refers to repository [docker.io/timinglee/base-debian11]
6835249f577a: Pushed
24aacbf97031: Pushed
8451c71f8c1e: Pushed
2388d21e8e2b: Pushed
c048279a7d9f: Pushed
1a73b54f556b: Pushed
2a92d6ac9e4f: Pushed
bbb6cacb8c82: Pushed
ac805962e479: Pushed
af5aa97ebe6c: Pushed
4d049f83d9cf: Pushed
9ed498e122b2: Pushed
577c8ee06f39: Pushed
5342a2647e87: Pushed
latest: digest:
sha256:f8179c20f1f2b1168665003412197549bd4faab5ccc1b140c666f9b8aa958042 size:
3234
2、搭建docker的私有仓库
2.1 搭建docker私有仓库的原因
- 网络与访问速度优势
-
公有 Docker Hub 外网访问慢、经常超时、拉取 / 推送卡顿;
-
私有仓库部署在内网,传输速度快、延迟低,适合集群内部批量分发镜像。
- 企业数据安全与隐私保护
-
业务定制镜像、项目环境镜像不能上传到公网 Docker Hub,防止源码、配置、敏感信息泄露;
-
私有仓库内网隔离,权限可控,保障镜像数据安全。
- 环境稳定性与版本可控
-
公有仓库镜像版本易变动、依赖不稳定,外网下载容易丢包、拉取失败;
-
私有仓库可统一固化镜像版本,适配开发、测试、生产统一环境,避免 "本地能跑线上不行"。
- 节省公网带宽资源
-
基础系统、运行环境类基础镜像体积大,多节点重复拉取耗费公网流量;
-
内网私有仓库一次推送、多节点重复复用,节约出口带宽。
- 内网无外网环境可用
-
部分服务器 / 涉密环境禁止联网,无法访问外网 Docker Hub;
-
本地私有仓库可离线导入
tar镜像、内网分发,满足离线部署需求。
- 权限精细化管理
-
可配置账号密码认证、HTTPS 加密、不同团队不同仓库读写权限;
-
相比公有仓库免费权限有限,私有仓库自主管控访问与推送权限。
- 适配容器集群运维
-
K8s / 单机 Docker 集群批量调度容器时,需要内网快速拉取镜像;
-
私有仓库是容器集群持续集成 / 持续部署(CI/CD) 的基础组件。
总结:
搭建 Docker 私有仓库,主要为了内网高速传输、保护项目镜像隐私、环境版本统一、离线无外网部署、节省公网带宽、集群运维适配,解决公有 Docker Hub 网络慢、不安全、版本不可控的痛点。
2.2 搭建简单的Registry仓库
1.下载Registry镜像
[root@docker-node1 ~]# docker pull registry
Using default tag: latest
latest: Pulling from library/registry
930bdd4d222e: Pull complete
a15309931e05: Pull complete
6263fb9c821f: Pull complete
86c1d3af3872: Pull complete
a37b1bf6a96f: Pull complete
Digest: sha256:12120425f07de11a1b899e418d4b0ea174c8d4d572d45bdb640f93bc7ca06a3d
Status: Downloaded newer image for registry:latest
docker.io/library/registry:latest
2.开启Registry

3.上传镜像到仓库中
#给要上传的经镜像大标签
[root@docker-node1 ~]# docker tag busybox:latest 172.25.254.100:5000/busybox:latest
!!重要:
#docker在上传的过程中默认使用https,但是我们并没有建立https认证需要的认证文件所以会报错
[root@docker-node1 ~]# docker push 172.25.254.100:5000/busybox:latest
The push refers to repository [172.25.254.100:5000/busybox]
Get "https://172.25.254.100:5000/v2/": dial tcp 172.25.254.100:5000: connect:
connection refused
!!重要:
#配置非加密端口
[root@docker-node1 ~]# vim /etc/docker/daemon.json
{
"insecure-registries" : ["http://172.25.254.100:5000"]
}
[root@docker-node1 ~]# systemctl restart docker
#上传镜像
[root@Docker-node1 ~]# docker push 172.25.254.100:5000/webserver:v4
The push refers to repository [172.25.254.100:5000/webserver]
bbb6cacb8c82: Pushed
6835249f577a: Pushed
c048279a7d9f: Pushed
5342a2647e87: Pushed
2388d21e8e2b: Pushed
af5aa97ebe6c: Pushed
ac805962e479: Pushed
24aacbf97031: Pushed
80326fa65361: Pushed
577c8ee06f39: Pushed
2a92d6ac9e4f: Pushed
1a73b54f556b: Pushed
9ed498e122b2: Pushed
8451c71f8c1e: Pushed
80cfdf7d24df: Pushed
4d049f83d9cf: Pushed
v4: digest: sha256:412eb17025423549e19650e1ec77d1cb11e231c296041bcb3ce33ef0c7edc3b9 size: 856
#查看镜像上传
[root@docker-node1 ~]# curl 172.25.254.100:5000/v2/_catalog
{"repositories":["webserver"]}



2.3 为Registry提供加密传输
#生成认证key和证书
[root@docker-node1 ~]# mkdir /etc/docker/certs
[root@docker-node1 ~]# openssl req -newkey rsa:4096 \
-nodes -sha256 -keyout /etc/docker/certs/timinglee.org.key \
-addext "subjectAltName = DNS:reg.timinglee.org" \ #指定备用名称
-x509 -days 365 -out /etc/docker/certs/timinglee.org.crt
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:Shaanxi
Locality Name (eg, city) [Default City]:Xi'an
Organization Name (eg, company) [Default Company Ltd]:timinglee
Organizational Unit Name (eg, section) []:docker
Common Name (eg, your name or your server's hostname) []:reg.timinglee.org #这里的名称要跟上面指定的备用名称相同
Email Address []:admin@timinglee.org
#查看证书信息
[root@docker-node1 ~]# openssl x509 -in certs/timinglee.org.crt -noout -text
#启动registry仓库
[root@docker-node1 ~]# docker run -d -p 443:443 --restart=always --name registry \
-v /opt/registry:/var/lib/registry \
-v /root/certs:/certs \
-e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/timinglee.org.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/timinglee.org.key registry
#进行加密后要做DNS本地解析,Docker-node1和2都要做
[root@Docker-node1 ~]# vim /etc/hosts
172.25.254.100 reg.timinglee.org #添加此解析,因为我们上面指定的名称就是这个
[root@Docker-node2 ~]# vim /etc/hosts
172.25.254.100 reg.timinglee.org







测试:
#一开始的报错原因:docker客户端没有key和证书,Docker 私有仓库用的是自签名 HTTPS 证书,Docker 客户端不认识这个证书颁发机构,所以拒绝连接。
[root@docker docker]# docker push reg.timinglee.org/webserver:v4
Error response from daemon: Get "https://reg.timinglee.org/v2/": tls: failed to
verify certificate: x509: certificate signed by unknown authority
#为客户端建立证书:
#创建对应仓库域名的证书目录
[root@docker docker]# mkdir /etc/docker/certs.d/reg.timinglee.org/ -p
#把仓库的 CA 证书放进去,必须命名为 ca.crt
[root@docker docker]# cp /etc/docker/certs/timinglee.org.crt /etc/docker/certs.d/reg.timinglee.org/ca.crt
#重启docker服务生效
[root@docker docker]# systemctl restart docker.service
#提交镜像成功
这代表:
✅ Docker 客户端已经信任证书✅ HTTPS 验证通过✅ 镜像上传成功✅ 证书问题 100% 解决
[root@docker docker]# docker push reg.timinglee.org/webserver:v4
The push refers to repository [reg.timinglee.org/webserver:v4]
af5aa97ebe6c: Pushed
v4: digest: sha256:412eb17025423549e19650e1ec77d1cb11e231c296041bcb3ce33ef0c7edc3b9 size: 856
#验证镜像是否被提交进入仓库,-k = 不验证证书(不安全,但测试用没问题)
返回了 webserver说明:✅ 镜像真的已经进仓库了✅ 仓库运行正常
[root@docker docker]# curl -k https://reg.timinglee.org/v2/_catalog
{"repositories":["webserver"]}



2.4 为仓库建立登陆认证
#安装建立认证文件的工具包
[root@docker docker]# dnf install httpd-tools -y
#建立认证文件
[root@docker ~]# mkdir auth
#-B 强制使用最安全加密方式,默认用md5加密
[root@docker ~]# htpasswd -Bc auth/htpasswd lee
New password:
Re-type new password:
Adding password for user lee
#添加认证到registry容器中
[root@docker ~]# docker run -d -p 443:443 --restart=always --name registry \
-v/opt/registry:/var/lib/registry \
-v /etc/docker/certs:/certs \
-e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/timinglee.org.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/timinglee.org.key \
-v /etc/docker/auth:/auth \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
registry
[root@docker ~]# curl -k https://reg.timinglee.org/v2/_catalog -u lee:lee
{"repositories":["webserver"]}
#登陆测试
[root@docker ~]# docker login reg.timinglee.org
Username: lee
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/#credential-stores
Login Succeeded
当仓库开启认证后必须登陆仓库才能进行镜像上传:
#未登陆情况下不能上传镜像
[root@docker ~]# docker push reg.timinglee.org/busybox
Using default tag: latest
The push refers to repository [reg.timinglee.org/busybox]
d51af96cf93e: Preparing
no basic auth credentials
#未登陆情况下也不能下载
[root@docker-node2 ~]# docker pull reg.timinglee.org/busybox
Using default tag: latest
Error response from daemon: Head
"https://reg.timinglee.org/v2/busybox/manifests/latest": no basic auth
credentials






将证书传到从node1传到node2上面


node2有证书并且登录私人仓库后就能下载镜像了

3、构建企业级私有仓库
**下载软件包地址:**https://github.com/goharbor/harbor/releases
Harbor 是由vmware公司开源的企业级 Docker Registry 项目。
它提供了以下主要功能和特点:
-
基于角色的访问控制(RBAC):可以为不同的用户和用户组分配不同的权限,增强了安全性和管理的灵活性。
-
镜像复制:支持在不同的 Harbor 实例之间复制镜像,方便在多个数据中心或环境中分发镜像。
-
图形化用户界面(UI):提供了直观的 Web 界面,便于管理镜像仓库、项目、用户等。
-
审计日志:记录了对镜像仓库的各种操作,有助于追踪和审查活动。
-
垃圾回收:可以清理不再使用的镜像,节省存储空间。
3.1 部署Harbor


修改harbor的配置文件




3.2 管理仓库
1.登陆

2.建立仓库项目

3.上传镜像
注:docker-ce3:29.3.1-1.el9这个版本可能会有证书问题,如出现此问题,可进行docker降级,将原docker-ce删除,下载docker-ce3:28.5.2-1.el9这个版本应该就没问题了。

