一、Docker 基础认知

1.1 Docker 简介与发展历程

- Docker 是由 Docker, Inc 开发的开源分布式应用平台,是管理容器的引擎,为应用提供打包、部署的运行环境,而非单纯的虚拟化技术。Docker 之父 Solomon Hykes 将其类比为传统货运集装箱,解决了应用在不同环境中的标准化交付问题。
- 技术发展背景:2008 年 LXC(Linux Container)发布,但缺乏行业标准、兼容性极差;2013 年 Docker 首次发布,基于 LXC 构建并形成标准化容器生态,彻底推动了容器技术的普及。
- 核心组件:
- Docker Engine:可移植、轻量级的应用运行时与打包工具;
- Docker Hub:用于共享应用、自动化工作流的云服务。
1.2 Docker 核心特性与优势
Docker 核心价值是实现了开发一次,到处运行(Build once, Run anywhere) ,对运维则实现了配置一次,运行任何应用(Configure once, Run anything),核心特性如下:
- 轻量级虚拟化:容器启动为秒级,远快于虚拟机的分钟级启动,大幅节省系统资源;
- 环境一致性:确保应用在开发、测试、生产等不同环境中表现完全一致,杜绝 "本地能跑线上不能跑" 的环境差异问题;
- 高可移植性:容器可无缝从本地环境迁移到云服务器,无需担心依赖与配置差异;
- 高效资源利用:多个容器共享宿主机操作系统内核,单机可支持上千个容器,远高于虚拟机的运行密度;
- 快速部署与扩展:可秒级完成应用实例部署,支持按需水平扩展。
1.3 Docker 企业级应用场景

Docker 在企业中作为业务的最小载体被广泛应用,核心场景覆盖 IaaS、PaaS、SaaS 三层架构:
- SaaS 层:云盘、微店、企业网站、各类 SaaS 应用的标准化部署;
- PaaS 层:Redis、MySQL、NGINX、MongoDB 等中间件与数据库的容器化交付;
- IaaS 层:基于 Docker 构建企业级云平台,实现基础设施的标准化与资源池化。
补充概念:
- IaaS(基础设施即服务):提供服务器、存储、网络等底层硬件资源;
- PaaS(平台即服务):提供应用开发、运行的平台环境,屏蔽底层基础设施;
- SaaS(软件即服务):通过网络直接提供开箱即用的软件应用。
1.4 Docker 容器与传统虚拟机的对比

| 对比维度 | 传统虚拟机 | Docker 容器 |
|---|---|---|
| 操作系统 | 宿主机上运行完整虚拟机 OS | 共享宿主机 OS 内核 |
| 存储占用 | 镜像体积大(GB 级) | 镜像体积小(MB 级) |
| 性能表现 | 操作系统额外消耗 CPU、内存 | 几乎无性能损耗 |
| 移植性 | 笨重,与虚拟化技术耦合度高 | 轻量,灵活跨平台迁移 |
| 隔离性 | 系统级完全隔离 | 安全的进程级隔离 |
| 部署速度 | 慢,分钟级 | 快速,秒级 |
| 运行密度 | 单机一般支持几十个 | 单机支持上千个容器 |
二、Docker 环境部署

2.1 Docker 核心工作架构
Docker 采用 C/S(客户端 - 服务端)架构,核心三大组件:
- Client(客户端):通过 docker 命令向服务端发送 build、pull、run 等指令;
- DOCKER_HOST(宿主机):运行 Docker daemon 守护进程,负责镜像管理、容器生命周期管理;
- Registry(镜像仓库):集中存储与分发 Docker 镜像,客户端可从仓库拉取镜像,也可将本地镜像推送至仓库。
2.2 部署前准备与软件仓库配置
以 RHEL 9 系列系统为例,配置阿里云 Docker 软件源:
# 进入yum仓库配置目录
cd /etc/yum.repos.d
# 创建docker仓库配置文件
vim docker.repo
配置文件内容:
[docker]
name=docker-ce
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/stable
gpgcheck=0
2.3 Docker 安装与服务启动
安装 Docker 社区版
yum install -y docker-ce
配置服务启动参数(指定 iptables 网络模式)
# 编辑docker服务启动文件
vim /usr/lib/systemd/system/docker.service
# 修改ExecStart行,添加iptables=true参数
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true
启动服务并设置开机自启
# 重载系统服务配置
systemctl daemon-reload
# 启动docker并设置开机自启
systemctl enable --now docker
# 验证docker服务状态
docker info
2.4 内核网络参数优化配置
Docker 容器网络依赖内核桥接模块与转发能力,需激活相关内核参数:
加载桥接内核模块
# 配置开机自动加载br_netfilter模块
echo br_netfilter > /etc/modules-load.d/docker_mod.conf
# 即时加载模块
modprobe br_netfilter
配置内核网络转发参数
# 创建sysctl配置文件
vim /etc/sysctl.d/docker.conf
配置内容:
# 开启桥接流量经过iptables链
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
# 开启IPv4内核转发
net.ipv4.ip_forward = 1
生效配置并重启服务
# 加载所有sysctl配置
sysctl --system
# 重启docker服务使配置生效
systemctl restart docker
三、Docker 核心基础操作
3.1 Docker 镜像管理
镜像是容器运行的只读模板,包含应用运行所需的代码、依赖、环境变量、配置文件等所有内容,核心操作如下:
3.1.1 搜索镜像
从镜像仓库中搜索目标镜像,示例:
docker search nginx
关键返回字段说明:
- NAME:镜像名称
- DESCRIPTION:镜像功能说明
- STARS:社区点赞数量,代表镜像受欢迎程度
- OFFICIAL:是否为官方维护镜像
3.1.2 拉取镜像
从仓库拉取镜像到本地,支持指定版本标签,无标签默认拉取 latest 最新版:
# 拉取最新版busybox镜像
docker pull busybox
# 拉取指定版本的nginx轻量镜像
docker pull nginx:1.26-alpine
# 查看本地已下载镜像
docker images
补充:alpine 版本是基于 Alpine Linux 的极简发行版,大幅缩减镜像体积,例如 nginx:1.26-alpine 仅 43.2MB,远小于标准版的 188MB。
3.1.3 镜像信息查看与管理
# 查看镜像详细元数据、配置信息
docker image inspect nginx:1.26-alpine
# 导出镜像到本地文件,支持多镜像打包、压缩
docker image save nginx:latest -o nginx-latest.tar.gz
# 同时导出多个镜像到一个压缩包
docker image save nginx:latest nginx:1.26-alpine -o nginx.tag.gz
# 批量导出本地所有镜像
docker save `docker images | awk 'NR>1{print $1":"$2}'` -o images.tar.gz
# 导入本地镜像包
docker load -i nginx-latest.tar.gz
# 删除本地镜像
docker rmi nginx:latest
# 批量删除本地所有镜像
docker rmi `docker images | awk 'NR>1{print $1":"$2}'`
3.2 Docker 容器生命周期管理
容器是镜像的运行实例,是一个独立的、可运行的沙箱环境,核心操作覆盖启动、查看、启停、删除全生命周期。
3.2.1 容器启动
核心启动命令docker run,关键参数说明:
-d:后台守护进程运行容器-i:交互式运行,保持输入流开启-t:为容器分配虚拟终端--name:指定容器唯一名称-p:端口映射,格式为宿主机端口:容器端口--rm:容器停止后自动删除--network:指定容器使用的网络
常用启动示例:
# 后台启动马里奥游戏容器,映射宿主机80端口到容器8080端口
docker run -d --name mario -p 80:8080 timinglee/mario
# 交互式启动centos7容器,进入容器终端
docker run -it --name centos7 centos:7
关键注意事项:
- 容器内第一个进程必须持续前台运行,否则容器会直接退出;
- 交互式容器退出方式:按
ctrl+d退出并停止容器;按ctrl+p+q退出但不停止容器;- 重新进入运行中的容器:
docker attach centos7;- 在运行中的容器内执行命令:
docker exec -it 容器名/容器ID 命令,示例:docker exec -it test ifconfig。
3.2.2 容器状态查看
# 查看当前正在运行的容器
docker ps
# 查看所有容器(包括已停止的)
docker ps -a
# 查看容器详细配置、网络、挂载等元数据
docker inspect 容器名/容器ID
3.2.3 容器启停与删除
# 停止运行中的容器
docker stop 容器名/容器ID
# 强制杀死容器(支持发送系统信号)
docker kill 容器名/容器ID
# 启动已停止的容器
docker start 容器名/容器ID
# 重启容器
docker restart 容器名/容器ID
# 删除已停止的容器
docker rm 容器名/容器ID
# 强制删除运行中的容器
docker rm -f 容器名/容器ID
# 批量删除所有已停止的容器
docker container prune -f
3.3 容器数据交互与镜像提交
3.3.1 容器与宿主机文件传输
# 将容器内的文件复制到宿主机
docker cp 容器名:/容器内文件路径 宿主机目标路径
# 示例:把test2容器内的/leefile复制到宿主机/mnt目录
docker cp test2:/leefile /mnt
# 将宿主机文件复制到容器内
docker cp 宿主机文件路径 容器名:/容器内目标路径
# 示例:把宿主机/etc/fstab复制到test2容器根目录
docker cp /etc/fstab test2:/fstab
3.3.2 容器修改提交为新镜像
默认容器删除后,容器内的所有修改都会丢失,通过docker commit可将容器内的修改提交为新的镜像,实现修改持久化:
# 1. 运行容器并创建测试文件
docker run -it --name test busybox
touch leefile
exit
# 2. 将容器修改提交为新镜像
docker commit -m "add leefile" test busybox:v1
# 3. 查看生成的新镜像
docker images
# 4. 查看镜像构建历史
docker image history busybox:v1
企业最佳实践:
docker commit不利于审计与版本管理,企业环境中禁止使用该方式构建镜像,应通过 Dockerfile 标准化构建镜像。
3.4 容器日志查看
# 查看容器运行日志,实时输出应用打印的标准输出/标准错误
docker logs 容器名/容器ID
# 示例:查看web容器的nginx运行日志
docker logs web
# 持续实时刷新日志
docker logs -f 容器名/容器ID
# 查看最近100行日志
docker logs --tail 100 容器名/容器ID
四、Docker 镜像构建与优化
4.1 Docker 镜像底层原理


4.1.1 镜像分层结构
- Docker 镜像采用分层存储架构,最底层为基础镜像(Base Image),提供最小化的 Linux 发行版环境,所有镜像共享宿主机的 Linux 内核;
- 镜像层全部为只读层 ,容器启动时会在镜像层之上创建一个可写的容器层,所有对容器的修改都保存在容器层,不会修改底层镜像;
- 分层结构的核心优势是资源共享,多个镜像可复用相同的基础层,大幅减少存储空间占用;
- 单个 Docker 镜像最多支持 127 个分层。
4.1.2 写时复制(Copy-on-Write)机制
- Docker 从上到下依次在镜像层中查找文件,找到后直接读取;
- 当需要修改、新增、删除文件时,会将文件从只读镜像层复制到可写容器层进行修改,原始镜像层文件保持不变;
- 容器删除后,容器层的所有修改会一并删除,底层镜像层保持不变。
4.1.3 镜像获取方式
- 从镜像仓库拉取:
docker pull 镜像地址 - 从本地镜像包导入:
docker load -i 本地镜像包 - 基于 Dockerfile 自定义构建(企业主流方式)
- 基于容器 commit 提交生成(不推荐)
4.2 Dockerfile 核心指令详解
Dockerfile 是用于构建 Docker 镜像的文本文件,包含一条条构建镜像所需的指令和步骤,核心指令如下:
| 指令 | 功能说明与用法示例 |
|---|---|
| FROM | 指定构建使用的基础镜像,必须为 Dockerfile 的第一条指令示例:FROM busybox:latest、FROM centos:7 AS build(多阶段构建命名) |
| MAINTAINER | 指定镜像作者信息(新版 Docker 已废弃,推荐使用 LABEL 替代)示例:MAINTAINER user@example.com |
| LABEL | 为镜像添加元数据标签,可用于标注作者、版本、描述等信息示例:LABEL maintainer="user@example.com" version="1.0" |
| COPY | 复制宿主机本地文件 / 目录到镜像内示例:COPY leefile /、COPY ["file1","file2","/opt/"] |
| ADD | 功能与 COPY 一致,额外支持 2 个特性:1. 自动解压 tar/zip 等压缩包到目标路径;2. 支持从 URL 下载文件到镜像内示例:ADD test.tar /mnt、ADD http://ip/test.tar /mnt |
| ENV | 设置容器内的环境变量,构建过程与容器运行时均生效示例:ENV NAME lee、ENV MYSQL_ROOT_PASSWORD=123456 |
| EXPOSE | 声明容器运行时监听的端口,仅做声明,不自动完成端口映射示例:EXPOSE 80、EXPOSE 80 443 |
| VOLUME | 声明容器数据卷挂载点,实现数据持久化,避免容器删除数据丢失示例:VOLUME ["/var/www/html"]、VOLUME /usr/local/nginx/html |
| WORKDIR | 切换容器内的工作目录,若目录不存在会自动创建,后续 RUN/CMD/ENTRYPOINT 等指令均在该目录下执行示例:WORKDIR /mnt、WORKDIR /opt/app |
| RUN | 在镜像构建阶段执行 shell 命令,每一条 RUN 指令会生成一个新的镜像层示例:RUN yum install -y gcc make、RUN touch leefile |
| CMD | 容器启动时默认执行的命令,可被 docker run 命令行参数覆盖 ;一个 Dockerfile 中只有最后一条 CMD 生效- shell 格式:CMD echo $NAME(会调用 shell 解析器)- exec 格式:CMD ["/bin/echo","$NAME"](不调用 shell 解析器,无法解析环境变量)- 推荐 exec 格式:CMD ["/bin/sh","-c","echo $NAME"] |
| ENTRYPOINT | 容器启动时执行的命令,不可被 docker run 命令行参数覆盖 ,与 CMD 配合可实现容器启动参数动态传递;用法格式与 CMD 一致示例:ENTRYPOINT ["nginx", "-g", "daemon off;"] |
4.3 Dockerfile 完整构建示例
以 CentOS7 为基础镜像,源码编译构建 Nginx 镜像:
创建构建目录并准备源码包
mkdir docker
cd docker
# 提前下载nginx源码包到当前目录
cp ~/nginx-1.23.3.tar.gz .
编写 Dockerfile 文件
# 指定基础镜像
FROM centos:7
# 复制并解压nginx源码包到/mnt目录
ADD nginx-1.23.3.tar.gz /mnt
# 切换工作目录到源码解压路径
WORKDIR /mnt/nginx-1.23.3
# 安装编译依赖
RUN yum install -y gcc make pcre-devel openssl-devel
# 关闭debug编译模式,减小二进制体积
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
# 配置编译参数,开启ssl与状态模块
RUN ./configure --with-http_ssl_module --with-http_stub_status_module
# 编译与安装
RUN make
RUN make install
# 声明容器监听端口
EXPOSE 80
# 声明数据持久化目录
VOLUME ["/usr/local/nginx/html"]
# 容器启动时前台运行nginx
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
执行镜像构建
# -t 指定镜像名称与标签,. 指定Dockerfile所在的上下文目录为当前目录
docker build -t webserver:v1 .
镜像验证与测试
# 查看构建完成的镜像
docker images webserver
# 查看镜像构建历史与分层
docker history webserver:v1
# 启动容器测试镜像可用性
docker run -d --name checkimage webserver:v1
# 查看容器运行状态
docker ps | grep checkimage
4.4 镜像优化核心策略与实战
Docker 镜像优化核心目标是减小镜像体积、减少镜像层数、提升构建效率、降低安全风险,核心策略与实战如下:
4.4.1 核心优化策略
- 选择最精简的基础镜像(如 alpine、distroless);
- 合并 RUN 指令,减少镜像分层数量;
- 清理镜像构建的中间产物(如 yum 缓存、源码包、编译临时文件);
- 采用多阶段构建,仅保留运行所需的二进制与依赖,剔除编译环境;
- 关闭不必要的编译 debug 信息,减小二进制文件体积。
4.4.2 优化实战示例
基于上述 Nginx 镜像,分阶段优化效果如下:
| 优化方式 | 镜像版本 | 镜像体积 | 优化效果 |
|---|---|---|---|
| 原始构建 | webserver:v1 | 494MB | 基准版本 |
| 合并 RUN 指令 + 清理中间产物 | webserver:v2 | 317MB | 体积缩减 36% |
| 多阶段构建 | webserver:v3 | 205MB | 体积缩减 58% |
| 精简 distroless 基础镜像 | webserver:v4 | 34MB | 体积缩减 93% |
优化 1:合并 RUN 指令 + 清理中间产物
FROM centos:7
ADD nginx-1.23.3.tar.gz /mnt
WORKDIR /mnt/nginx-1.23.3
# 合并所有RUN指令,构建完成后清理源码与yum缓存
RUN yum install -y gcc make pcre-devel openssl-devel && \
sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && \
./configure --with-http_ssl_module --with-http_stub_status_module && \
make && make install && \
cd .. && rm -fr nginx-1.23.3 && \
yum clean all
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
优化 2:多阶段构建第一阶段完成编译构建,第二阶段仅复制编译后的 nginx 运行文件,剔除编译环境与依赖:
# 构建阶段:完成nginx编译
FROM centos:7 AS build
ADD nginx-1.23.3.tar.gz /mnt
WORKDIR /mnt/nginx-1.23.3
RUN yum install -y gcc make pcre-devel openssl-devel && \
sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && \
./configure --with-http_ssl_module --with-http_stub_status_module && \
make && make install && \
cd .. && rm -fr nginx-1.23.3 && \
yum clean all
# 运行阶段:仅保留运行所需文件
FROM centos:7
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
优化 3:使用 distroless 极简基础镜像distroless 是 Google 开源的极简基础镜像,仅包含应用运行所需的最小组件,无 shell、包管理器等多余组件,极致缩减镜像体积:
# 基础构建阶段
FROM nginx:1.23 AS base
ARG TIME_ZONE
RUN mkdir -p /opt/var/cache/nginx && \
cp -a --parents /usr/lib/nginx /opt && \
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 && \
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 && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime
# 最终运行阶段:使用distroless基础镜像
FROM gcr.io/distroless/base-debian11
COPY --from=base /opt /
EXPOSE 80 443
ENTRYPOINT ["nginx", "-g", "daemon off;"]
五、Docker 镜像仓库管理

5.1 镜像仓库核心概念与分类
Docker Registry(镜像仓库)是用于存储和分发 Docker 镜像的集中式存储库,是 Docker 生态中镜像共享、版本管理的核心组件,分为两大类:
- 公共仓库:面向互联网开放,任何人都可访问、拉取镜像,典型代表为 Docker Hub,国内常用的有 DaoCloud 镜像仓库、阿里云容器镜像服务等;
- 私有仓库:由企业 / 个人自行搭建管理,用于存储内部业务镜像,保障数据安全与访问权限管控,典型开源方案为 Docker 官方 Registry、VMware 开源的 Harbor。
5.2 Docker Hub 公共仓库使用


Docker Hub 是 Docker 官方提供的公共镜像仓库,拥有海量官方与社区维护的镜像,是最主流的公共镜像源。
5.2.1 基础使用流程
-
账号准备:前往https://hub.docker.com/ 注册 Docker ID;
-
客户端登录:
docker login
按提示输入Docker ID与密码,登录成功后凭证会保存在/root/.docker/config.json
镜像打标签:推送镜像前,需按照用户名/镜像名:标签格式为镜像打标签
# 格式:docker tag 原镜像名:标签 用户名/镜像名:标签
docker tag gcr.io/distroless/base-debian11:latest timinglee/base-debian11:latest
推送镜像到 Docker Hub
docker push timinglee/base-debian11:latest
从 Docker Hub 拉取镜像
docker pull timinglee/base-debian11:latest
退出登录
docker logout
5.2.2 国内镜像加速配置
国内网络访问 Docker Hub 速度较慢,可配置镜像加速地址提升拉取速度:
# 创建/修改daemon.json配置文件
vim /etc/docker/daemon.json
配置内容:
{
"registry-mirrors": ["https://docker.m.daocloud.io"]
}
生效配置:
systemctl daemon-reload
systemctl restart docker
5.3 镜像推拉核心原理
5.3.1 镜像拉取(pull)原理

- Docker 客户端向 Index(索引服务)发送镜像拉取请求,并完成用户认证;
- Index 返回认证 token 与镜像所在的 Registry 地址;
- 客户端携带 token,根据 Index 指引连接对应的 Registry;
- Registry 将客户端的 token 发送给 Index,核实身份合法性;
- Index 确认 token 有效并返回验证结果;
- Registry 向客户端传输镜像分层数据,完成拉取。
5.3.2 镜像推送(push)原理

- Docker 客户端向 Index 发送镜像上传请求,并完成用户认证;
- Index 向客户端返回临时 token,用于证明客户端合法性;
- 客户端携带 token 连接目标 Registry;
- Registry 向 Index 核实 token 的合法性;
- Index 验证 token 有效并返回结果;
- Registry 接收客户端上传的镜像分层数据,完成推送。
5.4 私有 Registry 仓库搭建与配置
Docker 官方开源了 Registry 镜像,可快速搭建轻量级私有仓库,适用于测试与小型环境。
5.4.1 基础版私有仓库搭建(HTTP)
拉取 Registry 官方镜像
docker pull registry:latest
启动 Registry 容器
docker run -d -p 5000:5000 --restart=always --name registry registry
配置 Docker 客户端信任 HTTP 仓库
vim /etc/docker/daemon.json
配置内容(替换为仓库宿主机 IP):
{
"insecure-registries" : ["http://172.25.254.100:5000"]
}
重启 Docker 生效配置
systemctl daemon-reload
systemctl restart docker
镜像推送与拉取测试
# 为镜像打私有仓库标签
docker tag busybox:latest 172.25.254.100:5000/busybox:latest
# 推送镜像到私有仓库
docker push 172.25.254.100:5000/busybox:latest
# 查看仓库中的镜像列表
curl 172.25.254.100:5000/v2/_catalog
# 从私有仓库拉取镜像
docker pull 172.25.254.100:5000/busybox:latest
5.4.2 私有仓库 HTTPS 加密配置
生产环境需配置 HTTPS 保障传输安全,基于自签名证书实现:
创建证书目录并生成自签名证书
mkdir -p /root/certs
openssl req -newkey rsa:4096 \
-nodes -sha256 -keyout certs/timinglee.org.key \
-addext "subjectAltName = DNS:reg.timinglee.org" \
-x509 -days 365 -out certs/timinglee.org.crt
# 按提示填写证书信息,Common Name需填写域名reg.timinglee.org
启动带 HTTPS 配置的 Registry 容器
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
客户端配置证书信任
# 创建证书目录
mkdir /etc/docker/certs.d/reg.timinglee.org/ -p
# 复制CA证书到客户端目录
cp /root/certs/timinglee.org.crt /etc/docker/certs.d/reg.timinglee.org/ca.crt
# 重启docker
systemctl restart docker
测试 HTTPS 仓库
# 打标签
docker tag busybox:latest reg.timinglee.org/busybox:latest
# 推送镜像
docker push reg.timinglee.org/busybox:latest
# 查看仓库镜像
curl -k https://reg.timinglee.org/v2/_catalog
5.4.3 私有仓库用户认证配置
为仓库添加账号密码认证,未登录用户无法推拉镜像:
安装 htpasswd 工具
dnf install httpd-tools -y
创建认证账号密码文件
mkdir -p /root/auth
# 创建用户timinglee,设置密码,-B使用bcrypt加密
htpasswd -Bc auth/htpasswd timinglee
启动带认证的 HTTPS Registry 容器
docker run -d -p 443:443 --restart=always --name registry \
-v /opt/registry:/var/lib/registry \
-v /root/certs:/certs \
-v /root/auth:/auth \
-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 \
-e REGISTRY_AUTH=htpasswd \
-e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
registry
认证测试
# 登录仓库
docker login reg.timinglee.org
# 输入账号密码完成登录后,即可正常推拉镜像
docker push reg.timinglee.org/busybox:latest
# 未登录状态推拉镜像会提示no basic auth credentials
5.5 Harbor 企业级私有仓库部署

Harbor 是 VMware 开源的企业级 Docker Registry 项目,提供了 RBAC 角色权限控制、镜像复制、Web 管理界面、审计日志、安全扫描、垃圾回收等企业级功能,是生产环境的首选方案。
5.5.1 Harbor 部署步骤
-
下载 Harbor 离线安装包:前往https://github.com/goharbor/harbor/releases 下载对应版本;
-
解压安装包
tar zxf harbor-offline-installer-v2.5.4.tgz
cd harbor
复制并修改配置文件
cp harbor.yml.tmpl harbor.yml
vim harbor.yml
核心配置修改:
# 仓库访问域名/IP
hostname: reg.timinglee.org
# HTTPS证书与私钥路径
certificate: /data/certs/timinglee.org.crt
private_key: /data/certs/timinglee.org.key
# admin管理员初始密码
harbor_admin_password: lee
执行安装脚本
# 可附加参数:--with-trivy开启镜像安全扫描,--with-chartmuseum开启Helm仓库支持
./install.sh --with-chartmuseum
Harbor 生命周期管理
# 停止Harbor所有服务
docker compose stop
# 启动Harbor所有服务
docker compose up -d
5.5.2 Harbor 基础使用
-
访问 Web 界面:通过https://reg.timinglee.org 访问,使用 admin 账号登录;
-
创建项目:在 Web 界面新建项目(如 timinglee),可设置公开 / 私有访问级别;
-
客户端登录与镜像推送
登录Harbor仓库
docker login reg.timinglee.org
为镜像打标签,格式:仓库域名/项目名/镜像名:标签
docker tag busybox:latest reg.timinglee.org/timinglee/busybox:latest
推送镜像
docker push reg.timinglee.org/timinglee/busybox:latest
-
推送完成后,可在 Harbor Web 界面的对应项目中查看镜像详情。
六、Docker 网络体系
Docker 网络实现了容器之间、容器与宿主机、容器与外网的通信,是 Docker 核心能力之一。
6.1 Docker 原生网络模型
Docker 安装完成后,会自动创建 3 种原生网络:bridge、host、none,可通过docker network ls查看。
6.1.1 bridge(桥接网络)- 默认模式

- Docker 安装时会自动创建名为
docker0的 Linux 网桥,新建容器默认会桥接到该接口; - 桥接模式下,容器会获得独立的内网 IP,宿主机可直接访问容器,外部主机无法直接访问,需通过端口映射实现外网访问;
- 容器通过宿主机的 NAT 规则实现外网访问,依赖
net.ipv4.ip_forward=1内核转发参数; - 特点:容器之间网络隔离,通过 docker0 网桥实现通信,是最常用的网络模式。
6.1.2 host(主机网络)模式

- 容器创建时通过
--network=host指定,容器与宿主机共享网络栈; - 容器不会获得独立的 IP,直接使用宿主机的 IP 与端口,无需端口映射即可直接访问;
- 特点:网络性能无损耗,但网络隔离性差,容器端口与宿主机端口会产生冲突。
6.1.3 none(无网络)模式
- 容器创建时通过
--network=none指定,禁用容器所有网络功能,仅保留 lo 本地回环接口; - 特点:极致的网络隔离,适用于对安全性要求极高、无需网络访问的容器场景。
6.2 Docker 自定义网络
Docker 支持用户自定义网络,提供了 bridge、overlay、macvlan 三种驱动:
- bridge:类似默认 bridge 网络,但增加了内置 DNS 解析、更好的隔离性,是单主机容器网络的推荐方案;
- overlay/macvlan:用于创建跨主机容器网络,实现多主机上的容器直接通信。
6.2.1 自定义桥接网络创建与配置
创建默认自定义桥接网络
docker network create my_net1
创建自定义子网与网关的桥接网络
docker network create my_net2 --subnet 192.168.0.0/24 --gateway 192.168.0.100
查看网络详细配置
docker network inspect my_net2
容器使用自定义网络
# 启动容器时指定自定义网络
docker run -d --network my_net1 --name web nginx
# 容器内可直接通过容器名ping通同网络的其他容器
docker run -it --network my_net1 --name test busybox
ping web
6.2.2 自定义网络核心优势
- 内置 DNS 解析:同一自定义网络内的容器,可直接通过容器名称相互通信,无需依赖 IP,解决了默认 bridge 网络 IP 动态变化的问题;
- 更好的网络隔离:不同自定义网络之间默认隔离,无法直接通信;
- 灵活的地址管理:可自定义子网、网关、IP 地址范围,避免与宿主机网络冲突。
6.2.3 不同自定义网络互通

不同自定义网络的容器默认无法通信,可通过docker network connect将容器加入多个网络实现互通:
# 1. 分别在两个网络启动容器
docker run -d --name web1 --network my_net1 nginx
docker run -it --name test --network my_net2 busybox
# 2. 将test容器加入my_net1网络
docker network connect my_net1 test
# 3. 此时test容器拥有两个网络的网卡,可与my_net1的web1容器通信
docker exec -it test ifconfig
docker exec -it test ping web1
6.3 joined 容器网络模式

joined 容器是一种特殊的网络模式,容器创建时通过--network=container:已运行容器名指定,使多个容器共享同一个网络栈。
- 核心特点:多个容器共用同一个 IP、端口、网络设备,容器之间可通过
localhost直接通信,网络性能极高; - 典型应用场景:需要在同一个网络命名空间内配合工作的多容器应用,如网络抓包、sidecar 代理、phpmyadmin 与 mysql 组合。
实战示例:phpmyadmin 与 mysql 共享网络栈
# 1. 启动phpmyadmin容器
docker run -d --name mysqladmin --network my_net1 \
-e PMA_ARBITRARY=1 \
-p 80:80 phpmyadmin:latest
# 2. 启动mysql容器,加入phpmyadmin的网络栈
docker run -d --name mysql \
-e MYSQL_ROOT_PASSWORD='lee' \
--network container:mysqladmin \
mysql:5.7
效果:phpmyadmin 容器内可直接通过
localhost:3306访问 mysql 数据库,无需端口暴露与网络互通配置。
6.4 容器内外网访问原理
6.4.1 容器访问外网

- 容器通过 docker0 网桥的网关(默认 172.17.0.1)将流量转发到宿主机;
- 宿主机通过 iptables/nftables 的MASQUERADE(地址伪装) 策略,将容器内网 IP 的流量转换为宿主机 IP,实现外网访问;
- 可通过
iptables -t nat -nL查看 nat 表中的地址伪装规则。
6.4.2 外网访问容器

- 外网访问容器通过端口映射 实现,格式为
-p 宿主机端口:容器端口; - 底层实现两种机制:
- docker-proxy 进程:监听宿主机端口,将流量转发到容器内对应端口;
- DNAT 目标地址转换:通过 iptables nat 表的 DNAT 规则,将宿主机端口的流量直接转发到容器 IP 的对应端口;
- 两种机制同时生效,系统会自动选择传输效率更高的路径。
6.5 Docker 跨主机网络
生产环境中容器分布在多台宿主机上,需要实现跨主机的容器通信,主流解决方案分为两类:
- Docker 原生方案:overlay 网络、macvlan 网络;
- 第三方网络方案:flannel、weave、calico(企业生产环境主流)。
6.5.1 CNM 容器网络模型

Docker 通过 CNM(Container Network Model)对容器网络进行抽象,实现了网络方案与 Docker 引擎的解耦,核心三大组件:
- Sandbox:容器网络栈,包含容器网卡、DNS、路由表,对应 Linux 网络命名空间;
- Endpoint:将 Sandbox 接入 Network,对应 veth pair 虚拟网卡对;
- Network:包含一组 Endpoint,同一 Network 内的 Endpoint 可直接通信,对应 Linux 网桥、vxlan 隧道等。
6.5.2 macvlan 跨主机网络实现
macvlan 是 Linux 内核提供的网卡虚拟化技术,无需 Linux 网桥,直接让容器接口与物理网卡连接,性能极高,无需 NAT 和端口映射。实现步骤:
两台 Docker 宿主机均添加一块网卡,开启混杂模式
# 两台主机均执行
ip link set eth1 promisc on
ip link set up eth1
两台主机创建相同配置的 macvlan 网络
docker network create \
-d macvlan \
--subnet 1.1.1.0/24 \
--gateway 1.1.1.1 \
-o parent=eth1 macvlan1
跨主机通信测试
# 主机1启动容器,指定固定IP
docker run -it --name busybox --network macvlan1 --ip 1.1.1.100 --rm busybox
# 主机2启动容器,指定固定IP
docker run -it --name busybox --network macvlan1 --ip 1.1.1.200 --rm busybox
# 两个容器可直接ping通对方IP,实现跨主机通信
七、Docker 数据卷管理

Docker 数据卷是可供容器使用的特殊目录,绕过容器的分层文件系统,直接将数据存储在宿主机上,实现容器数据的持久化与共享。
7.1 数据卷核心价值
Docker 分层文件系统存在两大核心问题:
- 性能差:读写操作需要经过多层镜像叠加,远低于宿主机本地磁盘性能;
- 生命周期与容器绑定:容器删除后,容器内的所有数据会一并丢失。
数据卷完美解决了以上问题,核心价值:
- 数据持久化:数据卷生命周期独立于容器,容器删除 / 重建,数据卷中的数据不会丢失;
- 高性能:直接挂载宿主机文件系统,与宿主机磁盘性能一致;
- 数据共享:多个容器可同时挂载同一个数据卷,实现数据共享与交互;
- 配置解耦:将应用配置、业务数据与容器镜像解耦,镜像无需包含可变数据,提升可移植性。
Docker 提供了两种数据卷类型:bind mount(绑定挂载) 和 docker managed volume(Docker 管理卷)。
7.2 Bind Mount(绑定挂载)
将宿主机上的指定目录 / 文件,直接挂载到容器内的指定路径,是最直观、最常用的挂载方式。
- 用法:
-v 宿主机路径:容器内路径:权限,权限可选ro(只读)、rw(读写,默认); - 特点:挂载路径可任意指定,灵活性极高;若宿主机路径不存在,挂载时会自动创建。
实战示例:
docker run -it --rm \
# 读写挂载宿主机/tmp/data1到容器/data1
-v /tmp/data1:/data1 \
# 只读挂载宿主机/tmp/data1到容器/data2,容器内无法修改
-v /tmp/data1:/data2:ro \
# 只读挂载宿主机文件到容器内
-v /etc/passwd:/data/passwd:ro \
busybox
7.3 Docker Managed Volume(Docker 管理卷)
无需指定宿主机挂载源路径,Docker 自动在/var/lib/docker/volumes/目录下为容器创建数据卷目录,统一管理。
- 核心优势:无需关注宿主机路径,移植性强,适合跨环境部署;
- 关键特性:若挂载的容器内路径已有文件,Docker 会将原有文件复制到数据卷中,不会覆盖。
实战示例:
手动创建管理卷
# 创建自定义管理卷
docker volume create leevol1
# 查看所有管理卷
docker volume ls
# 查看卷的宿主机路径
docker volume inspect leevol1
容器使用管理卷
# 启动nginx容器,将网站目录挂载到自定义管理卷
docker run -d --name web1 -p 80:80 -v leevol1:/usr/share/nginx/html nginx
# 宿主机直接修改卷内文件,容器内实时生效
cd /var/lib/docker/volumes/leevol1/_data
echo "hello docker volume" > index.html
# 测试访问
curl 127.0.0.1
匿名管理卷不指定卷名,仅指定容器内路径,Docker 自动创建匿名卷,示例:
# 启动mysql容器,自动创建匿名卷挂载/var/lib/mysql
docker run -d --name mysql -e MYSQL_ROOT_PASSWORD='lee' mysql:5.7
清理未使用的管理卷
# 清理所有未被容器挂载的管理卷(不可逆,需谨慎操作)
docker volume prune
7.4 数据卷容器与数据备份迁移
7.4.1 数据卷容器
数据卷容器是专门用于管理数据卷的容器,其他容器可通过--volumes-from继承其挂载配置,实现多个容器之间批量、统一的挂载管理,适用于多容器共享大量数据卷的场景。
实战示例:
创建数据卷容器
docker run -d --name datavol \
-v /tmp/data1:/data1:rw \
-v /tmp/data2:/data2:ro \
-v /etc/resolv.conf:/etc/hosts \
busybox
其他容器继承挂载配置
docker run -it --name test --rm --volumes-from datavol busybox
# 进入容器后可看到所有继承的挂载点,与datavol容器完全一致
ls /
7.4.2 数据卷备份与迁移
# 数据卷备份:将datavol容器的data1目录打包备份到宿主机当前目录
docker run --volumes-from datavol \
-v `pwd`:/backup busybox \
tar zcf /backup/data1.tar.gz /data1
# 数据卷恢复:将备份包解压到目标数据卷中
docker run -it --name test -v leevol1:/data1 -v `pwd`:/backup busybox /bin/sh -c "tar zxf /backup/data1.tar.gz -C /"
7.5 两种数据卷类型对比
| 对比维度 | Bind Mount(绑定挂载) | Docker Managed Volume(管理卷) |
|---|---|---|
| 卷存储位置 | 可任意指定宿主机路径 | 固定在 /var/lib/docker/volumes/ |
| 移植性 | 与宿主机路径绑定,移植性弱 | 无需关注宿主机路径,移植性强 |
| 单个文件支持 | 支持挂载单个文件 | 仅支持挂载目录 |
| 已有目录影响 | 容器内挂载点原有内容会被宿主机目录覆盖 | 容器内挂载点原有内容会被复制到卷中 |
| 权限控制 | 支持读写 / 只读权限设置 | 无精细化权限控制,默认可读写 |
| 适用场景 | 宿主机与容器固定配置、代码共享、本地开发 | 生产环境数据持久化、容器间数据共享、无需关注宿主机路径的场景 |
八、Docker 安全与资源限制
Docker 容器的安全性核心依赖 Linux 系统自身的安全机制,同时 Docker 提供了丰富的资源限制与安全加固能力。
8.1 Docker 安全核心评估维度
- Linux 命名空间机制:提供容器的基础隔离,包括 PID、NET、MNT、UTS、IPC、USER 等命名空间,实现容器之间、容器与宿主机的进程、网络、文件系统隔离;
- Linux 控制组(Cgroups)机制:限制容器对 CPU、内存、磁盘 IO 等宿主机资源的使用,防止容器资源耗尽导致宿主机宕机,抵御 DDoS 攻击;
- Linux 内核能力机制(Capabilities):对容器 root 用户进行细粒度的权限控制,禁用非必需的 root 权限,降低权限逃逸风险;
- Docker 服务端防护:Docker daemon 守护进程需要 root 权限运行,需严格控制对 Docker 服务的访问权限,防止未授权访问;
- 其他安全增强机制:如 SELinux/AppArmor 强制访问控制、镜像安全扫描、签名校验等。
补充:RHEL 9 系统默认使用 cgroup-v2,不利于观察 Docker 资源限制,可切换为 cgroup-v1:
bash
运行
grubby --update-kernel=/boot/vmlinuz-$(uname -r) \ --args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller" # 重启系统生效 reboot
8.2 基于 Cgroups 的资源限制
Linux Cgroups(Control Group)可限制进程组的资源使用上限,Docker 通过 Cgroups 实现容器的资源配额管理,核心限制维度包括 CPU、内存、磁盘 IO。
8.2.1 CPU 资源限制
限制 CPU 使用率 通过--cpu-period与--cpu-quota配合,限制容器在一个调度周期内可使用的 CPU 时间:
# 限制容器最多使用20%的单核CPU
# cpu-period:CPU调度周期,默认100000微秒(100毫秒)
# cpu-quota:周期内可使用的CPU时间,20000即20%单核CPU
docker run -it --rm --name test \
--cpu-period 100000 \
--cpu-quota 20000 \
ubuntu
限制 CPU 优先级 通过--cpu-shares设置 CPU 权重,默认值 1024,值越大,CPU 资源争抢时优先级越高:
# 设置容器CPU权重为100,优先级低于默认值
docker run -it --rm --cpu-shares 100 ubuntu
8.2.2 内存资源限制
通过--memory限制容器最大可使用的物理内存,--memory-swap限制内存 + 交换分区的总上限:
# 限制容器最大使用200M物理内存,且禁用swap(swap=内存大小)
docker run -d --name test --memory 200M --memory-swap 200M nginx
# 查看容器内存限制配置
cat /sys/fs/cgroup/memory/docker/容器ID/memory.limit_in_bytes
关键注意事项:若不设置
--memory-swap,容器默认可使用的 swap 大小为--memory值的 2 倍;若设置--memory-swap与--memory值相同,则容器无法使用 swap。
8.2.3 磁盘 IO 资源限制
通过--device-write-bps/--device-read-bps限制容器对磁盘的读写速率,--device-write-iops/--device-read-iops限制读写 IOPS:
# 限制容器对/dev/nvme0n1磁盘的写入速率不超过30MB/s
docker run -it --rm \
--device-write-bps /dev/nvme0n1:30M \
ubuntu
# 测试写入速率,direct模式跳过系统缓存,直接写入磁盘
dd if=/dev/zero of=bigfile bs=1M count=100 oflag=direct
8.3 Docker 安全加固方案
8.3.1 解决容器资源可见性问题
默认情况下,容器内free、top等命令会读取宿主机的资源信息,无法看到容器自身的资源限制,可通过 LXCFS 工具解决该问题。
LXCFS 可使容器内进程看到准确的 CPU、内存等资源使用信息,适配容器内应用的资源评估与监控需求。
部署与使用:
安装 LXCFS
dnf install lxcfs -y
后台运行 LXCFS
lxcfs /var/lib/lxcfs &
启动容器挂载 LXCFS,实现资源可见性隔离
docker run -it -m 256m \
-v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \
-v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw \
-v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw \
-v /var/lib/lxcfs/proc/stat:/proc/stat:rw \
-v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \
-v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \
ubuntu
# 容器内执行free -m,可看到内存上限为256M,与限制一致
free -m
8.3.2 容器权限管理
-
特权模式(--privileged) 默认情况下,容器内的 root 用户仅拥有有限的内核权限,无法修改网络配置、挂载磁盘、管理设备等敏感操作。开启
--privileged=true后,容器将获得宿主机 root 的几乎所有权限。开启特权模式启动容器
docker run --rm -it --privileged busybox
容器内可正常修改网卡配置、查看磁盘分区等敏感操作
ip a a 192.168.0.100/24 dev eth0
fdisk -l
安全警告:特权模式极大提升了容器权限,存在严重的权限逃逸风险,生产环境禁止使用。
- Capabilities 权限白名单 为避免特权模式的权限滥用,Docker 提供了
--cap-add参数,仅为容器添加必需的最小权限,实现权限最小化。
常用权限示例:
# 仅为容器添加网络管理权限,无需开启完整特权模式
docker run --rm -it --cap-add NET_ADMIN busybox
# 容器内可正常修改网络配置,其他敏感权限仍被禁用
ip a a 192.168.0.100/24 dev eth0
企业最佳实践:遵循最小权限原则,禁止使用特权模式,仅为容器添加业务必需的 Capabilities 权限。
九、Docker Compose 容器编排

Docker Compose 是 Docker 官方提供的多容器应用编排工具,通过 YAML 文件定义一组关联的容器服务,实现一键启动、停止、管理整个应用的所有容器,解决了多容器应用手动管理效率低、依赖关系复杂的问题。
9.1 Compose 核心概述
9.1.1 核心功能
- 服务定义:通过 YAML 配置文件定义应用的所有服务、镜像、端口、环境变量、挂载、网络等参数;
- 一键生命周期管理:通过单条命令完成整个应用的启动、停止、重启,无需逐个操作容器;
- 服务依赖编排:定义容器之间的启动依赖顺序,确保服务按正确的顺序启动(如数据库先启动,Web 服务后启动);
- 统一网络管理:自动为应用创建专属网络,服务之间可通过服务名直接通信,无需手动配置网络;
- 多环境配置管理:通过环境变量实现开发、测试、生产环境的配置隔离。
9.1.2 核心架构概念
Docker Compose 分为三层架构:
- 项目(Project) :由一组关联的应用容器组成的完整业务单元,对应一个
docker-compose.yml文件; - 服务(Service):一个应用的容器定义,一个服务可包含多个运行相同镜像的容器实例;
- 容器(Container):服务的具体运行实例,基于服务定义的镜像创建。
9.1.3 工作原理
- Docker Compose 读取并解析 YAML 配置文件;
- 调用 Docker Engine API,根据配置创建对应的网络、数据卷、容器;
- 监控容器状态,根据配置处理容器的启动顺序、故障重启、生命周期管理。
9.2 Compose 核心命令详解
Compose 命令通用格式:docker compose [选项] [命令],核心命令分类如下:
9.2.1 服务生命周期管理
| 命令 | 功能说明 | 常用示例 |
|---|---|---|
| up | 启动配置文件中定义的所有服务,自动创建网络、卷、容器 | docker compose up -d(后台启动)docker compose -f ./test.yml up -d(指定配置文件)docker compose up --build(启动前重新构建镜像) |
| down | 停止并删除 up 命令创建的所有容器、网络,默认不删除数据卷 | docker compose down``docker compose down -v(同时删除数据卷) |
| start | 启动已存在的服务,不创建新容器 | docker compose start``docker compose start web(仅启动 web 服务) |
| stop | 停止正在运行的服务,不删除容器 | docker compose stop``docker compose stop db(仅停止 db 服务) |
| restart | 重启配置文件中的所有服务 | docker compose restart |
9.2.2 服务状态查看
| 命令 | 功能说明 | 常用示例 |
|---|---|---|
| ps | 列出服务对应的容器、状态、端口映射等信息 | docker compose ps |
| logs | 查看服务的日志输出 | docker compose logs db(查看 db 服务日志)docker compose logs -f web(实时刷新 web 服务日志) |
9.2.3 镜像构建相关
| 命令 | 功能说明 | 常用示例 |
|---|---|---|
| build | 构建配置文件中定义的服务镜像 | docker compose build``docker compose build test1(仅构建 test1 服务) |
| pull | 拉取配置文件中定义的所有服务镜像 | docker compose pull |
9.2.4 其他常用命令
| 命令 | 功能说明 | 常用示例 |
|---|---|---|
| exec | 在运行中的服务容器内执行命令 | docker compose exec web sh(进入 web 服务容器终端) |
| config | 验证 YAML 配置文件语法,并输出解析后的完整配置 | docker compose config``docker compose config -q(仅校验语法,无输出则配置正确) |
9.3 Compose YAML 配置文件核心语法
Docker Compose 的 YAML 配置文件核心分为三大顶级配置块:services(服务定义)、networks(网络定义)、volumes(数据卷定义)。
基础配置示例:
version: "3.8"
# 服务定义块:核心配置,定义应用的所有服务
services:
# 服务名称:web
web:
# 服务使用的镜像
image: nginx:latest
# 容器名称
container_name: webserver
# 端口映射
ports:
- "80:80"
# 重启策略:always表示容器退出时始终重启
restart: always
# 环境变量
environment:
- TZ=Asia/Shanghai
# 数据卷挂载
volumes:
- ./html:/usr/share/nginx/html:ro
- nginx_data:/var/log/nginx
# 网络配置
networks:
- app_net
# 服务名称:db
db:
image: mysql:5.7
container_name: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: "123456"
TZ=Asia/Shanghai
volumes:
- mysql_data:/var/lib/mysql
networks:
- app_net
# 暴露端口,仅对同网络服务可见,不映射到宿主机
expose:
- 3306
# 网络定义块:定义应用使用的网络
networks:
# 自定义网络名称
app_net:
# 网络驱动,bridge为单主机网络,overlay为跨主机网络
driver: bridge
# 自定义子网与网关
ipam:
driver: default
config:
- subnet: 172.28.0.0/16
gateway: 172.28.0.254
# 数据卷定义块:定义Docker管理卷
volumes:
# 定义mysql数据卷
mysql_data:
name: mysql_data
# 定义nginx日志数据卷
nginx_data:
name: nginx_data
核心配置项详解:
-
services 核心配置
-
image:服务使用的 Docker 镜像,必填项(或通过 build 指定 Dockerfile 构建); -
build:指定 Dockerfile 路径,基于 Dockerfile 构建镜像,示例:yaml
build: context: ./app # 构建上下文目录 dockerfile: Dockerfile # Dockerfile名称 -
ports:端口映射,格式为"宿主机端口:容器端口"; -
expose:声明容器暴露的端口,仅对同网络服务可见,不映射到宿主机; -
environment:设置容器内环境变量,支持数组和键值对两种格式; -
volumes:数据卷挂载,支持绑定挂载和 Docker 管理卷; -
restart:容器重启策略,可选值:no(不重启,默认)、always(始终重启)、on-failure(异常退出时重启)、unless-stopped(除非手动停止,否则始终重启); -
command:覆盖容器启动时默认执行的命令; -
depends_on:定义服务启动依赖顺序,示例:depends_on: [db]表示 db 服务启动后再启动当前服务; -
networks:指定服务加入的网络。
-
-
networks 核心配置
driver:网络驱动,常用bridge(单主机)、overlay(Swarm 集群跨主机);external:是否使用外部已存在的网络,true表示不创建新网络,使用已有网络;ipam:自定义 IP 地址管理,可指定子网、网关。
-
volumes 核心配置
name:指定管理卷的名称;external:是否使用外部已存在的数据卷。
9.4 企业级实战示例
基于 Docker Compose 实现 HAProxy + Nginx 的负载均衡架构,2 台 Nginx 作为后端 Web 节点,HAProxy 作为负载均衡入口:
步骤 1:目录与配置文件准备
# 创建目录结构
mkdir -p /docker/web/html1 /docker/web/html2 /docker/conf/haproxy
# 准备两个网站首页
echo "web1 server" > /docker/web/html1/index.html
echo "web2 server" > /docker/web/html2/index.html
# 编写haproxy配置文件
vim /docker/conf/haproxy/haproxy.cfg
haproxy.cfg 配置内容:
global
log 127.0.0.1 local0
maxconn 4096
chroot /usr/local/etc/haproxy
user haproxy
group haproxy
daemon
nbproc 1
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
maxconn 2000
timeout connect 5s
timeout client 50s
timeout server 50s
listen http_front
bind 0.0.0.0:80
stats uri /haproxy_stats
mode http
balance roundrobin
server web1 web1:80 check inter 2000 rise 2 fall 3
server web2 web2:80 check inter 2000 rise 2 fall 3
步骤 2:编写 docker-compose.yml 配置文件
version: "3.8"
services:
web1:
image: nginx:latest
container_name: web1
restart: always
networks:
- app_net
expose:
- 80
volumes:
- /docker/web/html1:/usr/share/nginx/html
web2:
image: nginx:latest
container_name: web2
restart: always
networks:
- app_net
expose:
- 80
volumes:
- /docker/web/html2:/usr/share/nginx/html
haproxy:
image: haproxy:2.3
container_name: haproxy
restart: always
networks:
- app_net
volumes:
- /docker/conf/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
ports:
- "80:80"
networks:
app_net:
driver: bridge
步骤 3:一键启动整个应用
# 进入配置文件目录,后台启动所有服务
docker compose up -d
# 查看服务运行状态
docker compose ps
步骤 4:效果验证
# 多次访问,负载均衡会轮询转发到web1和web2节点
curl 127.0.0.1
# 访问HAProxy监控页面:http://宿主机IP/haproxy_stats