ai_learn_node/DOCKER_ISOLATION.md

296 lines
11 KiB
Markdown
Raw Permalink Normal View History

# 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`
**隔离内容**:
```groovy
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 容器隔离
```yaml
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 容器隔离
```yaml
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. 网络隔离
```yaml
networks:
ai-learning-network:
driver: bridge
```
**隔离效果**:
-**独立网络**: 容器在独立的 Docker 网络中
-**服务发现**: 容器间通过服务名通信(如 `backend:3001`
-**端口隔离**: 容器端口不直接暴露给宿主机(除非映射)
-**安全隔离**: 外部无法直接访问容器内部网络
## 完全隔离的好处
### 1. 安全性
```
宿主机 ← 完全隔离 → 应用容器
```
-**进程隔离**: 容器崩溃不影响宿主机
-**文件系统隔离**: 容器无法访问宿主机敏感文件
-**网络隔离**: 容器间通信受控
-**权限隔离**: 容器以非 root 用户运行(可配置)
### 2. 环境一致性
```
开发环境 = 构建环境 = 生产环境
```
-**版本一致**: 所有环境使用相同的 Node.js 版本
-**依赖一致**: 依赖版本锁定在 package.json
-**配置一致**: Docker 配置统一管理
### 3. 资源隔离
```
容器 A ← 资源限制 → 容器 B
```
-**CPU 限制**: 可以限制容器 CPU 使用率
-**内存限制**: 可以限制容器内存使用
-**磁盘限制**: 可以限制容器磁盘使用
### 4. 易于管理
-**独立更新**: 可以单独更新某个容器,不影响其他
-**快速回滚**: 可以快速回滚到之前的镜像版本
-**日志隔离**: 每个容器的日志独立管理
-**监控隔离**: 可以单独监控每个容器
## 数据持久化(唯一与宿主机共享的部分)
虽然容器是隔离的,但某些数据需要持久化:
```yaml
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. 检查容器隔离
```bash
# 查看运行中的容器
docker ps
# 查看容器网络
docker network inspect ai-learning-network
# 查看容器进程(在宿主机上)
ps aux | grep nginx # 看不到容器内的进程
# 进入容器查看
docker exec -it ai-learning-nginx sh
# 在容器内:无法访问宿主机其他文件(除了挂载的 volume
```
### 2. 检查网络隔离
```bash
# 在宿主机上无法直接访问容器内部网络
curl http://backend:3001 # ❌ 失败backend 只在 Docker 网络内可访问
# 在容器内可以访问
docker exec -it ai-learning-nginx sh
curl http://backend:3001 # ✅ 成功,在同一 Docker 网络内
```
### 3. 检查文件系统隔离
```bash
# 容器内的文件系统是独立的
docker exec -it ai-learning-backend ls /app
# 只能看到容器内的文件,看不到宿主机其他目录(除了挂载的 volume
```
## 安全建议
虽然已经实现了完全隔离,但还可以进一步加强:
### 1. 使用非 root 用户运行容器
```dockerfile
# 在 Dockerfile 中
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
USER nodejs
```
### 2. 限制资源使用
```yaml
services:
backend:
deploy:
resources:
limits:
cpus: '1'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
```
### 3. 只读文件系统(除了必要目录)
```yaml
services:
nginx:
read_only: true
tmpfs:
- /tmp
- /var/cache/nginx
```
### 4. 网络策略
```yaml
services:
backend:
networks:
- ai-learning-network
# 不暴露端口到宿主机,只允许 nginx 访问
# ports: [] # 注释掉端口映射
```
## 总结
**是的,当前架构实现了完全隔离**
1.**构建阶段**: 在 Docker 容器中构建,与 Jenkins 服务器隔离
2.**运行阶段**: 应用在 Docker 容器中运行,与宿主机隔离
3.**网络隔离**: 容器在独立的 Docker 网络中
4.**文件系统隔离**: 容器只能访问挂载的 volume
5.**进程隔离**: 容器进程与宿主机进程隔离
**唯一与宿主机共享的**:
- 数据文件(数据库、日志)- 通过 volume 挂载
- 端口映射8080, 3001- 用于外部访问
这种架构提供了**最大的安全性和可移植性**,同时保持了必要的数据持久化。