# 部署/开发运行说明（Docker Compose）

本项目已拆分为两套 Compose 文件：

- **开发环境**：`docker-compose.dev.yml`（源码挂载到容器，适合本地开发调试）
- **正式发布**：`docker-compose.prod.yml`（运行预构建镜像，不挂载源码，适合可分发部署）

> 旧的 `docker-compose.yml` 可视为历史文件；建议后续统一使用 dev/prod 两份文件。

---

## 开发环境如何启动（dev）

### 1）启动

在项目根目录执行：

```bash
docker compose -f docker-compose.dev.yml up -d --build
```

开发环境默认暴露端口：

- Web：`http://localhost:8100`
- Postgres：`localhost:5432`
- PgAdmin：`http://localhost:5050`
- RabbitMQ 管理台：`http://localhost:15672`

### 2）初始化数据库（首次）

```bash
docker compose -f docker-compose.dev.yml exec web uv run python manage.py migrate
docker compose -f docker-compose.dev.yml exec web uv run python manage.py createsuperuser
```

### 3）查看日志 / 重启

```bash
docker compose -f docker-compose.dev.yml logs -f web
docker compose -f docker-compose.dev.yml logs -f celery_worker
docker compose -f docker-compose.dev.yml logs -f celery_beat

docker compose -f docker-compose.dev.yml restart web
```

### 4）停止 / 清理

```bash
docker compose -f docker-compose.dev.yml down

# 连同数据卷一起删除（会清空数据库等）
docker compose -f docker-compose.dev.yml down -v
```

---

## 正式发布如何部署（prod，镜像分发）

### 1）构建发布镜像（构建机）

Dockerfile 已新增 `runtime` stage 且作为默认最终产物，因此直接构建即可：

```bash
docker build -t flower-app:20251220 .
```

> `docker-compose.prod.yml` 会通过 `FLOWER_IMAGE` 使用这个镜像标签。

### 2）导出镜像（用于分发）

```bash
docker save -o flower-app_20251220.tar flower-app:20251220
```

（可选）压缩：

```bash
gzip -9 flower-app_20251220.tar
```

### 3）服务器导入镜像

```bash
docker load -i flower-app_20251220.tar
# 或者 gzip 版本：gunzip -c xxx.tar.gz | docker load
```

### 4）准备备份目录（推荐）

生产环境的数据库备份目录建议使用宿主机可见路径，例如：

```bash
mkdir -p /srv/flower/data-bak
```

### 5）启动生产环境（不使用 .env 文件）

`docker-compose.prod.yml` **不再使用 `env_file: .env`**。你可以用系统环境变量（或 systemd 注入）提供关键配置。

最小示例（请替换为真实值）：

```bash
export FLOWER_IMAGE=flower-app:20251220
export SECRET_KEY='请换成强随机值'
export ALLOWED_HOSTS='yuwenerp.yuwen.cloud'
export CSRF_TRUSTED_ORIGINS='https://yuwenerp.yuwen.cloud'
export DEBUG=0

# 备份目录（不设则默认 ./data-bak，相对 compose 文件所在目录）
export BACKUP_DIR=/srv/flower/data-bak

docker compose -f docker-compose.prod.yml up -d
```

说明：

- `web`/`celery_worker`/`celery_beat` **共用同一个镜像**，通过不同 `command` 启动（只需打包/分发一次）。
- 生产环境默认 `uvicorn` **workers=1**（与当前 SSE 实现兼容；若未来 SSE 改为 Redis/Channels 再考虑增大）。
- 数据库在生产 compose 中默认只绑定到 `127.0.0.1:5432`，避免对公网暴露。

### 6）验证运行

```bash
docker compose -f docker-compose.prod.yml ps
docker compose -f docker-compose.prod.yml logs -f web
```

---

## data-bak（备份目录）当前是如何处理的？

- **开发环境（dev）**：因为 `.:/app` 源码挂载，容器内 `/app/data-bak` 会直接对应宿主机项目目录的 `./data-bak`，你在宿主机上能直接看到备份文件。
- **生产环境（prod）**：`celery_worker` 将 `/app/data-bak` bind mount 到宿主机路径：
  - 默认：`./data-bak`（相对 `docker-compose.prod.yml` 所在目录）
  - 或者通过 `BACKUP_DIR=/srv/flower/data-bak` 指定绝对路径

---

## Dockerfile 现在该如何理解？

当前 `Dockerfile` 主要有三个阶段：

- `base`：安装依赖并 `COPY . /app`（开发 compose 使用 `target: base`）
- `celery`：保留作示例（目前不强依赖，prod compose 直接用同一镜像 + command 覆盖）
- `runtime`：作为默认最终产物，默认 `CMD` 为 `uvicorn ...`（prod 直接用该镜像）

并且已经添加 `.dockerignore`，确保 `.env`、`data-bak/` 等不会被打进发布镜像。

