Java进阶全套教程(八)------ Docker超详细实战详解
一、Docker 核心认知
1.1 什么是Docker
Docker 是一款基于 Go 语言开发、遵循 Apache2.0 开源协议的开源应用容器引擎,主打轻量化虚拟化技术。它可以将应用程序、运行依赖、系统环境、配置文件统一打包为可移植的镜像,实现应用在任意支持 Docker 的 Linux/Windows 环境中一致性运行,彻底解决"本地运行正常、服务器部署报错"的环境兼容问题。
Docker 名称直译是"码头工人",其品牌标识为鲸鱼承载多个集装箱,完美贴合技术理念:IT 领域的"集装箱"就是容器,标准化的容器可以封装各类应用,统一规格、相互隔离、可批量部署、可跨环境迁移,这也是 Docker 容器技术的核心精髓。
1.2 集装箱技术核心思想
传统软件部署最大的痛点是环境差异化:不同服务器的系统版本、依赖库、配置参数各不相同,导致应用部署、迁移、维护成本极高。
Docker 借鉴现实码头集装箱的标准化理念:现实中集装箱统一尺寸、独立密封、互不干扰、可堆叠运输;对应到 IT 领域,Docker 容器标准化应用运行环境,实现三大核心价值:
-
环境标准化:一次打包,所有环境运行一致,消除环境差异Bug
-
应用隔离化:不同容器独立运行,进程、资源、环境互不冲突
-
部署轻量化:无需重复配置环境,直接通过镜像快速部署
1.3 Docker 核心定位与核心优势
Docker 的核心定位:打包程序+完整运行环境,实现一次构建、随处运行的容器化部署工具,是当下 DevOps 开发运维一体化的核心工具。
相较于传统部署方式,Docker 在开发、测试、生产全流程具备显著优势:
-
极速交付部署:镜像构建完成后,秒级完成部署上线,无需繁琐环境配置
-
超高资源利用率:共享宿主机内核,无需虚拟化完整系统,内存、磁盘占用极低
-
灵活迁移扩展:镜像跨服务器、跨平台无缝迁移,支持横向批量扩容容器
-
极简版本管理:支持镜像版本迭代、回滚,精准控制应用版本,更新无风险
1.4 Docker 与传统虚拟机深度对比
传统虚拟机属于硬件级虚拟化,需要模拟完整硬件、安装完整操作系统;Docker 属于操作系统级虚拟化,共享宿主机系统内核,仅隔离应用运行环境,轻量化优势极其明显。
| 对比维度 | Docker 容器 | 传统虚拟机 |
|---|---|---|
| 启动速度 | 秒级启动,无系统初始化过程 | 分钟级启动,需加载完整系统 |
| 磁盘占用 | MB 级,仅存储应用与依赖 | GB 级,包含完整系统镜像 |
| 运行性能 | 接近原生物理机,无性能损耗 | 存在虚拟化损耗,性能低于原生 |
| 单机承载量 | 单机可部署上千个容器 | 单机仅支持几十个虚拟机 |
| 隔离级别 | 进程级资源隔离 | 系统级完全隔离 |
二、虚拟化技术体系与Docker技术归属
2.1 虚拟化技术概述
虚拟化是通过软件方式对物理硬件、系统资源进行逻辑划分的技术,核心是"逻辑隔离、资源复用",旨在提升硬件资源利用率,是云计算、容器化技术的底层基础。
通俗类比:一套物理房屋(物理机),直接使用仅能单人独享;通过虚拟化改造,可分割为多个独立单间(虚拟机/容器),多用户独立使用,提升资源利用率。
2.2 虚拟化技术分类
-
完全虚拟化:完整模拟硬件设备,可运行任意操作系统,代表:VMware、KVM
-
硬件辅助虚拟化:依托CPU虚拟化指令集加速,提升虚拟化性能,主流虚拟机均采用此技术
-
部分虚拟化:仅对部分硬件资源虚拟化,系统内核仍共享,隔离性较弱
-
超虚拟化:修改客户机内核,适配虚拟化环境,降低性能损耗
-
操作系统虚拟化 :共享宿主机操作系统内核,仅隔离用户空间,轻量化、高性能,Docker 属于此类虚拟化
2.3 物理机、虚拟机、Docker容器三者区别
-
物理机:真实物理服务器,完整硬件+原生系统,资源独占,无虚拟化损耗,部署繁琐、迁移困难
-
虚拟机:硬件级虚拟化,独立系统内核、独立硬件资源,隔离性极强,但笨重、启动慢、资源占用高
-
Docker容器:系统级虚拟化,共享宿主机内核,仅隔离应用进程与环境,轻量、极速、高并发,隔离性满足业务部署需求
三、Docker 三大核心核心概念
Docker 所有操作均围绕镜像、容器、仓库三大核心概念展开,三者层层关联、缺一不可,是掌握 Docker 的基础。
3.1 镜像(Image)------ 应用模板
Docker 镜像属于只读模板,是创建容器的唯一依据,包含应用运行所需的系统环境、依赖库、程序文件、配置脚本等所有资源。镜像采用分层存储结构,每一层都是独立的只读文件系统,支持复用、缓存加速构建。
镜像来源主要分为两种:
-
官方公共仓库拉取:从 Docker Hub、阿里云 ACR 下载现成镜像(JDK、MySQL、Nginx 等)
-
自定义构建:通过 Dockerfile 脚本,基于基础镜像封装专属业务镜像
3.2 容器(Container)------ 运行实例
容器是镜像的动态运行实例,镜像为静态模板,容器为动态运行的进程。一个镜像可以批量创建多个相互隔离的容器,容器支持启动、停止、重启、删除等操作。
核心公式:容器 = 只读镜像 + 可读写临时层
所有容器运行时的修改、日志、缓存数据,均存储在顶层可读写层,删除容器后,临时层数据默认丢失(可通过数据卷持久化保存)。
3.3 仓库(Repository)------ 镜像存储中心
Docker 仓库是集中存储、管理镜像的远程服务器,用于镜像的上传、下载、版本管理,理念与 Maven 仓库、Git 仓库高度相似。
主流仓库分类:
-
官方公共仓库:Docker Hub(全球最大镜像仓库,海量官方镜像)
-
国内镜像仓库:阿里云 ACR、腾讯云 TCR、华为云 SWR(解决国外仓库访问慢问题)
-
私有仓库:企业自建 Registry,存储内部业务专属镜像,保障数据安全
3.4 Docker 核心口号解读
-
Build, Ship and Run:一次构建、统一分发、任意运行
-
Build once,Run anywhere:单次打包构建,适配所有支持 Docker 的运行环境
四、Docker 环境搭建与基础配置
4.1 部署环境要求
-
操作系统:CentOS 7+/Ubuntu 16.04+
-
内核版本:Linux 内核 3.8 及以上(CentOS7 默认内核 3.10,完全兼容)
4.2 环境初始化配置(生产必备)
Docker 部署前需关闭防火墙与 SELinux,避免端口拦截、权限限制导致容器访问异常
bash
# 1. 临时关闭防火墙(重启失效)
systemctl stop firewalld
# 2. 永久关闭防火墙开机自启
systemctl disable firewalld
# 3. 永久关闭SELinux(重启生效)
sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
# 4. 临时关闭SELinux(无需重启立即生效)
setenforce 0
4.3 Docker 安装与启停配置
bash
# 1. 更新yum依赖源
yum update -y
# 2. 安装Docker引擎
yum install -y docker-ce
# 3. 启动Docker服务
systemctl start docker
# 4. 设置Docker开机自启
systemctl enable docker
# 5. 查看Docker运行状态
systemctl status docker
# 6. 测试Docker安装成功(运行测试镜像)
docker run hello-world
4.4 配置国内镜像加速(解决拉取镜像缓慢问题)
默认 Docker Hub 服务器在国外,拉取镜像速度极慢,配置阿里云镜像加速器提升下载速度
bash
# 1. 创建Docker配置目录
mkdir -p /etc/docker
# 2. 写入阿里云镜像加速配置
tee /etc/docker/daemon.json <<-EOF
{
"registry-mirrors": ["https://mirror.aliyuncs.com"]
}
EOF
# 3. 重新加载配置、重启Docker
systemctl daemon-reload
systemctl restart docker
五、Docker 核心镜像命令(实操高频)
镜像是容器运行的基础,所有容器操作都依赖本地镜像,以下为生产环境高频镜像管理命令。
5.1 查看本地镜像
bash
# 查看所有本地镜像基础信息
docker images
# 查看本地镜像详细信息(层数、大小、创建时间、元数据)
docker images --verbose
# 仅查看所有镜像ID(批量操作专用)
docker images -q
字段说明:REPOSITORY(镜像名称)、TAG(版本标签,latest为最新版)、IMAGE ID(镜像唯一ID)、CREATED(创建时间)、SIZE(镜像大小)
5.2 搜索远程镜像
bash
# 搜索Docker Hub远程指定镜像
docker search nginx
# 筛选星级大于100的官方镜像
docker search --filter=stars=100 --filter=is-official=true nginx
5.3 拉取远程镜像
bash
# 拉取最新版本镜像(默认latest)
docker pull nginx
# 拉取指定版本镜像(生产必须指定版本,避免版本迭代兼容问题)
docker pull nginx:1.24.0
# 拉取Java8官方镜像
docker pull openjdk:8-jdk-alpine
5.4 删除本地镜像
bash
# 根据镜像名称+版本删除
docker rmi nginx:1.24.0
# 根据镜像ID删除
docker rmi 23f6481799cb
# 强制删除所有未使用的镜像
docker image prune -a -f
5.5 镜像打包与导入导出
用于镜像跨服务器迁移,无需重新拉取、构建,直接复用镜像
bash
# 1. 导出本地镜像为tar压缩包
docker save -o nginx-1.24.0.tar nginx:1.24.0
# 2. 导入tar镜像包到本地Docker
docker load -i nginx-1.24.0.tar
六、Docker 核心容器命令(生产实操核心)
容器是 Docker 业务运行的核心,所有应用均以容器形式运行,熟练掌握容器启停、查看、运维命令是部署关键。
6.1 创建与启动容器
容器启动分为两步:创建容器、启动容器,也可通过 run 命令一步完成创建+启动
bash
# 1. 仅创建容器(停止状态,无运行进程)
docker create --name nginx-demo nginx:1.24.0
# 2. 启动已创建的停止态容器
docker start nginx-demo
# 3. 新建并后台启动容器(常用)
# --name:指定容器名称 -d:后台守护态运行 -p:端口映射
docker run -d --name nginx-web -p 80:80 nginx:1.24.0
# 4. 交互式启动容器(进入容器终端,前台运行)
docker run -it --name centos-test centos:7 /bin/bash
6.2 查看容器状态
bash
# 查看当前正在运行的容器
docker ps
# 查看所有容器(包含停止状态)
docker ps -a
# 仅查看所有容器ID
docker ps -aq
# 查看容器详细运行信息(IP、端口、挂载、网络等)
docker inspect nginx-web
6.3 容器启停与重启
bash
# 停止单个容器
docker stop nginx-web
# 重启容器
docker restart nginx-web
# 批量停止所有容器
docker stop $(docker ps -aq)
# 批量重启所有容器
docker restart $(docker ps -aq)
6.4 进入容器内部操作
后台运行的容器无法直接操作,需通过 exec 命令进入容器终端,是线上运维核心命令
bash
# 进入容器终端,执行bash交互命令
docker exec -it nginx-web /bin/bash
# 退出容器(不停止容器)
exit
核心区别:attach 命令进入容器会同步窗口日志,阻塞操作;exec 命令独立终端,生产环境优先使用 exec。
6.5 容器日志与进程查看
bash
# 查看容器全部运行日志
docker logs nginx-web
# 实时跟踪容器最新日志(线上排查问题必备)
docker logs -f nginx-web
# 查看近100行最新日志
docker logs -f --tail=100 nginx-web
# 查看容器内部运行进程
docker top nginx-web
6.6 容器文件拷贝
实现宿主机与容器之间的文件双向传输,无需挂载数据卷即可临时同步文件
bash
# 宿主机文件拷贝到容器内
docker cp /home/test.html nginx-web:/usr/share/nginx/html/
# 容器内文件拷贝到宿主机
docker cp nginx-web:/var/log/nginx/access.log /home/nginx/log/
6.7 删除容器
bash
# 删除停止状态的容器
docker rm centos-test
# 强制删除正在运行的容器
docker rm -f nginx-web
# 批量删除所有容器
docker rm -f $(docker ps -aq)
七、Docker 实战部署常用服务
通过 Docker 快速部署 Java 开发常用环境,无需复杂配置,一键部署即用。
7.1 部署 JDK11 运行环境
bash
# 1. 拉取JDK11轻量化镜像
docker pull openjdk:11-jre-slim
# 2. 后台启动Java环境容器
docker run -d --name java11-demo openjdk:11-jre-slim
# 3. 验证Java环境
docker exec -it java11-demo java -version
7.2 部署 Tomcat9 服务
bash
# 1. 拉取Tomcat9镜像
docker pull tomcat:9.0-jdk11
# 2. 启动Tomcat容器,映射8080端口
docker run -d --name tomcat9-web -p 8080:8080 \
--restart always \
tomcat:9.0-jdk11
# 参数说明:--restart always 容器异常自动重启,适配生产环境
7.3 部署 MySQL5.7 数据库(生产常用)
bash
# 1. 拉取MySQL5.7镜像
docker pull mysql:5.7
# 2. 启动MySQL容器,配置密码、端口、字符集
docker run -d --name mysql5.7 \
-p 3307:3306 \
-e MYSQL_ROOT_PASSWORD=Root@123456 \
--restart always \
--privileged=true \
mysql:5.7 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci
参数说明:自定义宿主机3307端口避免与本地MySQL冲突,默认开启utf8mb4字符集,支持emoji表情存储。
八、Docker 数据卷核心技术(数据持久化)
8.1 数据卷核心作用
容器默认数据存储在可读写临时层,容器删除,数据丢失。数据卷(Volume)是宿主机与容器的文件挂载映射技术,实现数据持久化、文件同步、容器数据共享。
核心价值:
-
容器删除后,数据卷文件保留,实现数据持久化
-
宿主机直接修改文件,容器实时生效,无需进入容器
-
支持多容器挂载同一数据卷,实现容器间数据共享
8.2 三种数据卷挂载方式
8.2.1 指定路径挂载(生产首选)
手动指定宿主机绝对路径与容器路径映射,路径不存在自动创建
bash
# Tomcat挂载项目目录,实现项目持久化部署
docker run -d --name tomcat-web -p 8080:8080 \
-v /home/tomcat/webapps:/usr/local/tomcat/webapps \
-v /home/tomcat/logs:/usr/local/tomcat/logs \
tomcat:9.0-jdk11
8.2.2 具名挂载
自定义数据卷名称,Docker 统一管理存储路径,无需手动指定宿主机路径
bash
# 创建具名数据卷
docker volume create tomcat-data
# 挂载具名数据卷
docker run -d --name tomcat-test -p 8081:8080 \
-v tomcat-data:/usr/local/tomcat/webapps \
tomcat:9.0-jdk11
8.2.3 匿名挂载
仅指定容器路径,Docker 自动生成随机名称数据卷,适合临时使用
bash
docker run -d --name nginx-test -p 8082:80 \
-v /usr/share/nginx/html \
nginx:1.24.0
8.3 数据卷权限控制
挂载时可指定文件读写权限,保障数据安全
-
rw:默认权限,可读可写
-
ro:只读权限,容器仅可读取文件,无法修改
bash
# 只读挂载示例
docker run -d --name nginx-ro -p 8083:80 \
-v /home/nginx/html:/usr/share/nginx/html:ro \
nginx:1.24.0
8.4 MySQL数据卷持久化实战
挂载MySQL数据目录、配置目录,实现数据库数据永久保存
bash
# 创建宿主机挂载目录
mkdir -p /home/mysql/data /home/mysql/conf
# 启动MySQL并挂载数据卷
docker run -d --name mysql-prod \
-p 3308:3306 \
-e MYSQL_ROOT_PASSWORD=Root@123456 \
-v /home/mysql/data:/var/lib/mysql \
-v /home/mysql/conf:/etc/mysql/conf.d \
--restart always \
mysql:5.7
九、Dockerfile 自定义镜像(核心进阶)
官方镜像无法满足个性化业务需求,通过 Dockerfile 脚本自定义封装专属镜像,支持定制环境、预装依赖、配置启动命令,是企业级镜像构建核心方式。
9.1 Dockerfile 概述
Dockerfile 是纯文本配置文件,由多条指令组成,每条指令对应一层镜像层,Docker 逐行执行指令,自动构建定制化镜像。核心优势:版本可控、环境统一、批量复用。
Dockerfile 四大组成部分:基础镜像、维护信息、镜像构建指令、容器启动指令。
9.2 Dockerfile 13大核心指令详解
9.2.1 FROM(必选)
指定基础镜像,必须为文件第一行指令,所有自定义镜像均基于已有基础镜像构建
bash
# 基于JDK8基础镜像构建Java项目镜像
FROM openjdk:8-jdk-alpine
# 基于CentOS7基础镜像构建环境镜像
FROM centos:7
9.2.2 MAINTAINER
声明镜像维护者信息(姓名、邮箱),非必选,规范项目镜像管理
bash
MAINTAINER Java-Dev 123456@qq.com
9.2.3 WORKDIR
设置容器工作目录,等效于 cd 命令,后续所有指令均在该目录执行,目录不存在自动创建
bash
# 设置项目工作目录
WORKDIR /home/project
9.2.4 RUN
镜像构建阶段执行的命令,用于安装依赖、配置环境、初始化文件,每层RUN生成一个镜像层
bash
# 安装常用工具、更新依赖
RUN yum update -y && yum install -y wget curl net-tools
9.2.5 ADD/COPY
均用于拷贝文件到镜像,核心区别:ADD 支持自动解压压缩包、拉取网络资源;COPY 仅拷贝本地文件,纯净无额外操作,生产优先使用 COPY。
bash
# 拷贝本地jar包到镜像工作目录
COPY app.jar /home/project/
# 解压压缩包到指定目录
ADD tomcat.tar.gz /usr/local/
9.2.6 ENV
设置环境变量,全局生效,构建阶段、容器运行阶段均可调用
bash
# 设置项目端口、JDK环境变量
ENV SERVER_PORT=8080
ENV JAVA_OPTS="-Xms512m -Xmx1024m"
9.2.7 EXPOSE
声明容器对外暴露的端口,仅为标识作用,不会自动开放端口,端口映射需配合 run -p 命令
bash
# 暴露项目8080端口
EXPOSE 8080
9.2.8 CMD
容器启动时执行的命令,仅最后一条 CMD 生效,可被 docker run 命令覆盖
9.2.9 ENTRYPOINT
与 CMD 类似,为容器启动常驻命令,不可被覆盖,可配合 CMD 追加启动参数
9.2.10 VOLUME
声明镜像数据卷,自动创建持久化目录,用于存储日志、数据文件
9.2.11 USER
指定容器运行用户,默认 root,可配置普通用户提升安全性
9.2.12 ONBUILD
延迟执行指令,基于当前镜像二次构建时自动触发,用于通用基础镜像封装
9.2.13 LABEL
添加镜像元数据标签,记录版本、描述、用途,方便镜像管理
9.3 实战:自定义SpringBoot项目镜像
编写完整 Dockerfile,封装可直接部署的 Java 项目镜像,优化分层构建、减少镜像体积
9.3.1 编写Dockerfile文件
bash
# 基础镜像:轻量化JDK8
FROM openjdk:8-jdk-alpine
# 镜像维护信息
MAINTAINER Java-Dev Team
# 镜像标签
LABEL version="1.0" description="SpringBoot Web Project Image"
# 设置工作目录
WORKDIR /home/app
# 拷贝项目jar包
COPY demo-web.jar app.jar
# 配置JVM参数环境变量
ENV JAVA_OPTS="-Xms256m -Xmx512m -XX:+UseG1GC"
# 暴露项目端口
EXPOSE 8080
# 容器启动命令
ENTRYPOINT ["sh","-c","java $JAVA_OPTS -jar app.jar"]
9.3.2 构建镜像
bash
# 构建镜像 -t 指定镜像名称和版本 . 代表当前目录Dockerfile
docker build -t springboot-demo:1.0 .
# 查看构建完成的镜像
docker images | grep springboot-demo
9.3.3 启动自定义镜像容器
bash
docker run -d --name springboot-web -p 8080:8080 \
--restart always \
springboot-demo:1.0
9.4 镜像分层优化技巧
Docker 镜像分层缓存机制:未变更的指令层会复用缓存,大幅提升构建速度,优化核心技巧:
-
频繁变更的指令(拷贝项目文件、启动命令)放在文件末尾
-
合并多条 RUN 命令,减少镜像层数,降低镜像体积
-
使用 alpine 轻量化基础镜像,替代完整版系统镜像
bash
# 优化前(多层冗余)
RUN yum update -y
RUN yum install wget -y
RUN yum install curl -y
# 优化后(合并为一层,节省空间、提升速度)
RUN yum update -y && yum install -y wget curl && yum clean all
十、Docker 网络原理与网络配置
10.1 Docker0默认网桥原理
Docker 安装后自动创建 docker0 虚拟网桥,采用veth-pair虚拟设备对技术实现容器网络通信。每创建一个容器,会生成一对虚拟网卡,一端绑定容器,一端绑定 docker0 网桥,实现容器与宿主机、容器与容器之间的网络互通。
核心特点:虚拟设备转发效率高、无硬件损耗,容器删除后对应虚拟网卡自动销毁,无残留资源。
10.2 Docker四大网络模式
10.2.1 Bridge桥接模式(默认)
容器独立网络命名空间,连接 docker0 网桥,自动分配内网 IP,容器间可互通,是默认网络模式,适合绝大多数业务场景。
10.2.2 Host主机模式
容器与宿主机共享网络命名空间,无独立 IP,直接使用宿主机 IP 和端口,网络性能最优,适合高并发、端口固定的服务。
bash
# 指定host网络模式启动容器
docker run -d --name nginx-host --net=host nginx:1.24.0
10.2.3 None封闭模式
容器仅保留回环网卡,无任何网络配置,完全隔离外网和内网,安全性极高,适合纯本地运行、无需网络交互的任务。
bash
docker run -d --name test-none --net=none centos:7
10.2.4 Container共享模式
新容器与已有容器共享网络命名空间,共用 IP 和端口,适合服务附属容器(日志收集、监控组件)。
bash
# 与已有nginx容器共享网络
docker run -d --name nginx-log --net=container:nginx-web centos:7
10.3 容器互联与自定义网络
10.3.1 --link容器互联
实现容器间通过容器名称通信,无需依赖固定IP,解决IP变动导致的服务连接失败问题
bash
# 启动数据库容器
docker run -d --name mysql-link mysql:5.7
# 启动项目容器,关联数据库容器
docker run -d --name web-link --link mysql-link:mysql springboot-demo:1.0
10.3.2 自定义网桥网络(生产推荐)
自定义专属网段与网桥,隔离不同业务容器,提升网络安全性与稳定性
bash
# 1. 创建自定义网络,指定网段、网关
docker network create --driver bridge --subnet=192.168.100.0/24 --gateway=192.168.100.1 biz-network
# 2. 查看所有网络
docker network ls
# 3. 容器接入自定义网络
docker run -d --name web-biz --net biz-network -p 8080:8080 springboot-demo:1.0
# 4. 查看网络详细信息
docker network inspect biz-network
十一、Docker 镜像仓库管理
11.1 镜像仓库分类
-
Docker Hub公共仓库:官方公共仓库,免费存储开源镜像,适合个人学习
-
阿里云ACR仓库:国内加速镜像仓库,支持免费私有镜像存储,企业开发首选
-
企业私有仓库:自建Registry仓库,存储内部业务镜像,保障数据安全
11.2 镜像提交与打包推送
11.2.1 容器提交为镜像
将运行中的容器修改内容,保存为新镜像,适合快速封装定制化环境
bash
# 提交容器为镜像
docker commit -m "新增项目配置" -a "Java-Dev" springboot-web springboot-custom:1.0
11.2.2 推送镜像到阿里云ACR
bash
# 1. 登录阿里云镜像仓库
docker login registry.cn-hangzhou.aliyuncs.com -u 你的阿里云账号
# 2. 镜像标签重命名(适配仓库地址)
docker tag springboot-custom:1.0 registry.cn-hangzhou.aliyuncs.com/自定义命名空间/springboot:1.0
# 3. 推送镜像到远程仓库
docker push registry.cn-hangzhou.aliyuncs.com/自定义命名空间/springboot:1.0
# 4. 从远程仓库拉取镜像
docker pull registry.cn-hangzhou.aliyuncs.com/自定义命名空间/springboot:1.0
十二、Docker 核心架构与底层原理
12.1 C/S架构模型
Docker 采用标准客户端/服务端(C/S)架构:
-
服务端(Docker Daemon):后台守护进程,监听客户端请求,负责镜像构建、容器创建、资源调度等核心操作
-
客户端(Docker Client):用户执行 docker 命令的终端,通过 RESTful API 与服务端通信,发送操作指令
12.2 联合文件系统(UnionFS)原理
UnionFS 是 Docker 镜像分层存储的底层核心,支持将多个文件系统分层叠加、统一挂载展示。所有镜像层只读、独立存储,共享底层基础层,极大节省磁盘空间、提升镜像复用效率。
分层核心优势:
-
底层镜像更新后,所有依赖该镜像的上层镜像自动同步基础环境
-
相同基础层镜像共享存储,无需重复占用磁盘空间
-
构建缓存复用,未变更层级无需重新构建,大幅提升构建速度
十三、Docker Compose 多容器编排实战
13.1 Docker Compose 核心认知
在实际业务部署中,一个完整应用通常包含多个容器(如 Nginx、SpringBoot、MySQL、Redis),若手动逐个启动、配置端口、关联网络、挂载数据,操作繁琐且易出错,无法统一管理服务生命周期。
Docker Compose 是 Docker 官方推出的多容器编排工具 ,专为单主机多容器应用设计,核心作用是通过一个标准化的 docker-compose.yml 配置文件,统一定义所有服务的镜像、端口、数据卷、网络、依赖关系、启动规则,实现一键启动、一键停止、一键重启整套应用服务,彻底解决多容器运维繁琐问题。
核心定位:批量管理多容器、标准化多服务部署、简化微服务单机运维,是 Java 项目、中小型微服务部署的必备工具。
核心特性:
-
单一文件管理所有服务配置,环境统一、可复用、可版本控制
-
自动创建专属网络,实现服务间通过服务名互通,无需配置固定IP
-
支持启动顺序、服务依赖、健康检查,解决服务启动报错问题
-
一键启停整套服务,无需逐个操作容器,运维效率大幅提升
13.2 Docker Compose 安装与验证
新版 Docker 已默认集成 Compose 插件,无需单独安装,旧版本需手动安装,以下为通用安装与验证命令(CentOS/Ubuntu 通用)。
bash
# 1. 查看Compose版本(验证是否安装成功)
docker compose version
# 2. 若未安装,执行一键安装命令
yum install -y docker-compose-plugin
# 3. 安装完成后再次验证,输出版本号即成功
docker compose version
注意:新版命令为 docker compose(无横线),旧版为 docker-compose(有横线),语法完全兼容,推荐使用新版命令。
13.3 docker-compose.yml 核心语法详解
docker-compose.yml 是 Compose 的核心配置文件,采用 YAML 语法,层级严格、缩进敏感(必须使用2个空格缩进,禁止使用Tab),核心包含五大核心模块:services、networks、volumes、configs、secrets,日常开发重点使用前三者。
13.3.1 核心顶级模块
-
version:指定Compose配置文件版本,适配Docker版本,推荐3.8及以上通用版本
-
services:核心模块,定义所有需要编排的容器服务(每个服务对应一个容器)
-
networks:自定义网络配置,实现服务隔离与互通
-
volumes:统一声明数据卷,实现容器数据持久化
13.3.2 服务(services)常用核心参数
yaml
# 示例:单服务完整配置模板
version: "3.8" # 配置文件通用版本
services:
# 服务名称(自定义,服务间通信的域名)
springboot-app:
image: springboot-demo:1.0 # 指定镜像名称:版本
container_name: springboot-compose # 自定义容器名称
ports:
- "8080:8080" # 端口映射 宿主机端口:容器端口
volumes:
- app-logs:/home/app/logs # 挂载具名数据卷
- ./config:/home/app/config # 挂载宿主机目录
environment: # 配置环境变量
- SERVER_PORT=8080
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/test_db?useUnicode=true&characterEncoding=utf-8
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=Root@123456
depends_on: # 服务依赖,指定启动顺序
- mysql
restart: always # 容器重启策略,异常自动重启
networks:
- app-network # 加入自定义网络
healthcheck: # 服务健康检查(精准控制启动依赖)
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 10s
timeout: 5s
retries: 3
# 自定义网络
networks:
app-network:
driver: bridge
# 声明数据卷
volumes:
app-logs:
关键参数详解:
-
depends_on:定义服务启动依赖,当前服务会在依赖服务启动后再启动,但仅控制启动顺序,不等待依赖服务初始化完成
-
healthcheck:健康检查机制,弥补depends_on缺陷,确保依赖服务完全启动就绪后再启动当前服务,生产必备
-
restart:重启策略,always代表容器退出、服务器重启后自动拉起服务,保障服务高可用
-
服务名通信 :同一自定义网络下,服务可直接通过服务名称相互访问,无需使用IP地址
13.4 实战:SpringBoot+MySQL+Nginx 多容器完整编排
搭建企业常用完整业务架构:Nginx反向代理 + SpringBoot后端服务 + MySQL数据库,通过Compose一键编排部署,包含端口映射、数据持久化、服务依赖、健康检查、网络隔离全套配置。
13.4.1 项目目录结构
bash
/home/docker-compose-demo
├── docker-compose.yml # 核心编排配置文件
├── nginx/
│ └── nginx.conf # Nginx反向代理配置文件
├── mysql/
│ └── init.sql # MySQL初始化脚本
└── app.jar # SpringBoot项目jar包
13.4.2 编写Nginx配置文件(nginx.conf)
nginx
user nginx;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
# 反向代理配置,转发请求到SpringBoot服务
server {
listen 80;
server_name localhost;
location / {
# 直接使用compose服务名通信
proxy_pass http://springboot-app:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
13.4.3 编写MySQL初始化脚本(init.sql)
sql
# 创建项目数据库
CREATE DATABASE IF NOT EXISTS test_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# 创建测试表
USE test_db;
CREATE TABLE IF NOT EXISTS user (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
age INT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 插入测试数据
INSERT INTO user(username,age) VALUES ('test',20);
13.4.4 编写核心docker-compose.yml配置
yaml
version: "3.8"
# 定义所有业务服务
services:
# 1. MySQL数据库服务
mysql:
image: mysql:5.7
container_name: mysql-compose
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=Root@123456
- MYSQL_DATABASE=test_db
volumes:
- mysql-data:/var/lib/mysql # 数据持久化
- ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql # 初始化脚本
restart: always
networks:
- app-network
# MySQL健康检查,确保数据库完全启动
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-uroot", "-pRoot@123456"]
interval: 10s
timeout: 5s
retries: 5
# 2. SpringBoot后端服务
springboot-app:
build: . # 基于当前目录Dockerfile构建镜像
container_name: springboot-compose
ports:
- "8080:8080"
depends_on:
mysql:
condition: service_healthy # 等待MySQL健康检查通过再启动
environment:
- SERVER_PORT=8080
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/test_db?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=Root@123456
restart: always
networks:
- app-network
# 3. Nginx反向代理服务
nginx:
image: nginx:1.24.0
container_name: nginx-compose
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf # 挂载自定义配置
depends_on:
- springboot-app
restart: always
networks:
- app-network
# 自定义统一网络
networks:
app-network:
driver: bridge
# 统一声明数据卷
volumes:
mysql-data:
13.4.5 编写SpringBoot服务Dockerfile
在项目根目录创建Dockerfile,用于构建SpringBoot项目镜像
bash
FROM openjdk:8-jdk-alpine
MAINTAINER Java-Dev Team
WORKDIR /home/app
COPY app.jar app.jar
ENV JAVA_OPTS="-Xms256m -Xmx512m"
EXPOSE 8080
ENTRYPOINT ["sh","-c","java $JAVA_OPTS -jar app.jar"]
13.5 Docker Compose 高频实操命令
所有命令需在docker-compose.yml所在目录执行,核心命令全覆盖,适配日常运维。
bash
# 1. 后台启动所有服务(常用,生产必备)
docker compose up -d
# 2. 查看所有服务运行状态
docker compose ps
# 3. 实时查看所有服务日志(排查问题必备)
docker compose logs -f
# 4. 查看指定服务日志
docker compose logs -f springboot-app
# 5. 重启指定服务
docker compose restart springboot-app
# 6. 停止所有服务,不删除容器、网络、数据卷
docker compose stop
# 7. 启动已停止的服务
docker compose start
# 8. 停止并删除所有容器、网络(保留数据卷和镜像)
docker compose down
# 9. 停止并删除所有容器、网络、数据卷(彻底清空环境)
docker compose down -v
# 10. 重新构建镜像并启动服务(修改配置/代码后生效)
docker compose up -d --build
13.6 生产环境核心优化与避坑指南
13.6.1 服务启动顺序优化
单纯使用 depends_on 仅能控制容器启动顺序,无法保证服务初始化完成,极易出现数据库未初始化完成、业务服务连接失败的问题。生产环境必须搭配 healthcheck 健康检查 + condition: service_healthy,精准控制服务启动时机,确保依赖服务完全就绪后再启动当前服务。
13.6.2 数据持久化优化
数据库、日志类数据必须使用具名数据卷 或固定宿主机路径挂载,禁止使用匿名挂载。执行 docker compose down 不会删除具名数据卷,避免误操作导致数据丢失,保障生产数据安全。
13.6.3 网络通信优化
统一使用 Compose 自定义网络,默认隔离外部容器,仅当前编排服务互通,安全性更高;服务间通信强制使用服务名代替IP地址,避免容器重启IP变动导致服务连接异常。
13.6.4 生产重启策略配置
所有业务服务统一配置 restart: always,服务器重启、容器异常退出后自动拉起服务,无需人工干预,保障服务7*24小时可用。
13.6.5 常见报错避坑
-
YAML文件缩进错误:必须使用2个空格,禁止Tab键,缩进层级严格对应
-
端口冲突:启动前检查宿主机端口是否被占用,避免端口映射失败
-
权限不足:挂载宿主机目录时,确保目录权限足够,可临时添加 --privileged=true 提升权限
-
镜像不存在:确保配置的镜像名称、版本本地存在,或配置正确的镜像拉取地址