很多 Docker 教程从命令表开始,读者能照着输入,却不知道这些命令为什么存在。这门课换一种走法:我们先明确要交付的项目,再让每个 Docker 概念解决一个真实问题。
课程主线是一个“任务清单 API”。它能接收任务、列出任务,并把数据保存在 Redis 中。我们会从一条命令开始,逐步得到两个容器、一张可分发的应用镜像、一份 compose.yaml,以及一套能复现的启动和排错流程。

一个应用要运行,通常需要程序文件、语言运行时、系统库、配置和启动命令。只复制源代码,很容易出现“依赖版本不同”“缺少系统库”“启动方式不一致”等问题。
容器把应用和它的运行条件一起组织起来。镜像描述静态内容,容器是镜像的一次运行实例。只要运行平台支持对应的操作系统与 CPU 架构,同一镜像就能以相同方式启动。
容器和虚拟机都能隔离工作负载,但边界不同:
容器不是缩小版虚拟机。Linux 容器依赖 Linux 内核;macOS 和 Windows 上的 Docker Desktop 会在受管理的 Linux 虚拟化环境中运行 Linux 容器。镜像还必须兼容目标 CPU 架构,后面会专门处理 amd64 与 arm64。
把容器理解成“带着独立视野和资源边界的一组进程”,比把它想成一台小电脑更准确。一个普通进程能看到设备上的进程列表、网络接口和文件目录;容器里的进程仍然由同一个 Linux 内核调度,但 Docker 会借助内核能力改变它能看到和能使用的范围。
这三部分解决的是不同问题:namespace 不等于资源限制,cgroup 也不负责隐藏进程;文件系统隔离更不代表网络已经隔离。后面学习网络、存储和安全时,我们会分别把这些边界展开。
容器之所以启动快,不是因为它“省略了操作系统的所有部分”,而是因为启动容器通常只需要准备隔离边界、挂载镜像层并创建应用进程,不必再引导一套新的内核。
镜像能固定应用的用户空间依赖,却不会消除外部条件。CPU 架构、内核能力、可用内存、挂载的数据、运行时注入的配置和外部服务仍然会影响结果。因此“在容器里能运行”只是交付链的一部分,可靠交付还需要:
linux/amd64 或 linux/arm64。这正是课程从单容器一路讲到 Compose、排错、安全和发布的原因。
后面的命令会反复操作这些对象。现在先建立一张简单地图。
镜像是只读模板,包含文件系统和默认启动配置。例如 redis:8-alpine 表示 Redis 仓库中标记为 8-alpine 的镜像。
容器由镜像创建。删除容器不会删除镜像;没有挂载到数据卷的数据,会随容器删除而丢失。
Dockerfile 是构建镜像的配方。FROM 选择基础镜像,COPY 放入文件,RUN 执行构建步骤,ENTRYPOINT 或 CMD 定义默认进程。
Registry 是镜像仓库服务。Docker Hub 是常见的公共 Registry,团队也可以使用私有仓库。pull 下载镜像,push 上传镜像。
容器网络让容器彼此通信。接入同一自定义网络的容器,可以通过容器名或 Compose 服务名发现对方。
数据卷由 Docker 管理,生命周期独立于容器。数据库数据、上传文件等需要跨容器重建保留的内容,应放进数据卷。
用户访问任务 API 时,这六个对象不是彼此孤立的名词:
注意这里有两条完全不同的生命周期:镜像从构建走向分发,容器从创建走向运行和删除。把二者分开,是后面不误删数据、不混淆状态的基础。
docker build 负责把源代码和依赖变成镜像;docker run 负责从镜像创建容器并启动进程。编译器通常只在构建时需要,端口、数据库地址和密钥则通常在运行时决定。把两类信息混在一起,会得到体积大、难复用或泄露配置的镜像。
容器里的 localhost 指向容器自己,不自动指向另一个容器,也不等于访问者所在的网络空间。容器端口只有被发布后,外部请求才能按映射进入;两个容器之间则通常通过共享网络和服务名通信。
应用二进制、系统库和默认配置适合放进镜像,因为它们可以重新构建。用户数据、数据库文件和上传内容不能依赖某个容器一直存在,应放到数据卷或外部存储。一个健康的容器化应用应该允许“删掉旧容器,用同一镜像创建新容器”。
如果你能在执行命令前先回答“这一步改变的是镜像、容器、网络还是数据卷”,就已经开始用 Docker 的对象模型思考,而不是只背命令。
项目目录最终包含这些文件:
docker-task-api/
├── .dockerignore
├── Dockerfile
├── compose.yaml
├── go.mod
├── go.sum
└── main.go最终运行关系如下:
浏览器或 curl
│ 端口 8080
▼
任务 API 容器 ── 服务名 redis:6379 ──► Redis 容器
│
▼
命名数据卷课程结束时,你应该能独立完成这些动作:
每次实操都按同一个顺序展开:先讲清楚命令要改变哪个对象,再执行命令,最后展示可核对的结果。不要跳过结果展示。Docker 的学习关键不是记参数,而是能根据状态判断下一步。
代码块中的 $ 只表示终端提示符,复制时不要输入。Windows 用户建议在 PowerShell 或 WSL 2 终端中执行;macOS 与 Linux 用户使用常见终端即可。
课程示例使用 Linux 容器。项目端口默认是 8080;如果这个端口被占用,Compose 章节会演示怎样通过 APP_PORT 改成其他端口。
每章建议按下面四轮学习:
ps、inspect、日志或实际请求验证状态,不以“命令没报错”代替验收。每章末尾都应该留下三类答案:我创建了什么、状态在哪里观察、失败时第一条证据从哪里找。学到后半程,你会发现 Docker 的多数问题都能沿着“配置 → 对象状态 → 进程输出 → 外部连通性”逐层缩小,而不需要猜。
下一节先把 Docker 安装好,并用一组体检命令分清“命令存在”和“引擎能工作”这两件事。