作者:王仕宇(JavaPub)
前言
很多开发者学习 Docker,只停留在:
dockerrun nginx然后认为 Docker 就是一个启动程序的工具。
但真正进入企业开发之后,你会发现:
- 为什么 Docker 启动速度这么快?
- 容器和虚拟机有什么区别?
- 为什么删除容器数据没了?
- 为什么线上 Docker 容器会越来越大?
- 为什么生产环境一定使用 Docker Compose?
- 为什么 Kubernetes 基于 Docker 思想发展?
理解 Docker 底层原理,才能真正掌握容器化技术。
一、Docker 到底解决了什么问题?
在传统开发模式中:
开发环境:
Mac Node 20 MySQL 8 Redis 7 Python 3.12测试环境:
Linux Node 18 MySQL 5.7 Redis 6 Python 3.10生产环境:
Linux Node 16 MySQL 5.7 Redis 6结果:
开发:
我本地可以运行。
上线:
为什么服务器不能运行?
Docker 解决的问题:
应用 + 运行环境 + 依赖 一起打包形成:
Docker Image无论在哪里:
开发机器 服务器 云服务器 Kubernetes运行结果保持一致。
这就是:
Build Once, Run Anywhere
二、Docker 架构
Docker 主要由三部分组成:
Docker Client | | Docker Daemon | ---------------- Image Container1. Docker Client
就是我们使用的命令:
dockerrun nginx实际上发送请求:
docker CLI ↓ Docker API ↓ Docker Daemon2. Docker Daemon
后台服务:
Linux:
systemctl statusdocker负责:
- 创建容器
- 管理镜像
- 管理网络
- 管理存储
3. Docker Registry
镜像仓库:
例如:
Docker Hub:
hub.docker.com流程:
docker pull nginx 本地没有 ↓ Docker Hub下载 ↓ 保存Image三、Docker 容器为什么这么快?
很多新人认为:
Docker = 小型虚拟机
实际上不是。
虚拟机架构
传统虚拟机:
物理服务器 ↓ Hypervisor ↓ Guest OS ↓ 应用例如:
VMware
VirtualBox
需要完整操作系统。
Docker 架构
Docker:
服务器 ↓ Linux Kernel ↓ Docker ↓ Container ↓ 应用多个容器共享:
- Linux Kernel
- 系统资源
所以启动:
虚拟机:
分钟级Docker:
秒级四、Docker 三大核心技术
Docker 能实现隔离,主要依靠 Linux:
- Namespace
- Cgroups
- UnionFS
1. Namespace:隔离环境
Namespace 负责:
看起来像独立系统。
例如:
容器 A:
PID: 1 nginx 2 worker容器 B:
PID: 1 mysql实际上:
宿主机:
PID: 100 nginx 200 mysql但是容器内部认为:
自己就是系统Namespace 类型:
| 类型 | 作用 |
|---|---|
| PID | 进程隔离 |
| NET | 网络隔离 |
| MNT | 文件系统隔离 |
| UTS | 主机名隔离 |
| IPC | 进程通信隔离 |
2. Cgroups:资源限制
如果一个容器占满 CPU:
服务器可能挂掉。
Cgroups:
控制:
- CPU
- 内存
- IO
例如:
限制 MySQL:
dockerrun\--memory=512m\mysql表示:
最多使用:
512MB RAM限制 CPU:
dockerrun\--cpus=2\nginx最多:
2个CPU核心3. UnionFS:镜像分层
Docker 镜像不是一个完整文件。
例如:
nginx:
Layer 1 Ubuntu Layer 2 nginx Layer 3 配置文件 Layer 4 启动脚本多个镜像共享基础层。
好处:
减少空间。
查看:
dockerhistorynginx五、Docker 镜像到底是什么?
镜像:
本质:
一个只读模板。
例如:
Dockerfile:
FROM ubuntu RUN apt update RUN apt install nginx COPY index.html / CMD nginx执行:
dockerbuild-tmy-nginx.生成:
Image my-nginx运行:
dockerrun my-nginx产生:
Container关系:
Image ↓ Container类似:
类 ↓ 对象六、Dockerfile 最佳实践
1. 使用官方基础镜像
推荐:
FROM node:20-alpine不要:
FROM ubuntu 自己安装node原因:
- 镜像小
- 安全
- 快速
2. 减少镜像体积
错误:
RUN apt update RUN apt install xxx多个 Layer。
优化:
RUN apt update \ && apt install xxx \ && rm -rf /var/lib/apt/lists/*3. 使用 .dockerignore
类似:
.gitignore
例如:
node_modules .git .env避免进入镜像。
七、Docker 数据持久化
很多新人踩坑:
启动 MySQL:
dockerrun mysql创建数据:
users orders products删除:
dockerrmmysql数据全部消失。
原因:
容器是临时的。
解决:
Volume。
结构:
宿主机 /data/mysql | | 容器 /var/lib/mysql创建:
dockervolume create mysql-data使用:
dockerrun\-vmysql-data:/var/lib/mysql\mysql八、Docker 网络原理
容器默认:
container network docker0查看:
ipaddr创建:
app | docker network | mysql推荐:
dockernetwork create app-net启动:
MySQL:
dockerrun\--networkapp-net\mysql应用:
dockerrun\--networkapp-net\backend然后:
代码连接:
MYSQL_HOST=mysql不需要写 IP。
九、Docker Compose 企业实践
实际项目:
不会启动:
docker run mysql docker run redis docker run nginx而是:
docker-compose.yml
例如:
version:"3"services:mysql:image:mysql:8environment:MYSQL_ROOT_PASSWORD:123456volumes:-mysql-data:/var/lib/mysqlredis:image:redisnginx:image:nginxports:-80:80volumes:mysql-data:启动:
dockercompose up-d停止:
dockercompose down十、生产环境 Docker 优化
1. 不使用 root 用户
Dockerfile:
USER app提高安全性。
2. 健康检查
HEALTHCHECK CMD curl http://localhostDocker 自动判断:
服务是否正常。
3. 日志管理
不要:
日志写文件 无限增长推荐:
stdout ↓ Docker logging ↓ ELK4. 固定版本
不要:
mysql:latest生产:
mysql:8.0.36避免升级导致故障。
十一、Docker 常见排查命令
查看日志
dockerlogs-fapp查看资源
dockerstats查看详细信息
dockerinspect app查看进程
dockertopapp进入容器
dockerexec-itappsh十二、Docker 与 Kubernetes 的关系
Docker:
负责:
运行一个容器Kubernetes:
负责:
管理大量 Docker 容器例如:
100 台服务器:
1000 个容器Kubernetes 自动:
- 创建
- 删除
- 扩容
- 故障恢复
关系:
Docker ↓ Container ↓ Kubernetes ↓ 云原生平台十三、Docker 学习路线
第一阶段
掌握:
docker run docker ps docker images docker logs docker exec第二阶段
学习:
Dockerfile Volume Network Compose第三阶段
深入:
Namespace Cgroups 镜像优化 安全 CI/CD Kubernetes总结
Docker 不只是一个部署工具。
它改变了软件交付方式:
以前:
代码 ↓ 配置环境 ↓ 部署 ↓ 解决环境问题现在:
代码 ↓ Docker Image ↓ 任何服务器运行对于后端开发者:
Java、Go、Python、Node.js、AI 服务部署,
Docker 已经成为现代工程体系的重要基础。
作者:王仕宇 JavaPub