296 lines
11 KiB
Markdown
296 lines
11 KiB
Markdown
|
|
# 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)- 用于外部访问
|
|||
|
|
|
|||
|
|
这种架构提供了**最大的安全性和可移植性**,同时保持了必要的数据持久化。
|