Docker知识点详解
Docker 是一个基于 Linux 内核能力实现的开源应用容器引擎,依托 命名空间(Namespaces) 与 控制组(cgroups) 实现轻量级进程隔离,支持将应用程序及其依赖项统一打包为标准化容器镜像,实现跨环境的敏捷交付与一致性运行。
1. 概述与核心机制#
1.1 核心特性与虚拟化差异#
容器技术与传统虚拟机(VM)在底层实现上有本质区别:
- 进程级轻量隔离:容器共享宿主机的操作系统内核,不需要像虚拟机那样虚拟化完整的 Guest OS 与虚拟硬件,秒级启动且系统资源开销极小。
- 独立的文件系统视图:容器内部拥有独立的用户态文件系统环境(例如 /bin、/etc、/usr、/app),能够独立执行 Linux 用户态程序与服务进程。
- 环境交付一致性:通过将代码、运行依赖与环境变量整体封装,实现“一次构建,随处运行”,消除开发、测试与生产环境不一致的痛点。
1.2 Windows 与 WSL2 协同运行模式#
在 Windows 环境下,Docker Desktop 并非直接运行于 Windows 原生内核之上,而是深度集成并依赖 WSL2(Windows Subsystem for Linux 2)提供的真实 Linux 内核环境:
- 架构协同关系:Windows 充当宿主操作系统;WSL2 虚拟机实例提供 Linux 内核调用支持;Docker Desktop 统一管理 Docker 守护进程引擎与图形化控制台。
- 最佳工程实践:建议将项目代码与挂载文件直接存放在 WSL 的 Linux 本地文件系统内(如 /home/user/…),避免跨跨系统 9P 文件协议读写带来的显著性能损耗。
2. 架构与核心概念#
Docker 采用标准的 C/S(客户端/服务端)架构,客户端工具与后端守护进程通过 REST API、UNIX 套接字或网络接口进行交互。
2.1 架构角色与核心概念#
| 角色/组件 | 描述与核心职责 |
|---|---|
| Docker Client | 命令行交互工具(docker CLI),负责向服务端分发构建、运行与管理指令。 |
| Docker Daemon (dockerd) | 常驻后台的守护进程,负责管理镜像、容器、存储卷与虚拟网络等核心对象。 |
| 镜像(Image) | 包含了应用程序及其完整运行依赖的只读层叠模板,用于生成容器运行时实例。 |
| 容器(Container) | 镜像的可运行实例,在镜像只读层之上附加读写层,具备隔离的网络与运行时环境。 |
| 镜像仓库(Registry) | 集中存储与分发容器镜像的中心服务,分为公有仓库(如 Docker Hub)与私有仓库(如 Harbor)。 |
| Dockerfile | 声明镜像构建流程的文本配置文件,逐层定义基础环境、依赖安装与启动参数。 |
| Docker Compose | 用于定义和编排多容器协同运行的工具,通过声明式 YAML 文件管理全栈服务。 |
2.2 Dockerfile 与 Compose 的职责划分#
两者处于不同层级的交付链路中,职责边界清晰:
- Dockerfile 聚焦“单镜像定义”:面向单一组件,定义底层镜像选型、文件拷贝、依赖安装与默认入口程序,类似“组装单台计算节点”。
- Docker Compose 聚焦“多服务编排”:面向系统级拓扑,定义容器互联、环境变量注入、端口映射、挂载卷以及服务依赖顺序,类似“构建多节点网络拓扑”。
3. 安装与环境验证#
3.1 Linux 系统环境安装#
(1) Ubuntu / Debian 系列(APT 源安装):
1# 1. 更新索引并安装基础前置工具
2sudo apt-get update
3sudo apt-get install -y ca-certificates curl gnupg
4
5# 2. 添加 Docker 官方 GPG 密钥
6sudo install -m 0755 -d /etc/apt/keyrings
7curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
8sudo chmod a+r /etc/apt/keyrings/docker.gpg
9
10# 3. 写入软件源配置
11echo \
12 "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
13 $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
14 sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
15
16# 4. 安装 Docker 核心引擎与组件
17sudo apt-get update
18sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
(2) CentOS / RHEL 系列(YUM / DNF 安装):
1# 1. 安装 yum 实用工具包
2sudo yum install -y yum-utils
3
4# 2. 配置官方镜像源仓库
5sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
6
7# 3. 安装 Docker 核心组件
8sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
3.2 版本验证与连通性测试#
安装完成后,执行以下命令验证安装状态与引擎运行状况:
1# 查看客户端与服务端版本详情
2docker --version
3
4# 验证系统信息与运行架构
5docker info
6
7# 运行官方测试容器验证完整拉取与执行链路
8docker run hello-world
4. 服务生命周期与核心配置#
4.1 服务生命周期管理#
| 操作 | 命令 |
|---|---|
| 启动 Docker 守护进程 | sudo systemctl start docker |
| 停止 Docker 守护进程 | sudo systemctl stop docker |
| 重启 Docker 守护进程 | sudo systemctl restart docker |
| 查看 Docker 服务状态 | sudo systemctl status docker |
| 设置开机自启 | sudo systemctl enable docker |
| 禁止开机自启 | sudo systemctl disable docker |
4.2 守护进程核心配置模板#
默认全局配置文件路径:/etc/docker/daemon.json
1{
2 "registry-mirrors": [
3 "https://registry.docker-cn.com",
4 "https://mirror.baidubce.com"
5 ],
6 "log-driver": "json-file",
7 "log-opts": {
8 "max-size": "100m",
9 "max-file": "3"
10 },
11 "data-root": "/var/lib/docker",
12 "exec-opts": [
13 "native.cgroupdriver=systemd"
14 ],
15 "live-restore": true
16}
- 配置项说明:
- registry-mirrors:配置镜像拉取加速地址,缓解公网下载超时问题。
- log-driver 与 log-opts:限制容器日志单文件最大容量为 100MB 且最多保留 3 个副本,防止磁盘被日志耗尽。
- data-root:指定镜像、容器与卷的本地存储持久化主目录。
- exec-opts:将底层 cgroup 驱动设置为 systemd,与 Kubernetes 及高版本 Linux 宿主机规范对齐。
- live-restore:在 Docker 守护进程发生重启或热升级时,保持运行中的容器继续工作不中断。
5. 常用命令与基础操作#
5.1 镜像与容器常用操作#
| 命令 | 操作描述 | 操作分类 |
|---|---|---|
| docker pull nginx:alpine | 从仓库拉取指定标签镜像 | 镜像检索与下载 |
| docker images | 查看本地已下载的镜像列表 | 镜像清单查看 |
| docker rmi nginx:alpine | 依据名称或 ID 删除镜像 | 镜像删除 |
| docker run -d -p 80:80 –name mynginx nginx:alpine | 映射端口并以后台守护模式运行 | 容器后台运行 |
| docker ps | 查看当前正在运行的容器 | 容器列表查看 |
| docker ps -a | 查看所有容器(含已停止状态) | 全部容器查看 |
| docker logs -f mynginx | 持续跟踪查看容器控制台输出日志 | 查看容器日志 |
| docker exec -it mynginx sh | 进入正在运行的容器执行 Shell 调试 | 交互式终端接入 |
| docker stop mynginx && docker rm mynginx | 停止指定容器并清除容器实例 | 容器停止与删除 |
5.2 资源清理与状态诊断#
| 命令 | 作用说明 | 诊断操作 |
|---|---|---|
| docker image prune -f | 清除因重新构建而无标签的未引用镜像 | 删除虚悬镜像 |
| docker system prune -f | 清理已停止容器、未挂载网络与悬空镜像 | 深度系统清理 |
| docker top mynginx | 查看目标容器内部正执行的系统进程 | 容器进程查看 |
| docker stats | 实时输出各容器的 CPU、内存、网络 IO 统计 | 资源动态监控 |
5.3 Docker Compose 核心控制命令#
| 命令 | 作用说明 | 操作分类 |
|---|---|---|
| docker compose up -d | 后台拉起并按依赖顺序启动全部服务 | 启动编排 |
| docker compose up -d –build | 强制重新构建包含 build 声明的镜像并启动 | 重新构建 |
| docker compose down | 停止并移除容器、默认网络,保留持久化卷 | 停止并清除 |
| docker compose ps | 列出当前 Compose 文件定义的服务容器状态 | 查看编排状态 |
| docker compose logs -f | 聚合输出所有服务的标准控制台日志 | 追踪多服务日志 |
| docker compose config | 解析并展开合并当前 YAML 配置文件 | 配置语法校验 |
6. 核心运行机制与网络端口流向#
6.1 镜像分层与联合文件系统(UnionFS)#
Docker 镜像由一系列只读层(Read-Only Layers)通过联合挂载技术组合而成:
- 写时复制(Copy-on-Write, CoW):下层镜像层保持不可变只读。当容器启动时,Docker 会在其顶部附加一个薄薄的容器读写层(Container Layer)。容器内任何增删改操作均发生在读写层,底层文件修改时触发复制操作,保障了基础镜像的不可变性与复用性。
- 存储效率与缓存复用:相同的镜像层在宿主机磁盘上仅需持久化存储一份,构建 Dockerfile 时若某一步骤前置指令未变,构建引擎将直接复用本地缓存层,极大地加快构建效率。
6.2 容器网络模式与端口流向机制#
Docker 默认提供多种网络驱动:
- bridge(桥接网络):默认驱动。每个容器被分配独立网络栈与内部虚拟 IP,通过 docker0 网桥或自定义用户桥接网络互通。
- host(主机网络):容器直接共享宿主机的网络命名空间,完全不隔离端口,效率最高但易产生端口冲突。
- none(无网络):封闭容器网络栈,仅保留本地回环接口,适用于安全计算隔离场景。
在微服务工程实践中,典型业务请求的端口流向存在两种主流路径:
- 路径一:宿主机直连访问后端应用 客户端请求 → 宿主机端口 9090 → Docker iptables 端口映射规则转发 → 容器端口 8080 → Spring Boot 应用服务。
- 路径二:通过 Nginx 边缘网关反向代理 客户端请求 → 宿主机对外端口 80 → Nginx 容器代理层识别 URL → 自定义 Bridge 网络域名解析(http://backend:8080)→ 后端容器端口 8080。
7. 典型实战场景#
7.1 单体应用构建:Spring Boot 基础 Dockerfile#
目标:将 Java 后端编译产物封装为独立轻量镜像并以后台容器运行。
Dockerfile 默认保存于项目根目录:Dockerfile
1# 采用精简版 Temurin OpenJDK 基础镜像
2FROM eclipse-temurin:17-jre-alpine
3
4# 设置容器内部默认工作主目录
5WORKDIR /app
6
7# 拷贝编译好的可执行 JAR 包至容器镜像内
8COPY target/*.jar app.jar
9
10# 修正容器系统时区为亚洲上海
11RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
12 && echo "Asia/Shanghai" > /etc/timezone
13
14# 声明应用暴露的通信端口
15EXPOSE 8080
16
17# 配置容器启动运行命令
18ENTRYPOINT ["java", "-jar", "app.jar"]
构建与启动执行命令:
1# 1. 在 Dockerfile 所在目录下触发镜像构建
2docker build -t my-springboot-app:1.0 .
3
4# 2. 映射宿主机 8080 端口并后台启动容器
5docker run -d -p 8080:8080 --name my-app my-springboot-app:1.0
7.2 前后端全栈编排:Docker Compose 综合部署#
目标:通过单一 Compose 配置文件协调拉起 MySQL 8.0 数据存储、Spring Boot 后端 API 以及承载 Vue 静态资源的反代 Nginx 前端。
(1) Nginx 边缘反向代理配置文件:nginx/default.conf
1server {
2 listen 80; # 监听容器内部 80 端口
3 server_name localhost; # 默认服务器名称
4
5 # 前端构建产物托管
6 location / {
7 root /usr/share/nginx/html; # 静态文件根目录
8 index index.html index.htm; # 默认首页索引
9 try_files $uri $uri/ /index.html; # 支持 Vue 客户端路由模式
10 }
11
12 # 后端 REST 接口反向代理
13 location /api/ {
14 proxy_pass http://backend:8080/; # 借助 Compose 内置 DNS 路由到后端服务
15 proxy_set_header Host $host; # 透传真实主机请求头
16 proxy_set_header X-Real-IP $remote_addr; # 透传客户端实际 IP
17 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 透传链路代理 IP
18 }
19}
(2) 多服务综合编排定义文件:docker-compose.yml
1version: "3.8"
2
3services:
4 # 关系型数据库存储服务
5 db:
6 image: mysql:8.0 # 声明官方 MySQL 镜像版本
7 container_name: library-mysql # 指定容器运行名称
8 restart: always # 宿主机重启或服务异常时自动重启
9 environment:
10 MYSQL_ROOT_PASSWORD: RootPassword123 # 设置 root 根密码
11 MYSQL_DATABASE: library # 初始化创建的业务数据库
12 TZ: Asia/Shanghai # 设置数据库系统时区
13 volumes:
14 - ./mysql/data:/var/lib/mysql # 持久化数据库存储目录
15 - ./mysql/init:/docker-entrypoint-initdb.d # 挂载初始化 SQL 脚本目录
16 networks:
17 - library-net # 接入内部虚拟网络
18
19 # 后端业务微服务
20 backend:
21 image: springboot:latest # 使用本地构建或私服拉取的后端镜像
22 container_name: library-backend # 指定后端容器名称
23 restart: always # 进程退出时自动重启
24 depends_on:
25 - db # 声明先于 backend 启动 db 数据库
26 environment:
27 SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/library?useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=GMT%2B8 # 连接串使用 db 主机名
28 SPRING_DATASOURCE_USERNAME: root # 数据库连接账号
29 SPRING_DATASOURCE_PASSWORD: RootPassword123 # 数据库连接密码
30 networks:
31 - library-net # 接入同一虚拟通信网络
32
33 # 前端 Web 与反向代理网关
34 nginx:
35 image: nginx:alpine # 采用轻量 Alpine 基础镜像
36 container_name: library-nginx # 指定网关容器名称
37 restart: always # 服务故障时保持重启
38 ports:
39 - "80:80" # 将宿主机 80 端口映射到 Nginx 容器 80 端口
40 volumes:
41 - ./frontend/dist:/usr/share/nginx/html # 挂载前端打包静态资源
42 - ./nginx/default.conf:/etc/nginx/conf.d/default.conf # 挂载自定义站点配置
43 depends_on:
44 - backend # 确保后端拉起后再启动网关
45 networks:
46 - library-net # 共享内部桥接网络
47
48networks:
49 # 自定义桥接通信网络
50 library-net:
51 driver: bridge # 采用标准桥接驱动
(3) 编排部署启动与验证:
1# 一键拉起并后台运行全部服务
2docker compose up -d
3
4# 检查各微服务运行与端口映射状态
5docker compose ps
6
7# 跟踪查看后端服务启动初始化日志
8docker compose logs -f backend
7.3 镜像交付流:Docker Hub 推送与异地拉取#
目标:将本地构建完成的镜像推送至公共仓库,并在远程目标节点拉取部署。
(1) 镜像打标与推流:
1# 1. 登录 Docker Hub 凭据
2docker login
3
4# 2. 为目标镜像附加包含命名空间的正式标签
5docker tag springboot:latest yourname/springboot-library:v1.0
6
7# 3. 推送镜像至中心仓库
8docker push yourname/springboot-library:v1.0
(2) 远程生产端拉取与组织结构: 标准生产部署目录推荐规范:
1project/
2├── docker-compose.yml # 编排声明文件
3├── nginx/
4│ └── default.conf # 边缘路由配置
5├── frontend/
6│ └── dist/ # 前端静态发布包
7└── mysql/
8 ├── data/ # 宿主机数据持久卷
9 └── init/
10 └── init.sql # 数据库初始化表结构
远程一键拉取并拉起编排:
1# 进入工程根目录并启动
2docker compose pull
3docker compose up -d
8. 性能优化与构建最佳实践#
8.1 镜像体积精简(多阶段构建)#
在工程化实践中,编译环境(如 Maven、JDK)与运行时环境(仅需 JRE)应当分离,利用多阶段构建(Multi-stage builds)可使产物镜像体积缩小 70% 以上:
1# 阶段一:源码构建阶段
2FROM maven:3.9-eclipse-temurin-17 AS builder
3WORKDIR /build
4COPY pom.xml .
5COPY src ./src
6RUN mvn clean package -DskipTests
7
8# 阶段二:精简运行阶段
9FROM eclipse-temurin:17-jre-alpine
10WORKDIR /app
11COPY --from=builder /build/target/*.jar app.jar
12EXPOSE 8080
13ENTRYPOINT ["java", "-jar", "app.jar"]
8.2 运行时资源配额控制#
为了防止单个故障容器消耗过多系统资源导致宿主机宕机,建议在 Compose 或启动命令中声明 CPU 与内存上限:
1services:
2 backend:
3 image: springboot:latest
4 deploy:
5 resources:
6 limits:
7 cpus: '2.0' # 最多使用 2 个 CPU 核心
8 memory: 2048M # 最大内存配额为 2GB
9 reservations:
10 cpus: '0.5' # 预留保障资源为 0.5 核
11 memory: 512M # 预留初始分配为 512MB
9. 常见问题与排错指南#
| 故障现象 | 根因分析 | 排查与修复方案 |
|---|---|---|
| 容器启动后立即退出 (Exited 0 或 1) | 容器前台没有常驻进程。Docker 依赖主进程(PID 1)生命周期维持运行,进程执行完毕即终止。 | 检查 ENTRYPOINT/CMD 是否为后台运行命令;若为测试环境可补充 tail -f /dev/null 保持前台等待。 |
| 端口已被占用 (bind: address already in use) | 宿主机对应端口已被其他宿主机原生服务或其他容器绑定占用。 | 执行 netstat -tuln | grep <端口号> 或 lsof -i:<端口号> 定位冲突进程,修改 Compose 映射主机端口。 |
| 容器间域名无法解析 (Unknown host) | 容器使用了默认 bridge 网络,未加入用户自定义网络,默认 bridge 不支持基于容器名的 DNS 服务发现。 | 将互联服务置于同一个由 networks 显式声明的自定义 bridge 网络中,使用服务名访问。 |
| 磁盘空间被持续占满 (No space left on device) | 容器日志无限制追加,或残留大量未清理的虚悬镜像与构建缓存。 | 配置 /etc/docker/daemon.json 中的 log-opts max-size;定期执行 docker system prune -a –volumes 清理。 |
| WSL2 宿主内存占用失控 (Vmmem 过高) | WSL2 默认按宿主机总内存的 50%~80% 动态分配上限,Java 或高负载构建后不会主动释放页面缓存。 | 在 Windows 用户目录创建 %USERPROFILE%.wslconfig,写入 [wsl2] memory=8GB 显式约束内存。 |
10. 总结#
Docker 通过基于 Linux 命名空间与控制组的轻量级容器化技术,重构了软件工程的交付与运维范式;在微服务与全栈开发实践中,结合 Dockerfile 的不可变镜像定义与 Docker Compose 的声明式服务编排,能够极大简化系统部署流程并确保跨环境运行的一致性与稳定性。