第九章:Docker 原理深入(从会用到真正懂)

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 内核技术。

两个:

最重要:

  1. Namespace
  2. 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 使用者。


Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐