一句话 讲述容器本质(docker为例2025)
一、虚拟机(VM/KVM vs docker):
Guest OS:虚拟机每台都要装完整系统(像租整套房),Docker直接用宿主机内核(像合租)。
资源占用:生产环境跑Nginx,虚拟机至少512MB内存,Docker容器64MB搞定。一台32核物理机,虚拟机只能开15台,Docker能跑200+容器。
启动速度:虚拟机从BIOS启动要2-3分钟,Docker容器0.5秒拉起。以前做CI/CD等虚拟机启动急死人,现在秒级扩容。
二、docker工作原理
1. 底层靠三个Linux内核技术
Cgroups:限制进程组的资源使用上限,比如CPU核数、内存大小、磁盘IO、网络带宽等。生产环境里,用它防止一个容器把整台服务器资源吃光。此外,还能够对进程进行优先级设置,资源的计量以及资源的控制(比如:将进程挂起和恢复等操作)。
Namespaces:搞隔离。生产环境跑多个Java服务时,每个容器有自己的PID(进程ID从1开始)、网络(独立IP和端口)、文件系统(/目录隔离)。比如我们容器里的Nginx监听80端口,宿主机和其他容器完全不受影响。
UnionFS:(如OverlayFS):做镜像分层。Dockerfile里每行命令生成一层,基础镜像(如Alpine 5MB)+ JDK层 + 应用层。生产环境推新版本时,只传变更的那层,100台机器10秒全部更新完。
2. 架构分三层干活
Docker Engine(dockerd):对外接口。docker run命令就是它接收,生产环境用它做CI/CD流水线触发。
containerd:管容器生命周期。负责拉镜像、创建容器、监控状态。K8s底层直接调containerd,绕过dockerd。
runc:真正创建容器的工具。调用Linux系统调用(clone()、mount()等)设置Namespaces/Cgroups。每次docker run,背后是runc fork出一个新进程。
3. 从镜像到容器的实际流程
以部署Spring Boot应用为例:
- 构建镜像:
docker build把JAR包+JRE打包成镜像,分层存储(基础层复用,应用层增量)。 - 运行容器:
docker run -m 1g -c 2命令触发:- containerd从镜像仓库拉取镜像(省带宽,只拉缺失层)
- runc创建新进程,用Namespaces隔离(网络/进程/文件系统)
- Cgroups挂载限制(/sys/fs/cgroup/cpu/docker/xxx目录写入2核配额)
- UnionFS挂载只读镜像层+可写容器层
- 运行时:应用进程在隔离环境中运行,监控工具(如cAdvisor)从Cgroups读取实时资源使用。
构建镜像参考
dockerfile FROM openjdk:21 # 基础层(复用) COPY target/user-service-1.0.jar /app/user.jar # 应用层(每次变) CMD ["java", "-jar", "/app/user.jar"] 构建 docker build -t myapp:v1 .

三、docker 网络5种模式
1.Docker默认有前3种网络模式:
bridge(默认):
容器通过docker0网桥通信,各自有独立IP。适合普通应用,比如Nginx容器和PHP容器通过内网IP互相访问,但对外要映射端口(-p 80:80)。
host
容器直接用宿主机网络,无隔离。适合高性能场景,比如监控agent需要抓宿主机所有流量,或性能敏感的网关服务(避免NAT损耗)。
none
完全无网络。跑纯计算任务时用,比如离线数据处理容器,不需要任何网络交互,最安全。
container
共享另一个容器的网络栈。典型场景:sidecar模式,比如主应用容器+Apm监控容器共享网络,Apm直接抓主容器流量,不用端口映射。
2.自定义网络(需要手动创建,不属于默认模式):
1.Docker自定义网络主要三种,生产常用前两种:
1.1自定义bridge
docker network create mynet
docker run --network=mynet -d nginx
作用:容器间通过服务名直接通信(不用IP),自动DNS解析
生产场景:微服务间调用,比如user-service容器直接ping order-service,不用记IP。比默认bridge强在避免端口冲突,100个容器可以都用8080端口。
1.2overlay
docker network create -d overlay my-cluster-net
作用:跨物理机容器组网,让不同服务器的容器像在同一个局域网
生产场景:Swarm/K8s集群里,上海服务器的容器直接访问北京服务器的Redis,网络对应用透明。我们自动扩的50个容器,不管在哪个机房都能互相发现。
1.3macvlan(少用)
作用:容器直接拿到物理网络IP,像虚拟机一样接入企业网络
生产场景:老旧系统改造,比如银行要求每个服务必须有固定IP做ACL策略,容器直接分配192.168.10.50,交换机策略不用变。
四、镜像构建docker commit VS Dockerfile
docker commit:
- 可靠性:
commit生成的镜像不可重现 - 安全合规:它会打包容器内所有临时文件(包括密钥、历史记录),违反SOC2审计要求。
- 可观察性:无法追溯变更来源,而Dockerfile每行指令都能关联Git提交,实现完整SLI/SLO追踪。
唯一例外:生产紧急热修复时,用 commit 快速止血,但24小时内必须重构为Dockerfile,否则自动阻断流水线发布。
Dockerfile:
-
镜像最小化:使用多阶段构建和精简基础镜像(如alpine),我们曾将部署时间减少65%,降低网络传输失败率,节约硬盘
-
缓存策略设计:按变更频率排序指令,确保CI/CD流水线高效运行,减少开发者等待时间
-
安全基线:
- 非root用户运行
- 构建时清理缓存
- 镜像签名与漏洞扫描集成到发布流水线
-
可观测性内置:标准化HEALTHCHECK和日志输出格式,确保平台能准确判断服务状态
-
环境一致性:通过ARG/ENV分离构建与运行时参数,消除"在我机器上能运行"问题
五、有状态VS无状态
无状态优先:业务逻辑容器必须无状态,确保秒级扩缩容和自愈。
有状态隔离:数据库等状态服务单独部署,通过外部存储(如云盘)持久化,与计算层解耦。
核心原则:容器销毁时,无状态服务零数据丢失,有状态服务RPO<5秒——这是我们的SLA红线。
若有状态必须容器化需满足:
- 数据目录挂外部云盘(非容器层)
- 单实例约束 + 禁用自动扩缩容
- 每日异地备份且验证恢复
六、容器分层
容器的数据分层目录
LowerDir: image 镜像层,即镜像本身,只读
UpperDir: 容器的上层,可读写 ,容器变化的数据存放在此处
MergedDir: 容器的文件系统,使用Union FS(联合文件系统)将lowerdir 和 upperdir 合并完成 后给容器使用,最终呈现给用户的统一视图
WorkDir: 容器在宿主机的工作目录,挂载后内容会被清空,且在使用过程中其内容用户不可见
查看 docker inspect +容器
更多推荐



所有评论(0)