Docker 学习文档(Mac + Docker Desktop 版)
适用人群:刚在 Mac 上装好 Docker Desktop、想系统学 Docker 的同学 工具环境:macOS + Docker Desktop(可视化桌面版) 作者视角:以「生产级」标准要求自己——镜像不是能跑就行,体积、安全、构建速度、可维护性一个都不能少。
0. 学习地图(先看这张图,心里有数)
Docker 知识树├── 理念层:容器 vs 虚拟机、为什么需要 Docker├── Mac 专属:Docker Desktop 本质 = Mac 上跑了一台 Linux 虚拟机├── 概念层:镜像(Image) / 容器(Container) / 仓库(Registry) / 卷(Volume) / 网络(Network)├── 操作层:docker 命令 + Docker Desktop 图形界面├── 构建层:Dockerfile / 多阶段构建 / .dockerignore├── 编排层:docker-compose(一次管多个容器)└── 实战层:从「跑起来」到「安全上线」
学习顺序建议:先理解概念 → 用 Desktop 点一点 → 用命令行敲一遍 → 自己写一个 Dockerfile → 用 compose 组一套服务。
1. Docker 是什么?为什么要用它?
1.1 一句话理解
Docker 把你的「应用 + 它运行所需的一切依赖(系统库、环境变量、配置文件)」打包成一个标准化、可移植的盒子(镜像)。这个盒子在任何装了 Docker 的机器上都能以完全一致的方式跑起来。
1.2 经典痛点(你一定遇过)
docker run | ||
1.3 容器 ≠ 虚拟机(重要区别)
| 毫秒级~秒级 | ||
记忆口诀:VM 是「租整栋楼」,容器是「租一个带独立水电的房间」,楼(内核)大家共用。
2. Mac 上 Docker 的特殊性(新手最容易踩的坑)
2.1 核心事实:Mac 不能直接跑 Linux 容器
macOS 的内核是 Darwin(XNU),而 Docker 容器本质上是 Linux 进程。所以:
Docker Desktop 在你的 Mac 上悄悄启动了一台轻量 Linux 虚拟机(基于 HyperKit / Apple 虚拟机框架),所有容器其实都跑在这台 VM 里。
带来的直接影响:
你 docker run的容器,逻辑上在「那台 Linux VM」里,不是直接在你的 macOS 上。容器访问宿主机(Mac)的服务时,不能直接用 localhost,要用特殊地址(见第 9 章)。
2.2 芯片架构:Intel(x86_64) vs Apple Silicon(arm64)
Mac 分两种芯片:
- Intel Mac
:x86_64 架构 - Apple Silicon(M1/M2/M3…)
:arm64 架构
坑点:很多老镜像只有 x86_64 版本。在 M 系列 Mac 上直接跑可能报错(如 exec format error)或靠 QEMU 模拟变慢。
解决:
优先拉取带 arm64标签或multi-arch(多架构)的官方镜像(官方镜像一般已支持)。用 docker run --platform linux/amd64 镜像名强制用 x86 模拟跑(慢,仅应急)。
查看自己架构:
uname -m# arm64 = Apple Silicon;x86_64 = Intel
2.3 Docker Desktop 的资源设置
打开 Docker Desktop → 右上角齿轮 ⚙️ → Settings → Resources:
- CPUs / Memory / Disk
:分配多少资源给那台 Linux VM。默认一般够用,跑重服务(如 Elasticsearch)可加内存。 - Disk image location
:VM 磁盘文件位置,别手贱删。 - General
里可勾选「Start Docker Desktop when you log in」(开机自启)。
3. Docker Desktop 界面导览(点点看,建立直觉)
启动 Docker Desktop 后,左侧是一排导航,常用这几个:
| Containers | docker psdocker logs | |
| Images | docker images | |
| Volumes | docker volume ls | |
| Builds | docker build | |
| Docker Hub | docker pull | |
| Settings ⚙️ |
新手建议:先用命令行把概念敲熟,再用 Desktop 的图形界面「回看」——图形界面是命令的可视化,理解了命令,界面一看就懂。
4. 核心概念(必须刻进脑子里)
4.1 镜像(Image)——「模板 / 类」
只读的模板,定义了容器里有什么。比如 node:20-alpine 就是一个预装了 Node 20 的镜像。
4.2 容器(Container)——「运行中的实例 / 对象」
镜像跑起来后变成容器,是可读可写的运行实例。一个镜像可以同时跑出 N 个容器。
4.3 仓库 / 镜像源(Registry)——「应用商店」
- Docker Hub
:默认公共仓库( docker pull nginx就是从这拉)。 国内加速:在 Settings → Docker Engine 里配置镜像加速器(如中科大、阿里云镜像),拉取更快。
4.4 卷(Volume)——「容器的硬盘」
容器删了,里面数据默认全没了。想持久化(数据库文件、上传资料),必须用 Volume 或挂载宿主机目录。
docker run -v 卷名:/容器里的路径 镜像4.5 网络(Network)——「容器间的局域网」
默认容器间可通过自定义网络互访(用服务名当域名)。compose 会自动建网络。
4.6 Dockerfile——「镜像的配方」
一个文本文件,写清楚「基于什么基础镜像、装什么、拷什么、怎么启动」。这是你亲手造镜像的方式(第 7 章细讲)。
5. 必会命令(建议全部亲手敲一遍)
提示:Docker Desktop 装好后,命令行里
docker命令就可用了(它会连上那台 VM)。
5.1 镜像相关
docker pull nginx:alpine # 拉取镜像(指定 tag,别用 latest!)docker images # 看本地镜像列表docker rmi 镜像ID # 删除镜像docker image prune # 删掉所有没被用的悬空镜像
5.2 容器相关(最常用)
docker run -d -p 8080:80 --name mynginx nginx:alpine# -d 后台运行# -p 8080:80 把宿主机 8080 映射到容器 80 端口# --name 给容器起个名字(不然是一串随机串)docker ps # 看正在跑的容器docker ps -a # 看所有容器(含已退出的)docker logs mynginx # 看日志docker exec -it mynginx sh # 进入容器里的 shell(-it 交互)docker stop mynginx # 停docker start mynginx # 起docker rm mynginx # 删(先 stop)docker rm -f mynginx # 强制删(没 stop 也行)
5.3 清理(Mac 磁盘容易被 Docker 吃满)
docker system prune # 删停止的容器 + 悬空镜像 + 网络(安全)docker system prune -a # 更狠:连没被用的镜像也删(谨慎)
在 Mac 上,Docker Desktop 的 VM 磁盘只增不减,
prune删文件后还要去 Settings → Resources → 「Clean / Reset」 才能真正回收磁盘空间。
5.4 一键跑个 Nginx 验证环境
docker run -d -p 8080:80 --name demo nginx:alpine浏览器打开 http://localhost:8080,看到 Nginx 欢迎页 = 环境 OK ✅
6. 第一个实战:从零做一个自己的镜像
目标:做一个打印「Hello Docker」的 Python 小服务,并容器化。
6.1 项目结构
demo/├── app.py└── requirements.txt
app.py:
from http.server import BaseHTTPRequestHandler, HTTPServerclass H(BaseHTTPRequestHandler):def do_GET(self):self.send_response(200)self.end_headers()self.wfile.write(b"Hello Docker from Mac!")if __name__ == "__main__":HTTPServer(("0.0.0.0", 8000)).serve_forever()
requirements.txt:(本例其实没第三方依赖,留空也行,演示用)
6.2 写 Dockerfile(基础版,先跑通)
FROM python:3.12-alpineWORKDIR /appCOPY app.py .CMD ["python", "app.py"]
6.3 构建并运行
cd demodocker build -t hello-docker .docker run -d -p 8000:8000 --name hello hello-docker# 打开 http://localhost:8000
跑通后你会发现镜像有几百 MB(因为带了整个 Python)。第 7 章教你压缩到几十 MB。
7. Dockerfile 写法与最佳实践(重点章节)
这是「生产级」和「玩具级」的分水岭。下面每条都是实战踩出来的。
7.1 基础镜像选型(体积/安全的第一步)
python:3.12 | ||
python:3.12-slim | ||
python:3.12-alpine | ||
gcr.io/distroless/... |
原则:版本别写 latest,要 pin 具体版本(如 python:3.12-alpine),否则今天构建和明天构建可能不一样,出事都查不到原因。
7.2 多阶段构建(把构建环境和运行环境分开)
以 Go 为例(Go 编译出静态二进制,最能体现多阶段价值):
# 阶段1:构建FROM golang:1.22-alpine AS builderWORKDIR /srcCOPY . .RUN go build -o app .# 阶段2:运行(极小的纯净镜像)FROM alpine:3.20WORKDIR /appCOPY --from=builder /src/app .USER 1000 # 不用 root 跑CMD ["./app"]
好处:构建工具(编译器、源码)全部留在第一阶段,最终镜像只有二进制 + 极简系统,体积能小一个数量级,攻击面也大幅减少。
7.3 非 root 用户运行(安全底线)
RUN addgroup -S app && adduser -S app -G appUSER app
容器里默认是 root,一旦被攻破,攻击者就在容器里拥有最高权限。切到普通用户是基本素养。
7.4 合理利用层缓存(让构建飞快)
Docker 按行构建,改得越少、越靠后的指令,越要放后面:
# ✅ 好:先拷依赖清单装依赖(这层很少变),再拷代码(常变)COPY package.json package-lock.json ./RUN npm ciCOPY . .# ❌ 差:COPY . . 在最前,每次改一行代码都要重装所有依赖
原理:依赖不变 → 这一层命中缓存 → 跳过 npm install,几秒过;只重跑代码拷贝和启动。
7.5 .dockerignore(别把垃圾塞进镜像)
项目根目录建 .dockerignore,作用类似 .gitignore:
node_modules.git.envDockerfile*.logdist(如果构建在宿主机做)
不忽略的话,COPY . . 会把 node_modules、.git 全打进镜像,体积爆炸、还有泄密风险。
7.6 HEALTHCHECK(让编排系统知道你「真活着」)
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \CMD wget -qO- http://localhost:8000/ || exit 1
加了之后,docker ps 里状态会从 starting 变成 healthy,K8s/compose 也靠它判断要不要重启。
7.7 不把密钥写进镜像
# ❌ 绝对不要ENV DB_PASSWORD=supersecret# ✅ 运行时通过 -e 或 secrets 注入docker run -e DB_PASSWORD=(pwd):/app挂载Mac 磁盘被吃满VM 磁盘不自动收缩prune后到 Settings → Resources 清理端口被占用宿主机端口已被占换-p 8081:80映射端口拉镜像慢默认连 Docker Hub 跨国配国内镜像加速器访问宿主机(Mac)的经典写法:# 容器里的应用要连 Mac 上跑的 MySQL(端口 3306)docker run myapp # 代码里填 host.docker.internal:330610. 学习路径 & 进阶建议10.1 30 天上手路线第 1 周:概念 + Desktop 界面 + 必会命令(第 1~5 章),把 nginx/redis/mysql 跑熟。第 2 周:自己写 Dockerfile,练多阶段、.dockerignore、非 root(第 6~7 章)。第 3 周:docker-compose 组一套「Web + DB + 缓存」(第 8 章)。第 4 周:镜像优化(体积/安全扫描)、.dockerignore/secret 管理进阶。10.2 推荐进阶主题镜像安全扫描:docker scout cves 镜像名(Desktop 内置),或 Trivy。BuildKit 新特性:--mount=type=cache 缓存依赖、--mount=type=secret 安全传密钥。Kubernetes:Docker Desktop 里 Settings 勾选 Kubernetes 即可本地单节点练手。CI 集成:把 docker build 放进 GitHub Actions / GitLab CI,做到提交即构建。10.3 给自己的三条铁律(记住就超过大多数人)基础镜像版本要 pin 死,绝不写 latest。最终运行镜像能小则小、能非 root 则非 root。密钥永远不进镜像,运行时注入。附:速查卡片(贴墙上)# 拉起一个服务docker run -d -p 宿主机端口:容器端口 --name 名字 镜像:tag# 进容器docker exec -it 名字 sh# 构建docker build -t 名字:版本 .# 清理docker system prune# 编排docker compose up -ddocker compose down
夜雨聆风