- 添加 Jenkinsfile 和 Jenkinsfile.docker 支持 Docker 构建 - 添加 Docker Compose 生产环境配置 - 添加后端 Dockerfile - 添加 Docker 部署脚本 - 添加部署文档 (JENKINS_DEPLOY.md, DOCKER_DEPLOY.md, DOCKER_ISOLATION.md) - 更新 nginx 配置支持生产环境部署
11 KiB
11 KiB
Docker 隔离架构说明
隔离层次概览
当前项目实现了完全隔离的架构,从构建到运行都在 Docker 容器中,与宿主机完全隔离。
┌─────────────────────────────────────────────────────────────┐
│ 宿主机 (Host) │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Jenkins 服务器 │ │
│ │ ┌──────────────────────────────────────────────┐ │ │
│ │ │ Docker 容器: node:18 (构建阶段) │ │ │
│ │ │ - 安装依赖 │ │ │
│ │ │ - 构建前端 │ │ │
│ │ │ - 构建后端 │ │ │
│ │ │ ✅ 与 Jenkins 服务器隔离 │ │ │
│ │ └──────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ ↓ │
│ 部署到远程服务器 │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 远程服务器 (180.76.180.105) │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────┐ │ │
│ │ │ Docker 容器: nginx:alpine │ │ │
│ │ │ - 端口: 8080:80 │ │ │
│ │ │ - 网络: ai-learning-network │ │ │
│ │ │ ✅ 与宿主机和其他容器隔离 │ │ │
│ │ └──────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────┐ │ │
│ │ │ Docker 容器: backend (node:18-alpine) │ │ │
│ │ │ - 端口: 3001:3001 │ │ │
│ │ │ - 网络: ai-learning-network │ │ │
│ │ │ ✅ 与宿主机和其他容器隔离 │ │ │
│ │ └──────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────┐ │ │
│ │ │ 宿主机文件系统 (仅数据持久化) │ │ │
│ │ │ - /opt/nginx/html/ai/current/ │ │ │
│ │ │ - 数据库文件 (volume 挂载) │ │ │
│ │ └──────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
隔离层次详解
1. 构建阶段隔离(Jenkins 服务器)
位置: Jenkins 服务器
容器: node:18
隔离内容:
def nodeImage = docker.image("node:18")
nodeImage.inside('-v /var/run/docker.sock:/var/run/docker.sock') {
// 所有构建操作都在容器中执行
npm install
npm run build
}
隔离效果:
- ✅ 文件系统隔离: 构建过程不影响 Jenkins 服务器文件系统
- ✅ 依赖隔离: 不需要在 Jenkins 服务器安装 Node.js、npm
- ✅ 版本隔离: 使用固定版本的 Node.js,不受宿主机影响
- ✅ 环境隔离: 每次构建都是干净的环境,无历史残留
好处:
- Jenkins 服务器保持干净,不需要安装各种构建工具
- 多个项目可以使用不同版本的 Node.js,互不干扰
- 构建失败不会影响 Jenkins 服务器
2. 运行阶段隔离(生产服务器)
2.1 Nginx 容器隔离
nginx:
image: nginx:alpine
container_name: ai-learning-nginx
ports:
- "8080:80"
networks:
- ai-learning-network
隔离效果:
- ✅ 进程隔离: Nginx 进程在容器内运行,与宿主机进程隔离
- ✅ 网络隔离: 使用独立的 Docker 网络
ai-learning-network - ✅ 文件系统隔离: 只能访问挂载的 volume
- ✅ 端口隔离: 使用 8080 端口,不影响宿主机 80 端口
2.2 Backend 容器隔离
backend:
build:
context: /opt/nginx/html/ai/current/backend
dockerfile: Dockerfile
container_name: ai-learning-backend
ports:
- "3001:3001"
networks:
- ai-learning-network
隔离效果:
- ✅ 运行时隔离: Node.js 应用在容器内运行
- ✅ 依赖隔离: 不需要在宿主机安装 Node.js
- ✅ 环境变量隔离: 容器内独立的环境变量
- ✅ 网络隔离: 只能通过 Docker 网络与其他容器通信
3. 网络隔离
networks:
ai-learning-network:
driver: bridge
隔离效果:
- ✅ 独立网络: 容器在独立的 Docker 网络中
- ✅ 服务发现: 容器间通过服务名通信(如
backend:3001) - ✅ 端口隔离: 容器端口不直接暴露给宿主机(除非映射)
- ✅ 安全隔离: 外部无法直接访问容器内部网络
完全隔离的好处
1. 安全性
宿主机 ← 完全隔离 → 应用容器
- ✅ 进程隔离: 容器崩溃不影响宿主机
- ✅ 文件系统隔离: 容器无法访问宿主机敏感文件
- ✅ 网络隔离: 容器间通信受控
- ✅ 权限隔离: 容器以非 root 用户运行(可配置)
2. 环境一致性
开发环境 = 构建环境 = 生产环境
- ✅ 版本一致: 所有环境使用相同的 Node.js 版本
- ✅ 依赖一致: 依赖版本锁定在 package.json
- ✅ 配置一致: Docker 配置统一管理
3. 资源隔离
容器 A ← 资源限制 → 容器 B
- ✅ CPU 限制: 可以限制容器 CPU 使用率
- ✅ 内存限制: 可以限制容器内存使用
- ✅ 磁盘限制: 可以限制容器磁盘使用
4. 易于管理
- ✅ 独立更新: 可以单独更新某个容器,不影响其他
- ✅ 快速回滚: 可以快速回滚到之前的镜像版本
- ✅ 日志隔离: 每个容器的日志独立管理
- ✅ 监控隔离: 可以单独监控每个容器
数据持久化(唯一与宿主机共享的部分)
虽然容器是隔离的,但某些数据需要持久化:
volumes:
# 数据库文件(需要持久化)
- /opt/nginx/html/ai/current/backend/prisma:/app/prisma
# 前端静态文件(只读)
- /opt/nginx/html/ai/current:/usr/share/nginx/html:ro
# 日志文件(需要持久化)
- /opt/nginx/html/ai/current/docker/logs:/var/log/nginx
说明:
- 数据库文件需要持久化,所以挂载到宿主机
- 前端文件是只读挂载,容器无法修改
- 日志文件挂载到宿主机,方便查看和管理
隔离验证
1. 检查容器隔离
# 查看运行中的容器
docker ps
# 查看容器网络
docker network inspect ai-learning-network
# 查看容器进程(在宿主机上)
ps aux | grep nginx # 看不到容器内的进程
# 进入容器查看
docker exec -it ai-learning-nginx sh
# 在容器内:无法访问宿主机其他文件(除了挂载的 volume)
2. 检查网络隔离
# 在宿主机上无法直接访问容器内部网络
curl http://backend:3001 # ❌ 失败,backend 只在 Docker 网络内可访问
# 在容器内可以访问
docker exec -it ai-learning-nginx sh
curl http://backend:3001 # ✅ 成功,在同一 Docker 网络内
3. 检查文件系统隔离
# 容器内的文件系统是独立的
docker exec -it ai-learning-backend ls /app
# 只能看到容器内的文件,看不到宿主机其他目录(除了挂载的 volume)
安全建议
虽然已经实现了完全隔离,但还可以进一步加强:
1. 使用非 root 用户运行容器
# 在 Dockerfile 中
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
USER nodejs
2. 限制资源使用
services:
backend:
deploy:
resources:
limits:
cpus: '1'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
3. 只读文件系统(除了必要目录)
services:
nginx:
read_only: true
tmpfs:
- /tmp
- /var/cache/nginx
4. 网络策略
services:
backend:
networks:
- ai-learning-network
# 不暴露端口到宿主机,只允许 nginx 访问
# ports: [] # 注释掉端口映射
总结
是的,当前架构实现了完全隔离:
- ✅ 构建阶段: 在 Docker 容器中构建,与 Jenkins 服务器隔离
- ✅ 运行阶段: 应用在 Docker 容器中运行,与宿主机隔离
- ✅ 网络隔离: 容器在独立的 Docker 网络中
- ✅ 文件系统隔离: 容器只能访问挂载的 volume
- ✅ 进程隔离: 容器进程与宿主机进程隔离
唯一与宿主机共享的:
- 数据文件(数据库、日志)- 通过 volume 挂载
- 端口映射(8080, 3001)- 用于外部访问
这种架构提供了最大的安全性和可移植性,同时保持了必要的数据持久化。