Docker基础操作

一、配置软件仓库并安装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 变成参数传给它
3. RUN vs CMD / ENTRYPOINT
  • RUN:构建镜像时执行(只执行一次,写进镜像层)
  • CMD / ENTRYPOINT:容器启动时执行(每次 run 都跑)

关键效果总结

  1. VOLUME "/mnt"→ 自动在宿主机生成匿名卷,宿主机写文件容器里立刻可见,实现持久化。

  2. WORKDIR /mnt→ 进入容器直接就在 /mnt 目录,不用再 cd。

  3. ADD 压缩包 会自动解压,COPY 只复制不解压。

  4. EXPOSE 8080 只是声明,是端口暴露,不是端口映射,真正映射要用 -p 主机端口:8080

  5. 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 仓库的所有操作均基于镜像分层机制,这是仓库能实现「增量传输、高效存储、共享分层」的核心原因,也是理解仓库工作原理的关键:

  1. 镜像分层 :一个 Docker 镜像由多个只读层(Layer) 组成,每层对应 Dockerfile 中的一条指令(如 FROM、RUN、COPY),每层有唯一的sha256 哈希值,仓库以「分层」为单位存储和传输镜像,而非整包镜像;
  2. 分层共享 :不同镜像若包含相同的分层(如多个镜像均基于 alpine:3.19 构建),仓库仅存储该分层一次,所有镜像共享此分层,大幅节省存储资源;
  3. 增量传输 :执行 docker pull/push 时,仓库会先对比「本地镜像分层的 sha256 哈希值」与「服务端分层的哈希值」,仅传输本地缺失 / 不一致的分层,而非整个镜像,大幅提升传输效率(比如本地已有基础层,仅拉取业务层即可);
  4. 标签映射 :镜像的「标签(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为例:

  1. 本地预处理:Docker Daemon 解析镜像标签,拆分出仓库地址、镜像名、标签,同时将本地镜像拆分为各分层,获取每一层的 sha256 哈希值;
  2. 建立连接 :通过 HTTP/HTTPS 向仓库服务端的/v2/接口发送请求,完成身份校验(公共仓库如 Docker Hub 需登录验证,私有仓库若配置 insecure 则免密);
  3. 分层校验 :向服务端发送「本地镜像各分层的哈希值」,服务端通过索引模块 查询该分层是否已存在:
    • 若分层已存在:跳过该分层,无需重复上传;
    • 若分层不存在:进入上传流程;
  4. 增量上传 :将本地缺失的分层二进制文件,通过服务端/v2/webserver/blobs/接口上传至存储模块,上传完成后服务端返回分层校验成功;
  5. 元数据注册 :所有分层上传完成后,向服务端发送「镜像标签(v4)与分层哈希值的映射关系」,服务端将该元数据写入索引模块,完成推送;
  6. 结果返回:服务端返回推送成功,本地 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为例:

  1. 标签解析 :Docker Daemon 向仓库服务端/v2/webserver/tags/list接口发送请求,获取v4标签对应的所有分层哈希值
  2. 分层校验:本地对比服务端返回的分层哈希值,检查哪些分层本地已存在、哪些缺失;
  3. 增量下载 :向服务端/v2/webserver/blobs/sha256:xxx接口请求下载本地缺失的分层,下载完成后本地验证分层哈希值(防止传输损坏);
  4. 本地组装:所有缺失分层下载完成后,Docker Daemon 根据服务端返回的「分层顺序」,将各只读层组装为完整镜像,同时在本地注册镜像标签;
  5. 结果返回 :拉取成功,本地可通过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(个人访问令牌) 替代密码登录,核心是提升安全性的同时实现细粒度权限控制,其工作原理为:

  1. PAT 是用户账号的「有限权限令牌」,由用户在 Docker Hub 后台创建,可指定有效期(如 7 天)、权限范围(仅读 / 可写 / 可删除),本质是「替代密码的临时身份凭证」;
  2. 执行docker login输入 PAT 时,Docker Daemon 将「用户名 + PAT」加密后发送至 Docker Hub 认证接口;
  3. Docker Hub 验证 PAT 的有效性(是否过期、权限是否匹配),验证通过后返回临时会话令牌 ,本地 Docker Daemon 将该令牌缓存至~/.docker/config.json,后续 pull/push 无需重复验证;
  4. 若 PAT 泄露,可直接在 Docker Hub 后台删除该令牌,不会影响用户账号密码,实现「令牌失效,账号安全」。

6、核心总结:Docker 仓库工作的 3 个关键核心

  1. 协议标准化 :所有仓库均遵循Registry V2 协议,通过 HTTP/HTTPS 的 RESTful API 实现客户端与服务端的通信,保证了不同仓库(Docker Hub/registry/Harbor)的兼容性;
  2. 存储分层化:以「分层」为单位存储和传输镜像,通过 sha256 哈希值实现分层唯一标识、增量传输和共享,是仓库高效存储和传输的基础;
  3. 架构客户端 - 服务端化:本地 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私有仓库的原因

  1. 网络与访问速度优势
  • 公有 Docker Hub 外网访问慢、经常超时、拉取 / 推送卡顿;

  • 私有仓库部署在内网,传输速度快、延迟低,适合集群内部批量分发镜像。

  1. 企业数据安全与隐私保护
  • 业务定制镜像、项目环境镜像不能上传到公网 Docker Hub,防止源码、配置、敏感信息泄露;

  • 私有仓库内网隔离,权限可控,保障镜像数据安全。

  1. 环境稳定性与版本可控
  • 公有仓库镜像版本易变动、依赖不稳定,外网下载容易丢包、拉取失败;

  • 私有仓库可统一固化镜像版本,适配开发、测试、生产统一环境,避免 "本地能跑线上不行"。

  1. 节省公网带宽资源
  • 基础系统、运行环境类基础镜像体积大,多节点重复拉取耗费公网流量;

  • 内网私有仓库一次推送、多节点重复复用,节约出口带宽

  1. 内网无外网环境可用
  • 部分服务器 / 涉密环境禁止联网,无法访问外网 Docker Hub;

  • 本地私有仓库可离线导入 tar 镜像、内网分发,满足离线部署需求。

  1. 权限精细化管理
  • 可配置账号密码认证、HTTPS 加密、不同团队不同仓库读写权限;

  • 相比公有仓库免费权限有限,私有仓库自主管控访问与推送权限。

  1. 适配容器集群运维
  • 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 项目。

它提供了以下主要功能和特点:

  1. 基于角色的访问控制(RBAC):可以为不同的用户和用户组分配不同的权限,增强了安全性和管理的灵活性。

  2. 镜像复制:支持在不同的 Harbor 实例之间复制镜像,方便在多个数据中心或环境中分发镜像。

  3. 图形化用户界面(UI):提供了直观的 Web 界面,便于管理镜像仓库、项目、用户等。

  4. 审计日志:记录了对镜像仓库的各种操作,有助于追踪和审查活动。

  5. 垃圾回收:可以清理不再使用的镜像,节省存储空间。

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这个版本应该就没问题了。

相关推荐
山人在山上1 小时前
docker zlmediakit 部署
docker·zlmediakit
Drache_long2 小时前
DevOps
运维·devops
不像程序员的程序媛2 小时前
nginx日志配置
运维·nginx
hopsky2 小时前
phoenix docker 启动
运维·docker·容器
又熟了2 小时前
乌班图Ubuntu安装
linux·运维·ubuntu
无情的西瓜皮3 小时前
MCP协议实战:从零搭建一个AI Agent工具服务器
运维·服务器·python
Do_GH3 小时前
【Linux】09.WSL+SVN部署操作说明
linux·运维·svn
哈德森hh3 小时前
我的 Twitter 自动化运营流程
运维·自动化·twitter
ElevenS_it1883 小时前
连锁门店IT运维监控实战:200+门店网络设备+POS统一纳管+按区域分组告警路由完整配置(Zabbix Proxy架构)
运维·网络·架构·zabbix