一、整体流程总览(先建立全局认知)
源码 ↓ Dockerfile(定义环境) ↓ docker build(生成不可变镜像) ↓ docker tag(版本化) ↓ docker push / docker save(传输) ↓ 服务器 docker pull / load ↓ docker run / docker compose
👉 核心思想:
镜像 = 唯一交付物
构建 ≠ 运行
服务器不参与构建
二、Step 0:准备条件(一次性)
本地需要
Docker
源码 + Dockerfile
服务器需要
Docker
能访问镜像来源(registry 或 scp)
❌ 服务器不需要:
node
npm
源码
三、Step 1:编写 Dockerfile(定义“世界”)
示例(以 Next.js / Node 为例)
# ---------- 构建阶段 ----------
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# ---------- 运行阶段 ----------
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]
原理说明
FROM:锁定 OS + runtime多阶段构建:
builder:编译、生成产物
runner:只跑结果(更小、更安全)
镜像里包含 运行所需的一切
四、Step 2:本地构建镜像(最关键)
docker build -t my-app:1.0.0 .
原理说明
Docker:
创建隔离的 Linux 环境
执行 Dockerfile 中的指令
生成一个 不可变镜像
这个镜像:
不依赖你的电脑
不依赖服务器
📌 这一步 等同于“编译交付物”
五、Step 3:给镜像打 Tag(版本化)
docker tag my-app:1.0.0 registry.example.com/my-app:1.0.0
原理说明
Tag ≈ 版本号
同一个 IMAGE ID 可以有多个 tag
用于:
回滚
灰度
多环境部署
六、Step 4:把镜像传到服务器
这里有 两种标准方式(选其一)
✅ 方式 A(生产推荐):使用镜像仓库
1️⃣ 登录仓库
docker login registry.example.com
2️⃣ 推送镜像
docker push registry.example.com/my-app:1.0.0
3️⃣ 服务器拉取
docker pull registry.example.com/my-app:1.0.0
原理
Registry = 镜像 CDN
镜像被拆成 layer
相同 layer 不重复传输
天然支持多服务器、回滚
⚠️ 方式 B(无仓库):save / scp / load
本地
docker save my-app:1.0.0 > my-app.tar scp my-app.tar user@server:/opt/
服务器
docker load < /opt/my-app.tar
原理
镜像打包成 tar
完整拷贝
无版本管理、无缓存
📌 只适合内网 / 临时
七、Step 5:服务器运行镜像
docker run -d \
--name my-app \
-p 3000:3000 \
-e NODE_ENV=production \
registry.example.com/my-app:1.0.0
原理说明
镜像是只读的
docker run创建 容器实例环境变量、端口、数据卷 = 运行态注入
八、Step 6:升级 / 回滚(生产必备)
升级
docker pull registry.example.com/my-app:1.0.1
docker stop my-app
docker rm my-app
docker run ... my-app:1.0.1
回滚
docker run ... my-app:1.0.0
原理
镜像不可变
切换版本 = 切换 tag
不存在“环境不一致”
九、docker-compose(真实生产常用)
docker-compose.yml(服务器)
version: "3.9"
services:
web:
image: registry.example.com/my-app:1.0.0
ports:
- "3000:3000"
env_file:
- .env
restart: always
docker compose up -d
原理
声明式
服务定义 = 基础设施代码
可复现部署