Docker 从入门到精通:原理、实战与生产运维全攻略
第九章:Docker 原理深入(从会用到真正懂)
前面我们一直在讲:
怎么使用 Docker。
现在开始讲:
Docker 为什么能做到这些?
如果你想成为 Docker 高手,这一章必须理解。
1. Docker 的整体架构
先看 Docker 内部结构:
id="3qz3rd"
用户
|
|
docker 命令
|
↓
Docker Client
|
|
Docker API
|
↓
Docker Daemon
|
+----------------+
| |
↓ ↓
containerd 镜像管理
|
↓
runc
|
↓
Linux Kernel
|
↓
Container
我们逐个解释。
2. Docker Client
你平时输入:
docker run nginx
这个:
docker
就是客户端。
它负责:
例如:
你输入:
docker ps
实际上:
不是 docker 自己管理容器。
它只是:
告诉 Docker 服务:
给我列一下容器。
3. Docker Daemon(核心)
Docker Daemon:
中文:
Docker 守护进程。
它是真正干活的人。
负责:
- 创建容器
- 删除容器
- 下载镜像
- 管理网络
- 管理 Volume
Linux 查看:
systemctl status docker
看到:
dockerd
就是它。
4. containerd
现在 Docker 不直接管理容器运行。
中间有:
containerd
它负责:
- 镜像管理
- 容器生命周期
结构:
Docker
↓
containerd
↓
runc
↓
Linux
5. runc 是什么?
runc:
真正创建容器的程序。
它根据 OCI 标准:
创建:
- Namespace
- Cgroups
- 文件系统
最后产生:
Linux 进程。
所以:
Docker 容器本质:
不是 Docker 创建的。
而是:
Docker
↓
containerd
↓
runc
↓
Linux进程
6. Docker 为什么能隔离容器?
核心:
Linux 内核技术。
两个:
最重要:
- Namespace
- Cgroups
7. Namespace(命名空间)
作用:
隔离视图。
让一个进程看到的是自己的世界。
例如:
普通 Linux:
执行:
ps aux
看到:
PID 1
nginx
PID 2
mysql
PID 3
bash
但是容器里面:
ps aux
可能:
PID 1
nginx
为什么?
因为:
Namespace 隔离了进程空间。
8. Namespace 有哪些?
Linux 有多个 Namespace:
PID Namespace
隔离进程。
容器认为:
自己是 PID 1。
例如:
宿主:
PID 5000 nginx
容器:
PID 1 nginx
实际上:
同一个进程。
Network Namespace
隔离网络。
每个容器:
拥有:
- 独立网卡
- IP
- 路由
例如:
容器:
eth0
172.18.0.2
Mount Namespace
隔离文件系统。
容器:
看到:
/bin
/etc
/usr
但是:
和宿主不同。
UTS Namespace
隔离主机名。
容器:
hostname
输出:
mysql-container
User Namespace
隔离用户。
例如:
容器 root:
不一定等于:
宿主 root。
9. Cgroups(资源限制)
Namespace:
解决:
“你看到什么”。
Cgroups:
解决:
“你能用多少资源”。
例如:
限制:
docker run \
--memory=512m \
--cpus=1 \
nginx
背后:
就是 Cgroups。
没有 Cgroups:
一个容器:
可能吃光:
CPU
内存
磁盘
导致:
服务器崩溃。
10. UnionFS 镜像分层原理
这是 Docker 镜像核心。
之前说:
镜像像千层蛋糕。
为什么?
因为:
Union File System。
例如:
Dockerfile:
FROM ubuntu
RUN apt install nginx
COPY index.html /
生成:
三层:
Layer 3
index.html
------------
Layer 2
nginx
------------
Layer 1
ubuntu
启动容器:
增加一层:
Container Layer
(可写)
--------------
Layer 3
--------------
Layer 2
--------------
Layer 1
重点:
镜像:
只读。
容器:
增加可写层。
11. 为什么删除容器数据消失?
因为:
数据在:
Container Writable Layer
删除:
这一层消失。
Volume:
为什么保存?
因为:
它在外部:
Container
|
Volume
|
Host Disk
12. Docker 为什么启动快?
虚拟机:
启动:
BIOS
↓
启动内核
↓
启动系统
↓
启动程序
需要:
几十秒。
Docker:
启动进程
↓
隔离环境
↓
运行
几秒。
因为:
没有启动完整操作系统。
13. Docker 镜像为什么下载快?
原因:
三个:
1. 分层
例如:
Ubuntu:
已经下载。
Python镜像:
复用。
2. 缓存
Docker 保存:
Layer
下一次:
不用重新下载。
3. 并行下载
多个 layer:
同时下载。
14. 容器和普通进程区别
很多人问:
Docker 容器是不是虚拟机?
不是。
实际上:
普通程序:
nginx
↓
Linux进程
Docker:
nginx
↓
Linux进程
+
Namespace
+
Cgroups
+
Filesystem
15. Docker 安全边界
注意:
容器不是绝对安全。
为什么?
因为:
共享:
Linux Kernel。
如果:
Kernel 有漏洞:
可能突破。
所以:
生产环境:
需要:
- 更新内核
- 最小权限
- 非 root 用户
- 镜像扫描
- 网络隔离
16. Docker 和 Kubernetes 的关系
很多人混淆。
Docker:
负责:
运行容器。
例如:
一台服务器
运行10个容器
Docker 很舒服。
但是:
100台服务器:
10000个容器。
怎么办?
需要:
Kubernetes。
关系:
Kubernetes
管理
↓
Docker / containerd
运行
↓
Containers
17. Docker 到底解决了什么?
总结:
以前:
开发环境
Python版本不同
依赖不同
服务器不同
部署失败
Docker:
程序
+
环境
+
依赖
↓
镜像
↓
哪里都能运行
18. 高手必须掌握的 Docker 排错思路
生产出问题:
不要乱试。
按层排查:
第一层:容器有没有运行?
docker ps
第二层:日志
docker logs
第三层:进入容器
docker exec -it
第四层:网络
docker network inspect
第五层:资源
docker stats
第六层:镜像
docker inspect
19. 到这里你的 Docker 知识体系
现在:
基础:
docker run
docker ps
↓
核心:
Image
Container
Volume
Network
↓
开发:
Dockerfile
Compose
↓
生产:
部署
日志
优化
↓
原理:
Namespace
Cgroups
containerd
runc
UnionFS
第十章:Docker 高级实战(工程师级)
现在你已经不是 Docker 小白了。
前面你掌握了:
Docker基础
↓
镜像
↓
容器
↓
Volume
↓
Network
↓
Dockerfile
↓
Compose
↓
底层原理
这一章开始进入企业真实环境。
目标:
能写生产级 Dockerfile,能优化镜像,能部署、维护、排查线上 Docker 服务。
一、Docker 镜像优化(企业必做)
很多新人写 Dockerfile:
FROM ubuntu
RUN apt update
RUN apt install python
COPY .
CMD python app.py
能运行。
但是生产不合格。
问题:
1. 镜像巨大
Ubuntu:
70MB+
安装各种工具:
可能:
1GB+
2. 攻击面增加
软件越多:
漏洞越多。
3. 下载慢
部署速度慢。
生产目标:
小
快
安全
二、选择合适基础镜像
普通:
FROM ubuntu
大小:
几百 MB。
slim
例如:
FROM python:3.12-slim
特点:
删除很多无用工具。
推荐:
生产常用。
alpine
例如:
FROM python:3.12-alpine
非常小。
但是:
有兼容问题。
例如:
某些 Python 库需要 gcc。
经验:
| 场景 | 选择 |
|---|---|
| 生产Python | python-slim |
| Java | temurin-jre |
| Node | node-slim |
| 极致优化 | alpine |
三、多阶段构建(重点)
这是企业最常用技术。
问题:
Java 项目。
编译需要:
JDK
Maven
源码
依赖
但是运行只需要:
JRE
jar包
错误:
FROM maven
COPY .
RUN mvn package
CMD java -jar app.jar
结果:
镜像:
包含:
- Maven
- 源码
- 编译工具
巨大。
多阶段:
# 第一阶段:编译
FROM maven:3.9 AS build
WORKDIR /app
COPY . .
RUN mvn package
# 第二阶段:运行
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY --from=build /app/target/app.jar .
CMD ["java","-jar","app.jar"]
结构:
阶段1
Maven
源码
↓
app.jar
阶段2
JRE
+
app.jar
结果:
可能:
1GB
↓
200MB
四、Dockerfile 最佳实践
1. 固定版本
不要:
FROM python
因为:
未来版本变化。
推荐:
FROM python:3.12.5-slim
2. 不使用 root
默认:
容器:
root。
风险:
攻击后权限过高。
推荐:
FROM nginx
RUN adduser app
USER app
3. 不安装无用工具
不要:
RUN apt install vim
生产:
不需要。
4. 清理缓存
例如:
错误:
RUN apt update
RUN apt install nginx
留下缓存。
正确:
RUN apt update \
&& apt install -y nginx \
&& rm -rf /var/lib/apt/lists/*
五、Docker 镜像安全扫描
企业不会直接使用镜像。
流程:
镜像
↓
扫描漏洞
↓
上线
常见工具:
Trivy
例如:
扫描:
trivy image nginx
发现:
CVE漏洞
为什么?
因为:
基础镜像可能包含:
漏洞软件。
六、私有镜像仓库
公司不会把所有镜像放 Docker Hub。
通常:
自己搭:
私有 Registry。
结构:
开发电脑
docker build
↓
公司Registry
↓
服务器pull
例如:
镜像:
nginx
变:
registry.company.com/shop/backend:v1
七、Docker Registry 工作流程
开发:
构建:
docker build -t backend:v1 .
登录:
docker login
打标签:
docker tag backend:v1 \
registry.com/backend:v1
上传:
docker push registry.com/backend:v1
服务器:
docker pull registry.com/backend:v1
八、Harbor(企业常用)
Harbor
很多公司使用。
它比普通 Registry 强:
提供:
- 用户管理
- 权限控制
- 镜像扫描
- 审计
- Web界面
结构:
开发
|
docker push
↓
Harbor
|
docker pull
↓
生产服务器
九、Docker + CI/CD 自动化
真实公司:
不会每天:
手动:
docker build
docker push
而是自动。
流程:
开发提交代码
↓
Git
↓
CI系统
↓
自动测试
↓
docker build
↓
镜像仓库
↓
服务器部署
例如:
代码:
git push
自动:
1. 拉代码
2. 构建镜像
3. 扫描
4. 上传
5. 更新服务器
十、GitLab CI 示例
文件:
.gitlab-ci.yml
例如:
build:
script:
- docker build -t app:v1 .
- docker push app:v1
提交代码:
自动执行。
十一、Jenkins + Docker
传统企业大量使用。
流程:
Git
↓
Jenkins
↓
Docker Build
↓
Docker Push
↓
服务器部署
十二、Docker 生产监控
线上不能只看:
docker ps
需要监控。
关注:
CPU
CPU使用率
内存
Memory
网络
流量
容器状态
是否重启
命令:
docker stats
企业:
常用:
- Prometheus
- Grafana
组成:
Docker
↓
Prometheus
↓
Grafana
↓
监控面板
十三、Docker 日志管理
默认:
json-file
长期:
可能撑爆磁盘。
查看:
docker info
限制:
daemon.json:
{
"log-driver":"json-file",
"log-opts":{
"max-size":"100m",
"max-file":"3"
}
}
意思:
单个日志:
最多100MB。
保留3个文件。
十四、Docker 健康检查
问题:
容器运行:
不代表服务正常。
例如:
容器 alive
但是
Java死循环
添加:
Dockerfile:
HEALTHCHECK CMD curl http://localhost:8080
Compose:
healthcheck:
test:
- CMD
- curl
- localhost:8080
效果:
Docker知道:
服务健康状态。
十五、自动恢复
生产:
一定:
restart: always
例如:
服务器重启:
服务器开机
↓
Docker启动
↓
容器自动启动
常见:
restart: unless-stopped
意思:
除非人为停止。
十六、Docker 网络生产设计
不要所有服务一个网络。
推荐:
分层:
公网网络
|
↓
Nginx
内部网络
|
↓
Backend
数据库网络
|
↓
MySQL
例如:
networks:
frontend:
backend:
database:
隔离。
十七、Docker 数据备份策略
数据库:
不能只靠 Volume。
生产:
至少:
每日备份
例如:
凌晨3点
mysqldump
↓
备份文件
异地备份
例如:
服务器:
↓
对象存储。
十八、Docker 常见线上事故
事故1:
磁盘爆满
原因:
日志。
解决:
docker system prune
事故2:
容器不停重启
查看:
docker ps
然后:
docker logs
事故3:
数据库数据丢失
原因:
没有 Volume。
事故4:
服务访问不了
检查:
顺序:
docker ps
docker logs
docker network inspect
端口:
docker port
十九、Docker 运维黄金流程
上线:
代码提交
↓
CI构建
↓
Docker镜像
↓
漏洞扫描
↓
推送仓库
↓
服务器拉取
↓
Compose更新
↓
监控观察
二十、现在你的 Docker 能力等级
大概:
初级
会:
docker run
docker ps
docker pull
中级
会:
Dockerfile
Volume
Network
Compose
高级
会:
镜像优化
安全
CI/CD
私有仓库
监控
生产部署
你现在已经进入:
高级 Docker 使用者。
更多推荐


所有评论(0)