vault backup: 2026-04-28 20:31:20
This commit is contained in:
@@ -0,0 +1,491 @@
|
|||||||
|
# Dockerfile 编写指南
|
||||||
|
|
||||||
|
> Dockerfile 是**镜像构建的蓝图**,每一行指令都会在镜像中生成一层。写好 Dockerfile 的核心目标:**镜像更小、构建更快、启动更安全**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、Dockerfile 基本结构
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# 1. 基础镜像
|
||||||
|
FROM node:20-slim AS builder
|
||||||
|
|
||||||
|
# 2. 维护者信息(可选)
|
||||||
|
LABEL maintainer="yourname@example.com"
|
||||||
|
|
||||||
|
# 3. 设置工作目录
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 4. 复制依赖文件并安装
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci --production
|
||||||
|
|
||||||
|
# 5. 复制源代码
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# 6. 构建(开发环境需要,生产环境不需要)
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# 7. 暴露端口
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
# 8. 启动命令
|
||||||
|
CMD ["node", "dist/index.js"]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、常用指令详解
|
||||||
|
|
||||||
|
### 2.1 `FROM` — 基础镜像
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# 选镜像的通用原则:
|
||||||
|
# 有 Alpine 选 Alpine(体积小)
|
||||||
|
# 有 Slim 选 Slim(平衡体积和功能)
|
||||||
|
# 没有再选完整版本
|
||||||
|
|
||||||
|
FROM node:20-alpine # 推荐:最小体积
|
||||||
|
FROM node:20-slim # 推荐:平衡方案
|
||||||
|
FROM node:20 # 不推荐:包含完整 OS,镜像臃肿
|
||||||
|
FROM python:3.12-slim-bookworm
|
||||||
|
FROM nginx:alpine
|
||||||
|
FROM golang:1.22-alpine
|
||||||
|
FROM ubuntu:24.04 # 一般作为多阶段构建的第一步
|
||||||
|
```
|
||||||
|
|
||||||
|
**常见基础镜像体积对比:**
|
||||||
|
|
||||||
|
| 镜像 | 大小 | 适用场景 |
|
||||||
|
|------|------|----------|
|
||||||
|
| `alpine` | 5-10MB | 生产环境、追求极致体积 |
|
||||||
|
| `slim` | 100-200MB | 大多数生产场景,兼容性好 |
|
||||||
|
| 完整版 | 1GB+ | 开发环境、需要完整工具链 |
|
||||||
|
|
||||||
|
### 2.2 `RUN` — 执行命令
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# 合并 RUN 指令减少镜像层数
|
||||||
|
# 不推荐:每行一个 RUN,产生多层
|
||||||
|
RUN apt-get update
|
||||||
|
RUN apt-get install -y nginx
|
||||||
|
RUN rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# 推荐:合并为一行,并用 && 连接,用 \ 换行
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y nginx && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# 注意:RUN 产生的层会**永久留在镜像中**,即使后续 rm 了也没用
|
||||||
|
# 所以更新和安装、清理要放在同一个 RUN 里
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 `COPY` vs `ADD`
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# COPY — 简单复制,推荐优先使用
|
||||||
|
COPY package.json ./
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# ADD — 有额外功能但不可预测,不推荐
|
||||||
|
ADD https://example.com/file.tar.gz /tmp/ # 能下载远程文件,但容易出错
|
||||||
|
ADD file.tar.gz /app/ # 能自动解压,但 COPY + RUN tar 更清晰
|
||||||
|
|
||||||
|
# 结论:99% 的情况用 COPY,ADD 只在自动解压 tar 和下载远程文件时有用
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.4 `WORKDIR` — 工作目录
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
WORKDIR /app # 设置工作目录
|
||||||
|
COPY package.json ./ # 相对于 /app
|
||||||
|
RUN npm install
|
||||||
|
COPY . . # 复制代码到 /app
|
||||||
|
|
||||||
|
# WORKDIR 会被后续指令继承,且会自动创建(不需要提前 mkdir)
|
||||||
|
WORKDIR /subdir # 现在是 /app/subdir
|
||||||
|
RUN pwd # 输出 /app/subdir
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.5 `EXPOSE` — 声明端口
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# 声明容器运行时监听的端口(文档性质,不自动映射)
|
||||||
|
EXPOSE 3000
|
||||||
|
EXPOSE 80 443
|
||||||
|
|
||||||
|
# 实际端口映射需要在 docker run -p 或 docker-compose 中指定
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.6 `ENV` — 环境变量
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV APP_PORT=3000
|
||||||
|
ENV DB_HOST=localhost
|
||||||
|
|
||||||
|
# 容器启动时可以覆盖:
|
||||||
|
# docker run -e DB_HOST=192.168.1.100 my-app
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.7 `CMD` vs `ENTRYPOINT`
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# CMD — 容器启动时执行的默认命令(可被覆盖)
|
||||||
|
CMD ["node", "dist/index.js"]
|
||||||
|
# 运行 docker run my-app echo "hello" 会覆盖 CMD
|
||||||
|
|
||||||
|
# ENTRYPOINT — 入口点,不可被 docker run 覆盖(但可用 --entrypoint 强制覆盖)
|
||||||
|
ENTRYPOINT ["node"]
|
||||||
|
CMD ["dist/index.js"] # 作为 ENTRYPOINT 的参数
|
||||||
|
|
||||||
|
# 实际开发中,大多数情况用 CMD 就够了
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、多阶段构建(关键优化手段)
|
||||||
|
|
||||||
|
### 3.1 为什么需要多阶段构建
|
||||||
|
|
||||||
|
前端项目用 Next.js/Vite + TypeScript 构建,需要 Node.js 全套环境。但运行只需要一个编译后的静态文件。多阶段构建可以**把构建工具留在第一阶段,最终镜像只放产物**。
|
||||||
|
|
||||||
|
### 3.2 前端多阶段构建(Node + TypeScript)
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# ========== 第一阶段:构建 ==========
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# ① 先复制依赖文件,利用 Docker 缓存
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# ② 再复制源码(代码改了才重新构建)
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# ③ 构建
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# ========== 第二阶段:运行 ==========
|
||||||
|
FROM node:20-alpine AS production
|
||||||
|
|
||||||
|
# 安装 tini(处理僵尸进程,可选但推荐)
|
||||||
|
RUN apk add --no-cache tini
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 仅复制 production 依赖
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci --production
|
||||||
|
|
||||||
|
# 从构建阶段复制产物
|
||||||
|
COPY --from=builder /app/dist ./dist
|
||||||
|
COPY --from=builder /app/public ./public
|
||||||
|
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
# 使用 tini 作为 PID 1
|
||||||
|
ENTRYPOINT ["/sbin/tini", "--"]
|
||||||
|
CMD ["node", "dist/index.js"]
|
||||||
|
```
|
||||||
|
|
||||||
|
**核心思路:先用大镜像构建 → 再把产物复制到最小镜像中运行。**
|
||||||
|
|
||||||
|
### 3.3 Java 多阶段构建
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# 第一阶段:Maven 构建
|
||||||
|
FROM maven:3.9-eclipse-temurin-21 AS build
|
||||||
|
WORKDIR /app
|
||||||
|
COPY pom.xml .
|
||||||
|
RUN mvn dependency:go-offline -B
|
||||||
|
COPY src ./src
|
||||||
|
RUN mvn package -DskipTests
|
||||||
|
|
||||||
|
# 第二阶段:运行
|
||||||
|
FROM eclipse-temurin:21-jre-alpine
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=build /app/target/*.jar app.jar
|
||||||
|
EXPOSE 8080
|
||||||
|
ENTRYPOINT ["java", "-jar", "app.jar"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.4 Go 多阶段构建
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# 第一阶段:编译
|
||||||
|
FROM golang:1.22-alpine AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
COPY . .
|
||||||
|
RUN CGO_ENABLED=0 go build -o /app/server
|
||||||
|
|
||||||
|
# 第二阶段:运行
|
||||||
|
FROM alpine:3.19
|
||||||
|
RUN apk --no-cache add ca-certificates
|
||||||
|
COPY --from=builder /app/server /app/server
|
||||||
|
EXPOSE 8080
|
||||||
|
CMD ["/app/server"]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、.dockerignore 文件
|
||||||
|
|
||||||
|
> **和 `.gitignore` 一样重要!** 不写 `.dockerignore` 会导致不必要的文件被复制到镜像中,增大体积、暴露敏感信息。
|
||||||
|
|
||||||
|
```dockerignore
|
||||||
|
# 依赖
|
||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
|
||||||
|
# Git
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
# 构建产物(别把 build 直接拷进去,让容器自己 build)
|
||||||
|
dist
|
||||||
|
build
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# 编辑器
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# Docker 自身
|
||||||
|
docker-compose.yml
|
||||||
|
Dockerfile
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
# 文档和测试
|
||||||
|
README.md
|
||||||
|
LICENSE
|
||||||
|
tests
|
||||||
|
__tests__
|
||||||
|
|
||||||
|
# 环境变量(千万不要拷进去!)
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、最佳实践清单
|
||||||
|
|
||||||
|
### ✅ 应该做
|
||||||
|
|
||||||
|
| 实践 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| 使用具体版本号 | `FROM node:20.11-alpine`,不要用 `latest` |
|
||||||
|
| 用 `alpine` 或 `slim` | 减小镜像体积 |
|
||||||
|
| 合并 `RUN` 指令 | 减少镜像层数 |
|
||||||
|
| 先复制 `package.json` 再 `npm install` | 利用 Docker 层缓存 |
|
||||||
|
| 用 `.dockerignore` | 排除不必要的文件 |
|
||||||
|
| 用多阶段构建 | 分离构建和运行环境 |
|
||||||
|
| 非 root 用户运行 | 安全考虑 |
|
||||||
|
| 用 `CMD ["exec格式"]` | 避免 shell 包装问题 |
|
||||||
|
|
||||||
|
### ❌ 不应该做
|
||||||
|
|
||||||
|
| 实践 | 问题 |
|
||||||
|
|------|------|
|
||||||
|
| 用 `latest` 标签 | 构建结果不可复现 |
|
||||||
|
| 在 Dockerfile 中存密码/密钥 | 暴露敏感信息 |
|
||||||
|
| 用 `ADD` 替代 `COPY` | 不可预测行为 |
|
||||||
|
| 安装不必要的应用 | 镜像臃肿 |
|
||||||
|
| 用 `RUN apt-get install && apt-get remove` | 删除的文件仍在镜像层中 |
|
||||||
|
| 以 root 用户运行应用 | 安全风险 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、非 Root 用户示例
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM node:20-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# 创建非 root 用户
|
||||||
|
RUN addgroup -S appgroup && \
|
||||||
|
adduser -S appuser -G appgroup
|
||||||
|
|
||||||
|
# 切换用户
|
||||||
|
USER appuser
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
CMD ["node", "dist/index.js"]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、常见问题排查
|
||||||
|
|
||||||
|
### 7.1 镜像太大
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 分析镜像各层大小
|
||||||
|
docker history my-app:latest
|
||||||
|
|
||||||
|
# 检查是否有未清理的缓存
|
||||||
|
# 解决:使用 alpine/slim 基础镜像 + 多阶段构建 + .dockerignore
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.2 构建缓存失效
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# 错误:代码改动导致 npm install 也重新执行
|
||||||
|
COPY . .
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# 正确:依赖文件不变时跳过 npm install
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
COPY . .
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.3 容器启动后立即退出
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看日志
|
||||||
|
docker logs <容器名>
|
||||||
|
|
||||||
|
# 常见原因:
|
||||||
|
# 1. CMD/ENTRYPOINT 写错了
|
||||||
|
# 2. 主进程不是 PID 1(用 tini 或 dumb-init 处理)
|
||||||
|
# 3. 应用启动失败(检查日志)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.4 端口无法访问
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 检查 docker run -p 是否映射
|
||||||
|
docker run -p 3000:3000 ...
|
||||||
|
|
||||||
|
# 2. 检查容器内应用是否监听 0.0.0.0(不是 localhost)
|
||||||
|
# 3. 检查防火墙
|
||||||
|
|
||||||
|
# 4. 用 docker-compose 时,确认 services 定义正确
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、Docker 安全加固
|
||||||
|
|
||||||
|
### 7.1 使用非 root 用户
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# 最简方式(Node 官方镜像已内置 node 用户)
|
||||||
|
FROM node:20-alpine
|
||||||
|
USER node
|
||||||
|
CMD ["node", "server.js"]
|
||||||
|
|
||||||
|
# 手动创建用户(通用模式)
|
||||||
|
FROM node:20-alpine
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --chown=node:node package*.json ./
|
||||||
|
RUN npm ci
|
||||||
|
COPY --chown=node:node . .
|
||||||
|
USER node
|
||||||
|
CMD ["node", "dist/index.js"]
|
||||||
|
```
|
||||||
|
|
||||||
|
> `--chown=user:group` 在 COPY/RUN 时设置文件所有者,**避免 root 拥有文件**后切换到非 root 用户导致权限问题。
|
||||||
|
|
||||||
|
### 7.2 不要安装 build 依赖到生产镜像
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# 错误:所有依赖都装进去了
|
||||||
|
FROM node:20-alpine
|
||||||
|
RUN npm install # devDependencies 也被安装了
|
||||||
|
|
||||||
|
# 正确:生产环境只装 dependencies
|
||||||
|
RUN npm ci --only=production
|
||||||
|
|
||||||
|
# 更正确:多阶段构建
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
|
RUN npm install # 包含 devDependencies
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
FROM node:20-alpine
|
||||||
|
RUN npm ci --only=production
|
||||||
|
COPY --from=builder /app/dist ./dist
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.3 扫描镜像漏洞
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 使用 trivy(推荐)
|
||||||
|
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
|
||||||
|
aquasec/trivy image nginx:latest
|
||||||
|
|
||||||
|
# 扫描指定镜像
|
||||||
|
trivy image my-app:v1.0
|
||||||
|
|
||||||
|
# 只输出高危及以上
|
||||||
|
trivy image --severity HIGH,CRITICAL my-app:v1.0
|
||||||
|
|
||||||
|
# 扫描 Dockerfile 本身(不用构建镜像)
|
||||||
|
trivy config Dockerfile
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.4 密钥管理原则
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# ❌ 绝对不要硬编码密码
|
||||||
|
RUN echo "password=123456" > /app/config.env
|
||||||
|
|
||||||
|
# ❌ 不要在构建时传递密钥(会留在镜像层中)
|
||||||
|
docker build --build-arg DB_PASSWORD=secret .
|
||||||
|
|
||||||
|
# ✅ 运行时传入环境变量
|
||||||
|
docker run -e DB_PASSWORD=secret my-app
|
||||||
|
|
||||||
|
# ✅ 或使用 Docker secrets(Swarm 模式)
|
||||||
|
# ✅ 生产环境用 Kubernetes Secrets / AWS Secrets Manager
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、实战:Node.js + Express 完整 Dockerfile
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# Build stage
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci --only=production
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM node:20-alpine
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /app/node_modules ./node_modules
|
||||||
|
COPY --from=builder /app/dist ./dist
|
||||||
|
COPY --from=builder /app/package.json ./package.json
|
||||||
|
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV PORT=3000
|
||||||
|
|
||||||
|
RUN addgroup -S app && adduser -S app -G app
|
||||||
|
USER app
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
CMD ["node", "dist/server.js"]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> 下一步:理解 Dockerfile 后,学习 [[docker-compose]] 来编排多容器应用。
|
||||||
@@ -0,0 +1,362 @@
|
|||||||
|
# Docker 常用命令
|
||||||
|
|
||||||
|
> 按「生命周期」组织,从拉取镜像到清理收尾,日常 90% 的操作都在以下命令中。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、镜像管理(Image)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 拉取镜像
|
||||||
|
docker pull nginx:latest # 拉取最新标签
|
||||||
|
docker pull redis:7-alpine # 拉取精简版(alpine 体积更小)
|
||||||
|
docker pull node:20-slim
|
||||||
|
|
||||||
|
# 查看所有镜像
|
||||||
|
docker images # 或 docker image ls
|
||||||
|
|
||||||
|
# 搜索镜像
|
||||||
|
docker search nginx # 搜索官方和社区镜像
|
||||||
|
|
||||||
|
# 给镜像打标签
|
||||||
|
docker tag my-app:latest myrepo/my-app:v1.0
|
||||||
|
|
||||||
|
# 删除镜像
|
||||||
|
docker rmi nginx # 删除单个
|
||||||
|
docker rmi $(docker images -q) # 删除所有镜像(谨慎)
|
||||||
|
|
||||||
|
# 构建镜像
|
||||||
|
docker build -t my-app:v1.0 . # 当前目录构建(默认用 Dockerfile)
|
||||||
|
docker build -t my-app:v1.0 -f Dockerfile.prod . # 指定 Dockerfile
|
||||||
|
```
|
||||||
|
|
||||||
|
**镜像分层缓存:** `docker build` 从上到下逐行执行,每一行都会生成一层缓存。把**不变的部分放前面**(安装依赖),**变化的部分放后面**(复制代码),充分利用缓存加速。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、容器管理(Container)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 运行容器
|
||||||
|
docker run -d -p 8080:80 --name web nginx
|
||||||
|
# -d 后台运行(detached)
|
||||||
|
# -p 8080:80 宿主机端口:容器端口
|
||||||
|
# --name 容器名称(方便后续操作)
|
||||||
|
|
||||||
|
# 前台运行(查看日志用)
|
||||||
|
docker run -it --rm nginx bash
|
||||||
|
# -i 交互式 -t 终端 --rm 退出后自动删除
|
||||||
|
|
||||||
|
# 查看所有容器(含已停止的)
|
||||||
|
docker ps -a # 或 docker container ls -a
|
||||||
|
|
||||||
|
# 查看运行中的容器
|
||||||
|
docker ps
|
||||||
|
|
||||||
|
# 启动/停止/重启容器
|
||||||
|
docker start web
|
||||||
|
docker stop web # 优雅停止(发 SIGTERM,等 10s 后 SIGKILL)
|
||||||
|
docker restart web
|
||||||
|
docker kill web # 强制停止(发 SIGKILL)
|
||||||
|
|
||||||
|
# 进入运行中的容器
|
||||||
|
docker exec -it web bash # 在运行中的容器里执行命令
|
||||||
|
docker exec -it web sh # 有些精简镜像没有 bash,用 sh
|
||||||
|
|
||||||
|
# 删除容器
|
||||||
|
docker rm web # 删除已停止的容器
|
||||||
|
docker rm -f web # 强制删除运行中的容器
|
||||||
|
|
||||||
|
# 查看容器日志
|
||||||
|
docker logs web
|
||||||
|
docker logs -f web # 实时跟踪日志(类似 tail -f)
|
||||||
|
docker logs --tail 100 web # 只看最后 100 行
|
||||||
|
```
|
||||||
|
|
||||||
|
**`docker run` 常用参数速查:**
|
||||||
|
|
||||||
|
| 参数 | 作用 |
|
||||||
|
|------|------|
|
||||||
|
| `-d` | 后台运行 |
|
||||||
|
| `-p host:container` | 端口映射 |
|
||||||
|
| `-v host:container` | 挂载卷 |
|
||||||
|
| `-e KEY=VALUE` | 设置环境变量 |
|
||||||
|
| `--name` | 容器名称 |
|
||||||
|
| `--network` | 指定网络 |
|
||||||
|
| `--restart=always` | 容器崩溃/开机自动重启 |
|
||||||
|
| `--rm` | 退出后自动删除(临时调试用) |
|
||||||
|
| `-it` | 交互式终端 |
|
||||||
|
| `--gpus all` | 启用 GPU(NVIDIA) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、网络管理(Network)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看所有网络
|
||||||
|
docker network ls
|
||||||
|
|
||||||
|
# 创建自定义网络
|
||||||
|
docker network create my-network
|
||||||
|
|
||||||
|
# 容器加入指定网络
|
||||||
|
docker run -d --name web1 --network my-network nginx
|
||||||
|
docker run -d --name db1 --network my-network mysql
|
||||||
|
|
||||||
|
# 容器间通过名称互相访问(自动 DNS 解析)
|
||||||
|
docker exec web1 ping db1 # 在同一网络下可直接 ping 容器名
|
||||||
|
|
||||||
|
# 删除网络
|
||||||
|
docker network rm my-network
|
||||||
|
```
|
||||||
|
|
||||||
|
> **为什么需要自定义网络?** Docker 默认的 `bridge` 网络不支持容器名 DNS 解析。自定义网络(`docker network create`)可以让容器通过**名字**互相通信。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、数据卷(Volume)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看所有卷
|
||||||
|
docker volume ls
|
||||||
|
|
||||||
|
# 创建卷
|
||||||
|
docker volume create my-data
|
||||||
|
|
||||||
|
# 挂载卷到容器
|
||||||
|
docker run -d -v my-data:/data --name app nginx
|
||||||
|
|
||||||
|
# 挂载宿主机目录到容器(bind mount)
|
||||||
|
docker run -d -v /host/path:/container/path nginx
|
||||||
|
|
||||||
|
# 只读挂载
|
||||||
|
docker run -d -v my-data:/data:ro nginx
|
||||||
|
|
||||||
|
# 查看卷详情
|
||||||
|
docker volume inspect my-data
|
||||||
|
```
|
||||||
|
|
||||||
|
> **数据持久化原则:** 容器是** ephemeral(易失的)**——删除容器,容器内的数据就没了。必须用 `-v` 把数据存到宿主机或 Docker Volume 中。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、日志与调试
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 进入容器
|
||||||
|
docker exec -it <容器名> bash
|
||||||
|
|
||||||
|
# 查看容器资源占用
|
||||||
|
docker stats
|
||||||
|
|
||||||
|
# 查看容器详情
|
||||||
|
docker inspect web
|
||||||
|
|
||||||
|
# 查看容器进程
|
||||||
|
docker top web
|
||||||
|
|
||||||
|
# 拷贝文件进出容器
|
||||||
|
docker cp container.log web:/tmp/
|
||||||
|
docker cp web:/tmp/remote.log ./local.log
|
||||||
|
|
||||||
|
# 查看容器创建命令
|
||||||
|
docker history my-app:v1.0 # 查看镜像构建历史
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、清理命令(重要!)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 删除所有已停止的容器
|
||||||
|
docker container prune
|
||||||
|
|
||||||
|
# 删除所有未使用的镜像
|
||||||
|
docker image prune -a
|
||||||
|
|
||||||
|
# 删除所有未使用的卷
|
||||||
|
docker volume prune
|
||||||
|
|
||||||
|
# 一键清理(容器+镜像+卷+网络,谨慎使用)
|
||||||
|
docker system prune -a
|
||||||
|
|
||||||
|
# 查看磁盘占用
|
||||||
|
docker system df
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、常用完整命令场景
|
||||||
|
|
||||||
|
### 7.1 运行 Nginx
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
-p 80:80 \
|
||||||
|
-v ./nginx.conf:/etc/nginx/nginx.conf:ro \
|
||||||
|
-v ./html:/usr/share/nginx/html \
|
||||||
|
--name my-nginx \
|
||||||
|
--restart=always \
|
||||||
|
nginx:alpine
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.2 运行 MySQL
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
-p 3306:3306 \
|
||||||
|
-e MYSQL_ROOT_PASSWORD=root123 \
|
||||||
|
-e MYSQL_DATABASE=mydb \
|
||||||
|
-v mysql-data:/var/lib/mysql \
|
||||||
|
--name my-mysql \
|
||||||
|
--restart=always \
|
||||||
|
mysql:8.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.3 运行 Redis
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
-p 6379:6379 \
|
||||||
|
-v redis-data:/data \
|
||||||
|
--name my-redis \
|
||||||
|
redis:7-alpine redis-server --appendonly yes
|
||||||
|
--restart=always
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.4 运行 Node 开发环境
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -it \
|
||||||
|
-p 3000:3000 \
|
||||||
|
-v $(pwd):/app \
|
||||||
|
-w /app \
|
||||||
|
node:20 \
|
||||||
|
bash
|
||||||
|
# -v $(pwd):/app 挂载项目目录,修改代码实时生效
|
||||||
|
# -w /app 设置工作目录
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、进阶:Docker 网络模式
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Docker 提供四种网络模式
|
||||||
|
|
||||||
|
# 1. bridge(默认)— 桥接网络,容器有独立 IP
|
||||||
|
docker run -d --network bridge nginx
|
||||||
|
|
||||||
|
# 2. host — 共享宿主机网络,性能最好但端口会冲突
|
||||||
|
docker run -d --network host nginx
|
||||||
|
|
||||||
|
# 3. none — 无网络(隔离)
|
||||||
|
docker run -d --network none nginx
|
||||||
|
|
||||||
|
# 4. container — 共享另一个容器的网络命名空间
|
||||||
|
docker run -d --network container:web nginx
|
||||||
|
|
||||||
|
# 推荐使用自定义 bridge 网络(前面已讲过)
|
||||||
|
docker network create my-net
|
||||||
|
docker run -d --network my-net --name app nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
## 八、进阶:Docker 日志驱动
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看容器的日志配置
|
||||||
|
docker inspect web | grep LogConfig
|
||||||
|
|
||||||
|
# 日志驱动类型
|
||||||
|
# json-file — 默认,日志写入文件
|
||||||
|
# local — 循环写入,控制大小
|
||||||
|
# syslog — 发送到 syslog
|
||||||
|
# journald — 发送到 systemd journal
|
||||||
|
# none — 不记录日志
|
||||||
|
|
||||||
|
# docker-compose 中限制日志大小
|
||||||
|
services:
|
||||||
|
api:
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m" # 单个日志文件最大 10MB
|
||||||
|
max-file: "3" # 最多保留 3 个文件
|
||||||
|
```
|
||||||
|
|
||||||
|
## 九、进阶:Docker 资源限制
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 限制 CPU 和内存
|
||||||
|
docker run -d \
|
||||||
|
--cpus="1.5" \ # 限制 1.5 个 CPU 核心
|
||||||
|
--memory="512m" \ # 限制 512MB 内存
|
||||||
|
--memory-swap="1g" \ # 允许使用的 swap 总量
|
||||||
|
--pids-limit=100 \ # 最多 100 个进程(防 fork 炸弹)
|
||||||
|
nginx
|
||||||
|
|
||||||
|
# docker-compose 中配置
|
||||||
|
services:
|
||||||
|
api:
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '1.5'
|
||||||
|
memory: 512M
|
||||||
|
reservations:
|
||||||
|
cpus: '0.5'
|
||||||
|
memory: 128M
|
||||||
|
```
|
||||||
|
|
||||||
|
## 十、进阶:Docker Swarm(简易集群)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 初始化集群(单节点)
|
||||||
|
docker swarm init
|
||||||
|
|
||||||
|
# 查看节点
|
||||||
|
docker node ls
|
||||||
|
|
||||||
|
# 创建服务(Swarm 管理方式)
|
||||||
|
docker service create --name web -p 80:80 --replicas 3 nginx
|
||||||
|
|
||||||
|
# 扩容
|
||||||
|
docker service scale web=5
|
||||||
|
|
||||||
|
# 查看服务
|
||||||
|
docker service ls
|
||||||
|
|
||||||
|
# 更新服务(零停机滚动更新)
|
||||||
|
docker service update --image nginx:1.25 web
|
||||||
|
|
||||||
|
# 删除服务
|
||||||
|
docker service rm web
|
||||||
|
|
||||||
|
# 退出集群
|
||||||
|
docker swarm leave
|
||||||
|
|
||||||
|
# 初始化集群 + 管理节点令牌 + 工作节点令牌
|
||||||
|
docker swarm init --advertise-addr <IP>
|
||||||
|
docker swarm join-token manager # 添加管理节点
|
||||||
|
docker swarm join-token worker # 添加工作节点
|
||||||
|
```
|
||||||
|
|
||||||
|
> Swarm 适合轻量级部署。大规模生产环境建议用 Kubernetes。
|
||||||
|
|
||||||
|
## 十一、快速速查表
|
||||||
|
|
||||||
|
| 操作 | 命令 |
|
||||||
|
|------|------|
|
||||||
|
| 启动 Docker 服务 | `systemctl start docker` |
|
||||||
|
| 查看版本 | `docker --version` |
|
||||||
|
| 查看信息 | `docker info` |
|
||||||
|
| 登录镜像仓库 | `docker login` |
|
||||||
|
| 推送镜像 | `docker push my-app:v1.0` |
|
||||||
|
| 导出镜像 | `docker save -o my-app.tar my-app:v1.0` |
|
||||||
|
| 导入镜像 | `docker load -i my-app.tar` |
|
||||||
|
| 查看容器日志 | `docker logs -f <容器名>` |
|
||||||
|
| 进入容器 | `docker exec -it <容器名> bash` |
|
||||||
|
| 停止所有容器 | `docker stop $(docker ps -q)` |
|
||||||
|
| 删除所有容器 | `docker rm -f $(docker ps -aq)` |
|
||||||
|
| 查看磁盘占用 | `docker system df` |
|
||||||
|
| 全面清理 | `docker system prune -a` |
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# Docker 学习笔记
|
||||||
|
|
||||||
|
> Docker 容器化技术全套入门资料,从常用命令到 Dockerfile 编写再到多容器编排。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📂 文档索引
|
||||||
|
|
||||||
|
| 文档 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| [[Docker常用命令]] | 镜像/容器/网络/卷的常用命令,日常 90% 操作 |
|
||||||
|
| [[Dockerfile编写指南]] | Dockerfile 指令详解、多阶段构建、最佳实践 |
|
||||||
|
| [[docker-compose使用指南]] | 多容器编排、健康检查、多环境配置、完整模板 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 学习路径
|
||||||
|
|
||||||
|
建议按以下顺序学习:
|
||||||
|
|
||||||
|
1. **[[Docker常用命令]]** — 先掌握单个容器的基本操作
|
||||||
|
2. **[[Dockerfile编写指南]]** — 学会构建自己的镜像
|
||||||
|
3. **[[docker-compose使用指南]]** — 学会用 Compose 编排多容器应用
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔑 核心概念速记
|
||||||
|
|
||||||
|
| 概念 | 一句话 |
|
||||||
|
|------|--------|
|
||||||
|
| **镜像(Image)** | 只读模板,类似「类」 |
|
||||||
|
| **容器(Container)** | 镜像的运行实例,类似「对象」 |
|
||||||
|
| **Dockerfile** | 构建镜像的指令文件 |
|
||||||
|
| **Volume** | 持久化存储,容器删了数据还在 |
|
||||||
|
| **Network** | 容器间通信网络 |
|
||||||
|
| **Compose** | 用 YAML 定义和启动多容器应用 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> Docker 容器是**易失的**,数据必须用 `-v` 持久化;镜像构建要善用**多阶段构建**和**层缓存**。
|
||||||
@@ -0,0 +1,896 @@
|
|||||||
|
# Docker Compose 使用指南
|
||||||
|
|
||||||
|
> Docker Compose 用 **YAML 文件**定义多容器应用,一条 `docker compose up` 启动所有服务。**开发环境和生产环境都大量使用。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 快速开始(TL;DR)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 创建 docker-compose.yml
|
||||||
|
# 2. 启动所有服务
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# 3. 查看状态
|
||||||
|
docker compose ps
|
||||||
|
|
||||||
|
# 4. 查看日志
|
||||||
|
docker compose logs -f
|
||||||
|
|
||||||
|
# 5. 停止并清理
|
||||||
|
docker compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
**目录:** [基本结构](#一基本结构) · [完整示例](#二完整示例) · [常用配置](#三常用配置详解) · [多环境](#四多环境配置) · [常用命令](#五常用命令) · [常见问题](#六常见问题) · [模板速查](#七常用模板速查) · [格式演进](#八compose-文件格式演进) · [高级配置](#九高级配置) · [最佳实践](#十最佳实践) · [速查卡](#十一快速参考卡)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、基本结构
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker-compose.yml
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
web: # 前端/后端应用
|
||||||
|
db: # 数据库
|
||||||
|
redis: # 缓存
|
||||||
|
nginx: # 反向代理
|
||||||
|
|
||||||
|
networks: # 网络定义
|
||||||
|
volumes: # 数据卷定义
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、完整示例
|
||||||
|
|
||||||
|
### 2.1 Node.js + MySQL + Redis 全栈项目
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
# ========== 后端应用 ==========
|
||||||
|
api:
|
||||||
|
build:
|
||||||
|
context: ./server
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
args:
|
||||||
|
NODE_ENV: production
|
||||||
|
container_name: my-api
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
- DB_HOST=db
|
||||||
|
- DB_PORT=3306
|
||||||
|
- DB_USER=root
|
||||||
|
- DB_PASSWORD=root123
|
||||||
|
- DB_NAME=mydb
|
||||||
|
- REDIS_HOST=redis
|
||||||
|
- REDIS_PORT=6379
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_started
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- app-network
|
||||||
|
volumes:
|
||||||
|
- api-logs:/app/logs
|
||||||
|
|
||||||
|
# ========== 前端应用 ==========
|
||||||
|
web:
|
||||||
|
build:
|
||||||
|
context: ./client
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: my-web
|
||||||
|
ports:
|
||||||
|
- "80:3000"
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- app-network
|
||||||
|
|
||||||
|
# ========== 数据库 ==========
|
||||||
|
db:
|
||||||
|
image: mysql:8.0
|
||||||
|
container_name: my-db
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: root123
|
||||||
|
MYSQL_DATABASE: mydb
|
||||||
|
MYSQL_USER: admin
|
||||||
|
MYSQL_PASSWORD: admin123
|
||||||
|
ports:
|
||||||
|
- "3306:3306"
|
||||||
|
volumes:
|
||||||
|
- db-data:/var/lib/mysql
|
||||||
|
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- app-network
|
||||||
|
|
||||||
|
# ========== 缓存 ==========
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
container_name: my-redis
|
||||||
|
ports:
|
||||||
|
- "6379:6379"
|
||||||
|
volumes:
|
||||||
|
- redis-data:/data
|
||||||
|
command: redis-server --appendonly yes
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- app-network
|
||||||
|
|
||||||
|
# ========== 反向代理 ==========
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: my-nginx
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
depends_on:
|
||||||
|
- web
|
||||||
|
- api
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- app-network
|
||||||
|
|
||||||
|
# ========== 网络 ==========
|
||||||
|
networks:
|
||||||
|
app-network:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
# ========== 数据卷 ==========
|
||||||
|
volumes:
|
||||||
|
db-data:
|
||||||
|
redis-data:
|
||||||
|
api-logs:
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、常用配置详解
|
||||||
|
|
||||||
|
### 3.1 `build` — 从 Dockerfile 构建
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
# 方式一:当前目录(自动找 Dockerfile)
|
||||||
|
web:
|
||||||
|
build: .
|
||||||
|
|
||||||
|
# 方式二:指定上下文和 Dockerfile
|
||||||
|
web:
|
||||||
|
build:
|
||||||
|
context: ./frontend
|
||||||
|
dockerfile: Dockerfile.prod
|
||||||
|
|
||||||
|
# 方式三:加构建参数
|
||||||
|
web:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
args:
|
||||||
|
NODE_ENV: production
|
||||||
|
VERSION: 1.0.0
|
||||||
|
target: production # 多阶段构建指定阶段
|
||||||
|
|
||||||
|
# 方式四:直接用已有镜像(不构建)
|
||||||
|
db:
|
||||||
|
image: mysql:8.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 `depends_on` — 启动顺序
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
api:
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy # 等 db 健康检查通过
|
||||||
|
redis:
|
||||||
|
condition: service_started # 等 redis 启动即可
|
||||||
|
```
|
||||||
|
|
||||||
|
> **注意:** `depends_on` 只管**启动顺序**,不管**可用性**。`condition: service_healthy` + `healthcheck` 才能真正等服务就绪。
|
||||||
|
|
||||||
|
### 3.3 `healthcheck` — 健康检查
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: mysql:8.0
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||||
|
interval: 10s # 每 10 秒检查一次
|
||||||
|
timeout: 5s # 超时时间
|
||||||
|
retries: 5 # 最多重试 5 次
|
||||||
|
start_period: 30s # 容器启动后等 30 秒才开始检查(给数据库初始化时间)
|
||||||
|
```
|
||||||
|
|
||||||
|
**常见健康检查命令:**
|
||||||
|
|
||||||
|
| 服务 | 健康检查命令 |
|
||||||
|
|------|-------------|
|
||||||
|
| MySQL | `mysqladmin ping -h localhost` |
|
||||||
|
| Redis | `redis-cli ping` |
|
||||||
|
| Node.js | `wget -qO- http://localhost:3000/health || exit 1` |
|
||||||
|
| Nginx | `curl -f http://localhost/ || exit 1` |
|
||||||
|
| PostgreSQL | `pg_isready -h localhost` |
|
||||||
|
|
||||||
|
### 3.4 `environment` — 环境变量
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# 方式一:列表格式
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
- DB_HOST=db
|
||||||
|
|
||||||
|
# 方式二:字典格式(推荐,更易读)
|
||||||
|
environment:
|
||||||
|
NODE_ENV: production
|
||||||
|
DB_HOST: db
|
||||||
|
DB_PORT: 3306
|
||||||
|
|
||||||
|
# 方式三:从 .env 文件加载(最推荐)
|
||||||
|
env_file:
|
||||||
|
- .env.production
|
||||||
|
|
||||||
|
# 混合使用
|
||||||
|
environment:
|
||||||
|
NODE_ENV: production
|
||||||
|
DB_HOST: db
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.5 `volumes` — 数据持久化
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
volumes:
|
||||||
|
# 命名卷(推荐,Docker 管理)
|
||||||
|
volumes:
|
||||||
|
- db-data:/var/lib/mysql
|
||||||
|
|
||||||
|
# 绑定挂载(绑定到宿主机路径)
|
||||||
|
volumes:
|
||||||
|
- ./data:/app/data
|
||||||
|
|
||||||
|
# 只读挂载
|
||||||
|
volumes:
|
||||||
|
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
|
||||||
|
# 匿名卷(不需要命名)
|
||||||
|
volumes:
|
||||||
|
- /tmp/data
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.6 `restart` — 重启策略
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
restart: always # 永远重启(包括手动停止后重启)
|
||||||
|
restart: on-failure # 仅失败时重启
|
||||||
|
restart: unless-stopped # 除非手动停止,否则重启(推荐)
|
||||||
|
restart: no # 不自动重启(默认)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.7 `ports` vs `expose`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
ports:
|
||||||
|
- "8080:80" # 宿主端口:容器端口(外部可访问)
|
||||||
|
- "127.0.0.1:8080:80" # 仅本地可访问
|
||||||
|
- "3000" # 随机端口
|
||||||
|
|
||||||
|
expose:
|
||||||
|
- "3000" # 仅容器间通信,外部不可访问
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、多环境配置
|
||||||
|
|
||||||
|
### 4.1 使用覆盖文件
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker-compose.yml(基础配置)
|
||||||
|
services:
|
||||||
|
api:
|
||||||
|
build: .
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=development
|
||||||
|
volumes:
|
||||||
|
- ./server:/app # 开发时热重载
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: mysql:8.0
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker-compose.prod.yml(生产覆盖)
|
||||||
|
services:
|
||||||
|
api:
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
# 覆盖开发时的 volume 挂载
|
||||||
|
volumes: [] # 生产时不要挂载宿主机目录
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 使用:基础 + 生产覆盖
|
||||||
|
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 更简洁的方式(环境变量控制)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker-compose.yml
|
||||||
|
services:
|
||||||
|
api:
|
||||||
|
build: .
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=${NODE_ENV:-development}
|
||||||
|
- DB_HOST=${DB_HOST:-db}
|
||||||
|
volumes:
|
||||||
|
- ${MOUNT_VOLUMES:-./server:/app}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 开发环境(默认)
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# 生产环境
|
||||||
|
NODE_ENV=production MOUNT_VOLUMES="" docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、常用命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 启动所有服务(后台)
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# 启动所有服务(前台,看日志)
|
||||||
|
docker compose up
|
||||||
|
|
||||||
|
# 启动单个服务
|
||||||
|
docker compose up -d db redis
|
||||||
|
|
||||||
|
# 停止所有服务(不删除容器和数据卷)
|
||||||
|
docker compose stop
|
||||||
|
|
||||||
|
# 停止并删除所有容器
|
||||||
|
docker compose down
|
||||||
|
|
||||||
|
# 停止并删除容器、网络
|
||||||
|
docker compose down --rmi all
|
||||||
|
|
||||||
|
# 重建镜像并启动(代码改动后)
|
||||||
|
docker compose up -d --build
|
||||||
|
|
||||||
|
# 重建并重新初始化数据卷
|
||||||
|
docker compose down -v
|
||||||
|
docker compose up -d --build
|
||||||
|
|
||||||
|
# 查看服务状态
|
||||||
|
docker compose ps
|
||||||
|
|
||||||
|
# 查看服务日志
|
||||||
|
docker compose logs
|
||||||
|
docker compose logs -f api # 只看 api 服务的日志
|
||||||
|
docker compose logs -f --tail 100 db # 只看 db 的最后 100 行
|
||||||
|
|
||||||
|
# 进入运行中的容器
|
||||||
|
docker compose exec api bash
|
||||||
|
docker compose exec db mysql -u root -p
|
||||||
|
|
||||||
|
# 执行单次命令
|
||||||
|
docker compose run api npm run db:migrate
|
||||||
|
docker compose run --rm web npm test # --rm 执行完自动删除
|
||||||
|
|
||||||
|
# 查看资源占用
|
||||||
|
docker compose ps
|
||||||
|
|
||||||
|
# 构建并启动
|
||||||
|
docker compose build
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# 更新镜像
|
||||||
|
docker compose pull
|
||||||
|
docker compose up -d --pull always
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、常见问题
|
||||||
|
|
||||||
|
### 6.1 容器间无法互相访问
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# 确保所有服务在同一网络下
|
||||||
|
services:
|
||||||
|
api:
|
||||||
|
networks: [app-network]
|
||||||
|
db:
|
||||||
|
networks: [app-network]
|
||||||
|
|
||||||
|
networks:
|
||||||
|
app-network:
|
||||||
|
driver: bridge
|
||||||
|
```
|
||||||
|
|
||||||
|
> 默认情况下,Docker Compose 会为同一个 compose 文件创建同一个网络,不同 compose 文件的容器**不能互相访问**。
|
||||||
|
|
||||||
|
### 6.2 数据库启动慢,应用连不上
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
api:
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy # 健康检查通过才启动
|
||||||
|
```
|
||||||
|
|
||||||
|
或在应用代码中添加重试逻辑。
|
||||||
|
|
||||||
|
### 6.3 端口冲突
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看端口占用
|
||||||
|
netstat -ano | findstr :3000 # Windows
|
||||||
|
lsof -i :3000 # macOS/Linux
|
||||||
|
```
|
||||||
|
|
||||||
|
修改 `docker-compose.yml` 中的端口映射:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
ports:
|
||||||
|
- "3001:3000" # 宿主机 3001 → 容器 3000
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.4 `.env` 文件
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 在项目根目录创建 .env 文件
|
||||||
|
DB_HOST=db
|
||||||
|
DB_PASSWORD=root123
|
||||||
|
NODE_ENV=production
|
||||||
|
COMPOSE_PROJECT_NAME=myapp
|
||||||
|
```
|
||||||
|
|
||||||
|
> Docker Compose 会**自动读取**当前目录的 `.env` 文件,无需额外配置。`$DB_HOST` 在 `docker-compose.yml` 中会被自动替换。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、常用模板速查
|
||||||
|
|
||||||
|
### 7.1 纯前端静态站点(Nginx)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
restart: always
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.2 Node.js + PostgreSQL
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
build: .
|
||||||
|
ports: ["3000:3000"]
|
||||||
|
environment:
|
||||||
|
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=user
|
||||||
|
- POSTGRES_PASSWORD=pass
|
||||||
|
- POSTGRES_DB=mydb
|
||||||
|
volumes:
|
||||||
|
- pg-data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U user"]
|
||||||
|
interval: 10s
|
||||||
|
|
||||||
|
networks:
|
||||||
|
volumes:
|
||||||
|
pg-data:
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.3 Next.js 全功能模板
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
target: production
|
||||||
|
ports: ["3000:3000"]
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
- DATABASE_URL=$DATABASE_URL
|
||||||
|
- NEXTAUTH_SECRET=$NEXTAUTH_SECRET
|
||||||
|
restart: always
|
||||||
|
networks: [app-network]
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
environment:
|
||||||
|
- POSTGRES_DB=myapp
|
||||||
|
- POSTGRES_USER=app
|
||||||
|
- POSTGRES_PASSWORD=$DB_PASSWORD
|
||||||
|
volumes: [pg-data:/var/lib/postgresql/data]
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U app"]
|
||||||
|
networks: [app-network]
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
volumes: [redis-data:/data]
|
||||||
|
networks: [app-network]
|
||||||
|
|
||||||
|
networks:
|
||||||
|
app-network:
|
||||||
|
volumes:
|
||||||
|
pg-data:
|
||||||
|
redis-data:
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、Compose 文件格式演进
|
||||||
|
|
||||||
|
### 8.1 新版 Compose Specification(推荐)
|
||||||
|
|
||||||
|
**不再需要 `version` 字段**,Docker Compose V2 起默认使用 Compose Specification 格式:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# 新版写法(推荐)
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: node:20-alpine
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
environment:
|
||||||
|
NODE_ENV: production
|
||||||
|
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
data:
|
||||||
|
```
|
||||||
|
|
||||||
|
> **关键区别:**
|
||||||
|
> - V3 及以下:必须写 `version: '3.8'`,字段名用点号分隔(如 `networks.default`)
|
||||||
|
> - V4 及以上(Compose Specification):**不需要 version**,字段名用嵌套格式(如 `networks:` 下的 `default:`)
|
||||||
|
|
||||||
|
### 8.2 如何判断使用哪种格式
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看 Compose 版本
|
||||||
|
docker compose version
|
||||||
|
|
||||||
|
# Compose V2+(2020 年起)→ 使用 Compose Specification 格式
|
||||||
|
# 使用 `docker compose`(注意是空格,不是连字符)
|
||||||
|
```
|
||||||
|
|
||||||
|
> **建议:** 新项目直接使用无 version 的新格式,兼容性更好。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、高级配置
|
||||||
|
|
||||||
|
### 9.1 `deploy` — 资源限制(适用于 Compose V3+)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
api:
|
||||||
|
image: my-api:latest
|
||||||
|
deploy:
|
||||||
|
replicas: 3 # 副本数(Swarm 模式)
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
delay: 5s
|
||||||
|
max_attempts: 3
|
||||||
|
window: 120s
|
||||||
|
update_config:
|
||||||
|
parallelism: 1 # 每次更新 1 个容器
|
||||||
|
delay: 10s
|
||||||
|
order: start-first # 先启动新再停止旧
|
||||||
|
rollback_config:
|
||||||
|
parallelism: 1
|
||||||
|
delay: 5s
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '0.5' # 最多 0.5 核 CPU
|
||||||
|
memory: 512M # 最多 512MB 内存
|
||||||
|
reservations:
|
||||||
|
cpus: '0.25'
|
||||||
|
memory: 128M
|
||||||
|
```
|
||||||
|
|
||||||
|
> **注意:** `deploy` 在 `docker compose up`(非 Swarm 模式)下**部分字段不生效**(`replicas`、`update_config` 等)。资源限制 `limits/reservations` 在普通模式下仍然生效。
|
||||||
|
|
||||||
|
### 9.2 `profiles` — 按需启停服务
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: nginx:alpine
|
||||||
|
profiles: ["app"]
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
profiles: ["db", "app"]
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
profiles: ["cache", "app"]
|
||||||
|
|
||||||
|
monitoring:
|
||||||
|
image: grafana/grafana
|
||||||
|
profiles: ["monitoring"]
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 启动 app 相关服务(web + db + redis)
|
||||||
|
docker compose --profile app up -d
|
||||||
|
|
||||||
|
# 启动 app + 监控
|
||||||
|
docker compose --profile app --profile monitoring up -d
|
||||||
|
|
||||||
|
# 启动所有带 profile 的服务
|
||||||
|
docker compose --profile app --profile db --profile cache --profile monitoring up -d
|
||||||
|
|
||||||
|
# 启动所有服务(包括无 profile 的)
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# 查看当前 profile 配置
|
||||||
|
docker compose config --profiles
|
||||||
|
```
|
||||||
|
|
||||||
|
> **场景:** 开发时只启动 `app`,测试时加上 `db`,生产环境加上 `monitoring`。
|
||||||
|
|
||||||
|
### 9.3 `configs` — 配置文件管理
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
configs:
|
||||||
|
- source: nginx_conf
|
||||||
|
target: /etc/nginx/conf.d/default.conf
|
||||||
|
mode: 0444 # 文件权限
|
||||||
|
|
||||||
|
app:
|
||||||
|
image: my-app:latest
|
||||||
|
configs:
|
||||||
|
- source: app_config
|
||||||
|
target: /etc/app/config.yaml
|
||||||
|
mode: 0440
|
||||||
|
|
||||||
|
configs:
|
||||||
|
nginx_conf:
|
||||||
|
file: ./configs/nginx.conf
|
||||||
|
app_config:
|
||||||
|
file: ./configs/app.yaml
|
||||||
|
external: false # 本地文件
|
||||||
|
```
|
||||||
|
|
||||||
|
> **适用场景:** 需要分发配置文件但不想硬编码到镜像中。
|
||||||
|
|
||||||
|
### 9.4 `secrets` — 敏感信息管理
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: mysql:8.0
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_pass
|
||||||
|
secrets:
|
||||||
|
- db_root_pass
|
||||||
|
- db_config
|
||||||
|
|
||||||
|
secrets:
|
||||||
|
db_root_pass:
|
||||||
|
file: ./secrets/db_root_pass.txt # 从文件读取
|
||||||
|
db_config:
|
||||||
|
string: '{"max_connections": 100}' # 直接写字符串
|
||||||
|
```
|
||||||
|
|
||||||
|
> **安全建议:** 敏感信息不要写死在 `docker-compose.yml` 中,使用 `secrets` 或 `.env` 文件管理。
|
||||||
|
|
||||||
|
### 9.5 其他实用配置
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: node:20-alpine
|
||||||
|
|
||||||
|
# 指定运行用户
|
||||||
|
user: "1000:1000"
|
||||||
|
|
||||||
|
# 工作目录
|
||||||
|
working_dir: /app
|
||||||
|
|
||||||
|
# 覆盖默认入口点和命令
|
||||||
|
entrypoint: ["node"]
|
||||||
|
command: ["server.js"]
|
||||||
|
|
||||||
|
# 容器别名(同一 compose 内通过别名访问)
|
||||||
|
container_name: my-app
|
||||||
|
|
||||||
|
# 标签(元数据)
|
||||||
|
labels:
|
||||||
|
- "com.example.description=API Server"
|
||||||
|
- "com.example.environment=production"
|
||||||
|
|
||||||
|
# 时区
|
||||||
|
environment:
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
|
|
||||||
|
# 挂载共享内存(深度学习场景)
|
||||||
|
shm_size: '2gb'
|
||||||
|
|
||||||
|
# 安全选项
|
||||||
|
security_opt:
|
||||||
|
- no-new-privileges:true
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
|
cap_add:
|
||||||
|
- NET_BIND_SERVICE
|
||||||
|
|
||||||
|
# 资源限制
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '1.0'
|
||||||
|
memory: 1G
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十、最佳实践
|
||||||
|
|
||||||
|
### 10.1 安全性
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# ✅ 使用非 root 用户
|
||||||
|
user: "1000:1000"
|
||||||
|
|
||||||
|
# ✅ 最小化权限
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
|
security_opt:
|
||||||
|
- no-new-privileges:true
|
||||||
|
|
||||||
|
# ✅ 敏感信息用 secrets 或 .env
|
||||||
|
secrets:
|
||||||
|
- db_password
|
||||||
|
|
||||||
|
# ❌ 避免使用 privileged
|
||||||
|
# privileged: true
|
||||||
|
|
||||||
|
# ❌ 避免绑定 0.0.0.0
|
||||||
|
# ports:
|
||||||
|
# - "0.0.0.0:3000:3000"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10.2 可靠性
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# ✅ 所有外部依赖都加 healthcheck
|
||||||
|
db:
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||||
|
start_period: 30s
|
||||||
|
|
||||||
|
# ✅ 合理的重启策略
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# ✅ 依赖顺序用 condition
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10.3 可维护性
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# ✅ 使用 .env 管理变量
|
||||||
|
# .env
|
||||||
|
COMPOSE_PROJECT_NAME=myapp
|
||||||
|
MYSQL_ROOT_PASSWORD=xxxxx
|
||||||
|
NODE_ENV=production
|
||||||
|
|
||||||
|
# docker-compose.yml
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: mysql:8.0
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- db-data:/var/lib/mysql
|
||||||
|
|
||||||
|
# ✅ 命名卷而不是绑定挂载(数据持久化)
|
||||||
|
volumes:
|
||||||
|
db-data: # Docker 管理,更安全
|
||||||
|
|
||||||
|
# ✅ 用 profiles 组织服务
|
||||||
|
# 开发只启动 app + db
|
||||||
|
# docker compose --profile dev up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10.4 性能优化
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# ✅ 生产环境使用 Alpine 镜像
|
||||||
|
image: node:20-alpine # 约 150MB
|
||||||
|
# vs
|
||||||
|
image: node:20 # 约 1GB
|
||||||
|
|
||||||
|
# ✅ 限制资源使用
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '0.5'
|
||||||
|
memory: 512M
|
||||||
|
|
||||||
|
# ✅ 只暴露必要的端口
|
||||||
|
# ❌ 数据库不要暴露到宿主机
|
||||||
|
# db:
|
||||||
|
# ports:
|
||||||
|
# - "3306:3306" # 删除这行
|
||||||
|
|
||||||
|
# ✅ 使用 expose 代替 ports(容器间通信)
|
||||||
|
db:
|
||||||
|
expose:
|
||||||
|
- "3306"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十一、快速参考卡
|
||||||
|
|
||||||
|
| 字段 | 用途 | 示例 |
|
||||||
|
|------|------|------|
|
||||||
|
| `image` | 使用已有镜像 | `image: nginx:alpine` |
|
||||||
|
| `build` | 从 Dockerfile 构建 | `build: ./app` |
|
||||||
|
| `ports` | 端口映射(外部可访问) | `"80:80"` |
|
||||||
|
| `expose` | 端口暴露(仅容器间) | `"3000"` |
|
||||||
|
| `volumes` | 数据持久化 | `data:/var/lib/mysql` |
|
||||||
|
| `environment` | 环境变量 | `NODE_ENV: production` |
|
||||||
|
| `depends_on` | 启动依赖 | `db: condition: service_healthy` |
|
||||||
|
| `healthcheck` | 健康检查 | `test: ["CMD", "curl", ...]` |
|
||||||
|
| `restart` | 重启策略 | `unless-stopped` |
|
||||||
|
| `networks` | 网络归属 | `app-network` |
|
||||||
|
| `profiles` | 按需启停 | `["dev", "monitoring"]` |
|
||||||
|
| `secrets` | 敏感信息管理 | `file: ./secrets/xxx` |
|
||||||
|
| `configs` | 配置文件管理 | `target: /etc/app/config` |
|
||||||
|
| `deploy.resources` | 资源限制 | `cpus: '0.5', memory: 512M` |
|
||||||
|
| `container_name` | 固定容器名 | `my-container` |
|
||||||
|
| `user` | 运行用户 | `"1000:1000"` |
|
||||||
Reference in New Issue
Block a user