第3章:Docker核心概念——镜像、容器、仓库与架构
搞空间分析的人,第一次接触 Docker 时,最头疼的就是那堆新名词。镜像是什么?容器又是什么?跟虚拟机有啥区别?我当年刚上手时,也被这些概念绕晕过。这一章咱们就把这些东西彻底说透。
3.1 镜像——只读的打包模板
你可以把镜像理解成一个只读的压缩包。里面装了你应用运行所需的一切:操作系统根文件系统、Python 解释器、GDAL 库、PostGIS 驱动,甚至是你写好的空间分析脚本。
镜像有个特点:分层构建。每一层都是只读的,修改时只记录差异。这有什么好处?你想想看,下载一个 2GB 的 GIS 基础镜像,下次再拉一个新镜像,如果底层相同,只需要下载新增的几十 MB 差异层。我维护过一套遥感数据处理流水线,每天都要发布新版本,依赖层几乎不动,每次推送就几百 KB,快得很。
查看本地已有镜像,用这个命令:
docker images
输出大概长这样:
REPOSITORY TAG IMAGE ID CREATED SIZE
postgis 15-3.4 abc123def456 2 weeks ago 1.2GB
python 3.11-slim def789ghi012 1 month ago 125MB
关键点:镜像是静态的、只读的、可分享的。你可以在笔记本上构建好,推到仓库,再到服务器上拉下来跑,结果完全一致。这在部署空间分析流程时太重要了——告别“在我机器上能跑”的尴尬。
3.2 容器——镜像的运行实例
镜像再大,不运行就是一堆文件。容器就是镜像活起来的样子。说白了,容器是镜像的运行态,它拥有自己的文件系统、网络栈、进程空间。
打个比方:
- 镜像 = 菜谱 + 所有食材(静态)
- 容器 = 正在锅里翻炒的菜(动态)
启动一个容器的命令:
docker run -it --name my-analysis ubuntu:22.04 bash
进入容器后,你可以安装软件、修改文件、跑代码。但要注意,容器默认是临时的。你退出后,容器就停了。如果没做持久化,里面的修改会丢失。
避坑提醒:千万不要在运行中的容器里保存重要数据!我曾经在容器里跑了一整天的矢量数据合并,结果手滑 exit 退出了,再启动时发现所有中间结果都没了……后来老老实实学会了挂载卷(volume)。咱们后面章节会专门讲数据持久化。
3.3 仓库——镜像的集中存储与分发
仓库就相当于一个镜像的 GitHub。你在本地构建好镜像,推上去,别人就能拉下来用。Docker 官方提供了 Docker Hub,上面有海量公共镜像。
拉取一个镜像:
docker pull postgis/postgis:15-3.4
推送自己构建的镜像:
docker tag my-analysis:1.0 yourdockerhub/my-analysis:1.0
docker push yourdockerhub/my-analysis:1.0
如果你是做空间分析项目的,我强烈建议你搭建私有仓库。公司内部的遥感底图、行政区划矢量、DEM 数据,不适合放到公网上。搭建方式很简单:
docker run -d -p 5000:5000 --name registry registry:2
推送时指定仓库地址就行:
docker tag my-analysis:1.0 localhost:5000/my-analysis:1.0
docker push localhost:5000/my-analysis:1.0
个人经验:国内访问 Docker Hub 经常慢得让人抓狂。我通常会配置镜像加速器,或者直接把常用 GIS 镜像缓存到内网私有仓库。团队里 20 多号人,每天拉上百次镜像,缓存一次能省几个小时。
配置镜像加速器很简单,编辑 Docker 配置文件:
# /etc/docker/daemon.json
{
"registry-mirrors": ["https://your-mirror.example.com"]
}
改完后重启 Docker 服务:
systemctl restart docker
3.4 Docker 架构——客户端-守护进程模式
Docker 采用C/S(客户端-服务端)架构。整个体系由三个核心组件构成:
| 组件 | 角色 | 空间分析场景中的实际角色 |
|---|---|---|
| Docker 客户端 | 你敲命令的那个终端 | 你在笔记本上执行 docker run |
| Docker 守护进程 | 后台常驻的核心引擎 | 管理容器生命周期、镜像层缓存 |
| 镜像仓库 | 存储和分发镜像 | 拉取 PostGIS、推送分析流程镜像 |
你敲的每一条 docker 命令,客户端都会通过 REST API 发给守护进程,由它来调度容器、管理镜像。可以跨机器操作:本地客户端控制远程服务器上的守护进程。
我曾经用这个特性在实验室的 8 卡 GPU 服务器上跑遥感影像推理:开发机上敲命令,计算节点上跑容器,调试和生产环境完全隔离。
3.5 核心工作原理——写时复制与命名空间
Docker 之所以能秒级启动、资源占用小,靠的是两项底层技术:
写时复制(Copy-on-Write):多个容器共享同一份只读镜像层,各自只记录自己的写入内容。你创建 10 个基于同一个 PostGIS 镜像的容器,磁盘上只有一份镜像数据。
命名空间(Namespace):每个容器看到自己独立的进程树、网络栈、文件系统。但实际上都运行在宿主机内核上。
这个模型和虚拟机有本质区别:
| 对比维度 | Docker 容器 | 虚拟机 |
|---|---|---|
| 启动时间 | 秒级 | 分钟级 |
| 资源开销 | 极低,共享宿主机内核 | 高,每个 VM 有独立 OS |
| 隔离级别 | 进程级 | 硬件级 |
| 磁盘占用 | 很小(复用镜像层) | 很大(完整 OS 镜像) |
| 适合场景 | 微服务、批量数据处理 | 多租户强隔离、需要不同内核 |
空间分析任务,尤其是批量栅格处理、矢量数据 ETL、模型推理,用容器再合适不过。一个任务一个容器,跑完就删,宿主机干干净净。你想想看,几百个任务同时跑,如果用虚拟机,光启动操作系统就得等半小时。
总结一下:
- 镜像 = 静态打包模板,只读分层存储
- 容器 = 镜像的运行实例,临时可写层
- 仓库 = 镜像的集中存储与分发中心
- 架构 = 客户端 -> 守护进程 -> 仓库的三层模型
- 核心原理 = 写时复制 + 命名空间,提供轻量级隔离