2、容器化技术基础:Docker基本概念与架构归纳总结输出为HTML正文内容片段

2.1 Docker到底是什么?

说到Docker,其实很多人第一次接触时都会有点懵。它到底是个虚拟机,还是个啥?

我个人习惯这么理解:Docker是一个“轻量级的集装箱系统”。你想想看,传统虚拟机就像搬家时租了个大卡车,你得先把整个房子(操作系统)搬进去,然后再放你的家具(应用)。而Docker呢,它就像一个个标准化的集装箱,只装你需要的家具和最基本的“生活必需品”(运行时环境)。

我在项目中遇到过这种情况:同一个Java应用,在开发环境跑得好好的,一到测试环境就报错。最后发现是测试环境的系统库版本和开发环境不一样。用了Docker之后,这种问题基本绝迹了。为什么?因为Docker把应用和它依赖的环境打包在了一起,走到哪儿都一样。

核心总结:Docker是一个开源的容器化平台,它让开发者可以把应用及其依赖打包到一个轻量级、可移植的容器中,然后在任何支持Docker的机器上运行。说白了,就是“一次构建,到处运行”。

2.2 Docker的三大核心概念

要搞懂Docker,得先弄明白它的三个核心部件:镜像(Image)、容器(Container)、仓库(Repository)。这三者就像炒菜用的菜谱、做好的菜和菜市场。

2.2.1 镜像(Image)

镜像是一个只读的模板,里面包含了运行某个应用所需要的所有东西——代码、运行时、库、环境变量、配置文件。嗯,你可以把它理解成一套完整的“安装盘”。

举个例子,我们做国密算法部署,需要一个支持SM2、SM3、SM4算法的OpenSSL环境。你就可以做一个自定义镜像,把这个环境固化下来。

# 一个简单的Dockerfile示例
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y openssl
COPY ./gmssl /opt/gmssl
ENV PATH="/opt/gmssl/bin:${PATH}"

镜像有个特点:它是分层构建的。每一层都是只读的,而且可以被多个镜像共享。我记得有一次,团队里好几个人都在用同一个基础镜像,因为分层机制,每个人的构建速度都很快。

2.2.2 容器(Container)

容器是镜像的运行实例。镜像你不动它,它就是一个静态文件。但当你用Docker运行一个镜像时,Docker会在镜像层之上创建一个可写层,这时候就变成了一个活生生的“容器”。

你可以把容器想象成一个轻量级的、隔离的“小房间”。每个房间都有自己的文件系统、网络、进程空间,彼此互不干扰。我在项目中经常同时跑多个容器,一个跑国密签名服务,一个跑SM4加解密服务,它们各自独立,互不影响。

提示:容器和虚拟机的最大区别在于——虚拟机需要模拟整个操作系统,而容器直接共享宿主机的操作系统内核。这意味着容器启动速度极快(毫秒级),资源开销也小得多。

2.2.3 仓库(Repository)

仓库是存放镜像的地方。你可以把本地做好的镜像推送到远程仓库,也可以从仓库拉取别人做好的镜像。

Docker Hub是最大的公共仓库。但一般来说,企业级应用,尤其是涉及国密算法的项目,我建议用私有仓库。比如Harbor或阿里云的容器镜像服务。安全第一嘛。

概念 类比 特点
镜像 菜谱 只读、可复用、分层构建
容器 做好的菜 可写、可启停、隔离运行
仓库 菜市场 存储、分发、版本管理

2.3 Docker的架构本质

Docker使用的是C/S(客户端/服务器)架构。说白了,你敲的docker run、docker build这些命令,都是客户端在向Docker守护进程(Docker Daemon)发请求。

这里我画了一张架构图,把主要组件和它们之间的关系梳理了一下。你看看就明白了。

Docker 架构核心组件关系图 Docker 客户端 docker build docker run docker push Docker Host(宿主机) Docker Daemon (守护进程) 管理镜像、容器、网络、存储 镜像层(Image Layers) 只读模板,分层构建 每个层可以被多个镜像共享 容器运行时 镜像 + 可写层 = 运行实例 隔离的进程、网络、文件系统 镜像仓库 Docker Hub 私有仓库 Harbor / 阿里云 宿主机操作系统内核 CPU、内存、存储、网络
架构核心要点:Docker Client 通过 REST API 与 Docker Daemon 通信;Daemon 负责管理镜像的生命周期、容器的启停、网络和存储卷;镜像可以存在本地缓存,也可以从远端仓库拉取。

2.4 Docker的隔离机制:Namespaces与Cgroups

很多朋友会问:“Docker里的进程跟宿主机上的其他进程真的完全隔离吗?” 答案是:在大部分维度上是的,但并非100%像虚拟机那样严丝合缝。

Docker实现隔离靠的是操作系统底层的两个关键技术:

  • Namespaces(命名空间):用来做“看不着”的隔离。进程在各自的Namespace里,只能看到自己的进程、网络、文件系统、用户,看不到外面的世界。
  • Cgroups(控制组):用来做“抢不到”的限制。我限制你最多用1个CPU核心、512MB内存,你就算跑死也不能用更多。我在项目中遇到过容器内存泄漏,就是因为没设置内存限制,结果容器把宿主机的内存吃光了。
注意:虽然Docker实现了进程隔离,但容器仍然共享宿主机的操作系统内核。这意味着——如果你在宿主机上装了CentOS,那容器里也只能跑基于Linux内核的发行版,不能跑Windows。这一点跟虚拟机有着本质区别。做国密算法部署时千万要留意基础镜像的操作系统系列。

2.5 Docker网络与数据管理

这一块我跟不少新手讲过,其实没那么复杂。你只要记住两个核心:网络怎么通,数据怎么存。

2.5.1 网络模式

Docker默认提供了几种网络模式:

网络模式 特点 适用场景
bridge 默认模式,容器通过虚拟网卡连接到网桥 单机容器间通信
host 容器直接使用宿主机网络,不隔离 对网络性能要求极高的场景
none 无网络,完全隔离 安全敏感型容器
overlay 跨宿主机容器通信,用于Swarm集群 多机部署的国密服务集群

我个人习惯,在开发环境用bridge模式就够了。生产环境如果涉及微服务之间的国密认证交互,我建议研究一下overlay网络,让多个宿主机上的国密容器能通过内部虚拟网络通信,安全且高效。

2.5.2 数据持久化

容器有一个特点:它会消亡。当你把容器删了,里面生成的数据也就没了。这显然不符合国密算法的部署需求——你总不能让签名密钥随容器一起消失吧?

解决方案就是挂载数据卷(Volume)。有两种方式:

  • bind mount:把宿主机的某个目录直接映射到容器里。简单直接,但跟宿主机耦合度高。
  • volume:由Docker管理的数据卷。更推荐,因为它是持久的、可迁移的。我在做国密容器部署时,习惯把密钥文件、日志、数据库文件都放在volume里,这样即使容器重建,数据也还在。
# 创建一个数据卷
docker volume create gmssl-keys

# 挂载数据卷到容器
docker run -d --name gmssl-server \
  -v gmssl-keys:/etc/gmssl/keys \
  -p 443:443 \
  my-gmssl-image:latest
实战经验:我建议你把国密算法的私钥证书放到volume中,不要在镜像中打包私钥。镜像一旦被推送到仓库,就等于把私钥公开了,这是大忌。

2.6 避坑指南:我刚学Docker时的几个教训

最后,分享几个我踩过的坑,希望能帮你少走弯路。

  1. 别用latest标签上生产环境。我曾经偷懒一直用latest,结果有一次基础镜像更新了,部署上去容器直接起不来。后来我强制团队使用具体版本号,比如v1.2.3。
  2. 容器里不要跑多进程。一个容器最好只跑一个进程。比如你要用国密Nginx,那就单独一个容器跑Nginx,不要再把SM4加解密模块也塞进去。否则出了问题不好排查。
  3. 定期清理无用的镜像和容器。我见过有人磁盘空间被none镜像吃光了。养成习惯,可以用docker system prune -f定期清理。
  4. 安全组和防火墙要仔细配置。Docker默认会修改iptables规则,如果不小心,可能会把宿主机暴露出去。尤其是国密相关的端口,一定要严格控制。

好,关于Docker的核心概念和架构,我们就先聊到这里。吃透这些,后面的实战部署才能顺风顺水。