Docker 核心概念
Docker 最有价值的地方,不是"更炫",而是让环境差异显著减少。
核心对象关系
graph TD
A[Dockerfile] -->|docker build| B[Image 镜像]
B -->|docker run| C[Container 容器]
C --> D[Volume 持久化数据]
C --> E[Network 容器网络]
B -->|docker push| F[Registry 镜像仓库]
F -->|docker pull| B
四个核心概念
| 概念 | 说明 | 类比 |
|---|---|---|
| Image | 只读的运行模板,包含代码、依赖、配置 | 操作系统安装盘 |
| Container | Image 的运行实例,有独立文件系统和进程 | 从安装盘启动的虚拟机 |
| Volume | 容器外部的持久化存储,容器删除后数据不丢 | 外挂硬盘 |
| Network | 容器间通信的虚拟网络 | 内网 VLAN |
多阶段构建(生产推荐)
不使用多阶段构建时,构建工具(编译器、测试库)全部进入生产镜像,体积大且存在安全风险。
# Dockerfile(Node.js 示例:多阶段构建)
# === Stage 1: 构建阶段 ===
FROM node:20-alpine AS builder
WORKDIR /app
# 先复制 package.json(利用层缓存,依赖不变则跳过 npm install)
COPY package*.json ./
RUN npm ci
# 复制源码并构建
COPY . .
RUN npm run build
# === Stage 2: 生产阶段(只包含运行时需要的文件)===
FROM node:20-alpine AS production
WORKDIR /app
# 只复制生产依赖
COPY package*.json ./
RUN npm ci --production && npm cache clean --force
# 从构建阶段复制编译产物
COPY --from=builder /app/dist ./dist
# 非 root 用户运行(安全最佳实践)
RUN addgroup -S app && adduser -S app -G app
USER app
EXPOSE 3000
CMD ["node", "dist/server.js"]
镜像大小对比:
| 构建方式 | 典型大小 | 包含内容 |
|---|---|---|
| 单阶段(含 devDependencies) | 800MB+ | 编译器、测试库、源码 |
| 多阶段构建 | 150–300MB | 仅运行时依赖 + 编译产物 |
| Alpine 基础镜像 | 额外减少 200MB | 最小 Linux 环境 |
常用命令速查
# 构建镜像
docker build -t myapp:latest .
docker build -t myapp:v1.2.3 --no-cache . # 不使用缓存
# 运行容器
docker run -d -p 3000:3000 --name myapp myapp:latest
docker run -d -p 3000:3000 \
--env-file /etc/myapp/myapp.env \ # 注入环境变量
-v /data/uploads:/app/uploads \ # 挂载数据卷
--restart unless-stopped \ # 自动重启策略
myapp:latest
# 查看和管理
docker ps # 运行中的容器
docker ps -a # 所有容器(含已停止)
docker logs myapp -f --tail 100 # 实时日志
docker exec -it myapp sh # 进入容器调试
docker stats # 实时资源使用
# 清理
docker stop myapp && docker rm myapp
docker image prune -f # 清理悬空镜像
docker system prune -f # 清理所有未使用资源
常见误区
| 误区 | 正确做法 |
|---|---|
| 在单一 Dockerfile 中安装所有依赖(含 devDeps) | 用多阶段构建,生产镜像只含运行时 |
| 以 root 用户运行容器 | 用 USER app 指令切换非 root 用户 |
| 把 Secrets 写入 Dockerfile 或镜像层 | 通过 --env-file 或 Volume 在运行时注入 |
COPY . . 放在 npm install 前面 | 先 COPY package.json → npm install → 再 COPY 源码,利用层缓存 |
本节执行清单
- [ ] 用多阶段构建重写 Dockerfile,验证生产镜像不含 devDependencies
- [ ] 确认容器以非 root 用户运行(
docker exec myapp whoami返回非 root) - [ ] 用
docker logs myapp -f确认日志正常输出 - [ ] 测试
docker stop→docker start后应用恢复正常
下一节:Docker Compose 单机管理——单容器之外,开始管理一组服务。