forked from erp-dev/erp
feat: split the docker compose config file
This commit is contained in:
23
.dockerignore
Normal file
23
.dockerignore
Normal file
@@ -0,0 +1,23 @@
|
||||
.git
|
||||
.idea
|
||||
.vscode
|
||||
.cursor
|
||||
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*.pyd
|
||||
.pytest_cache
|
||||
.mypy_cache
|
||||
.ruff_cache
|
||||
.coverage
|
||||
htmlcov/
|
||||
|
||||
# 本地环境变量(不要打进发布镜像)
|
||||
.env
|
||||
|
||||
# 本地备份文件(体积大且可能包含敏感数据)
|
||||
data-bak/
|
||||
*.sql
|
||||
|
||||
# Celery Beat 本地持久化调度文件(不要进镜像,也不要污染构建上下文)
|
||||
celerybeat-schedule*
|
||||
@@ -20,10 +20,16 @@ RUN pip install --upgrade pip \
|
||||
|
||||
COPY . /app
|
||||
|
||||
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
|
||||
CMD ["python", "manage.py", "runserver", "0.0.0.0:8100"]
|
||||
|
||||
|
||||
FROM base AS celery
|
||||
|
||||
CMD ["celery", "-A", "flower", "worker", "-l", "info", "--concurrency=2"]
|
||||
|
||||
|
||||
# 默认产物:runtime 镜像(用于 web / celery_worker / celery_beat 共用,通过 compose 覆盖 command)
|
||||
FROM base AS runtime
|
||||
|
||||
CMD ["uvicorn", "flower.asgi:application", "--host", "0.0.0.0", "--port", "8000", "--workers", "1"]
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
150
docker-compose.dev.yml
Normal file
150
docker-compose.dev.yml
Normal file
@@ -0,0 +1,150 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: postgres
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: flower
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- db_data:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
|
||||
pgadmin:
|
||||
image: dpage/pgadmin4:latest
|
||||
container_name: pgadmin
|
||||
environment:
|
||||
PGADMIN_DEFAULT_EMAIL: admin@admin.com
|
||||
PGADMIN_DEFAULT_PASSWORD: admin
|
||||
PGADMIN_CONFIG_SERVER_MODE: "False"
|
||||
ports:
|
||||
- "5050:80"
|
||||
volumes:
|
||||
- pgadmin_data:/var/lib/pgadmin
|
||||
depends_on:
|
||||
- postgres
|
||||
restart: unless-stopped
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: redis
|
||||
ports:
|
||||
- "6379:6379"
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
restart: unless-stopped
|
||||
|
||||
rabbitmq:
|
||||
image: rabbitmq:3-management-alpine
|
||||
container_name: rabbitmq
|
||||
environment:
|
||||
RABBITMQ_DEFAULT_USER: guest
|
||||
RABBITMQ_DEFAULT_PASS: guest
|
||||
ports:
|
||||
- "5672:5672"
|
||||
- "15672:15672"
|
||||
volumes:
|
||||
- rabbitmq_data:/var/lib/rabbitmq
|
||||
restart: unless-stopped
|
||||
|
||||
web:
|
||||
build:
|
||||
context: .
|
||||
target: base
|
||||
container_name: flower_web
|
||||
command: python manage.py runserver 0.0.0.0:8100
|
||||
ports:
|
||||
- "8100:8100"
|
||||
volumes:
|
||||
- .:/app
|
||||
environment:
|
||||
DJANGO_SETTINGS_MODULE: flower.settings
|
||||
PYTHONPATH: /app
|
||||
DEBUG: "1"
|
||||
ALLOWED_HOSTS: "localhost,127.0.0.1,0.0.0.0,8.148.215.233,yuwenerp.yuwen.cloud"
|
||||
DB_HOST: postgres
|
||||
DB_PORT: "5432"
|
||||
DB_NAME: flower
|
||||
DB_USER: postgres
|
||||
DB_PASSWORD: postgres
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
- rabbitmq
|
||||
restart: unless-stopped
|
||||
|
||||
celery_worker:
|
||||
build:
|
||||
context: .
|
||||
target: base
|
||||
container_name: celery_worker
|
||||
command:
|
||||
- celery
|
||||
- -A
|
||||
- flower
|
||||
- worker
|
||||
- -l
|
||||
- info
|
||||
- --concurrency=2
|
||||
- --pool=solo
|
||||
volumes:
|
||||
- .:/app
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
- rabbitmq
|
||||
environment:
|
||||
CELERY_BROKER_URL: amqp://guest:guest@rabbitmq:5672//
|
||||
CELERY_RESULT_BACKEND: redis://redis:6379/0
|
||||
PYTHONPATH: /app
|
||||
DB_HOST: postgres
|
||||
DB_PORT: "5432"
|
||||
DB_NAME: flower
|
||||
DB_USER: postgres
|
||||
DB_PASSWORD: postgres
|
||||
restart: unless-stopped
|
||||
|
||||
celery_beat:
|
||||
build:
|
||||
context: .
|
||||
target: base
|
||||
container_name: celery_beat
|
||||
command:
|
||||
- celery
|
||||
- -A
|
||||
- flower
|
||||
- beat
|
||||
- -l
|
||||
- info
|
||||
- --schedule
|
||||
- /var/lib/celery/celerybeat-schedule
|
||||
volumes:
|
||||
- .:/app
|
||||
- celery_beat_data:/var/lib/celery
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
- rabbitmq
|
||||
environment:
|
||||
DJANGO_SETTINGS_MODULE: flower.settings
|
||||
PYTHONPATH: /app
|
||||
DB_HOST: postgres
|
||||
DB_PORT: "5432"
|
||||
DB_NAME: flower
|
||||
DB_USER: postgres
|
||||
DB_PASSWORD: postgres
|
||||
CELERY_BROKER_URL: amqp://guest:guest@rabbitmq:5672//
|
||||
CELERY_RESULT_BACKEND: redis://redis:6379/0
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
db_data:
|
||||
redis_data:
|
||||
pgadmin_data:
|
||||
rabbitmq_data:
|
||||
celery_beat_data:
|
||||
|
||||
135
docker-compose.prod.yml
Normal file
135
docker-compose.prod.yml
Normal file
@@ -0,0 +1,135 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: postgres
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-postgres}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-flower}
|
||||
# 仅绑定到本机,避免把数据库暴露到公网
|
||||
ports:
|
||||
- "127.0.0.1:${POSTGRES_PORT:-5432}:5432"
|
||||
volumes:
|
||||
- db_data:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: redis
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
restart: unless-stopped
|
||||
|
||||
rabbitmq:
|
||||
image: rabbitmq:3-management-alpine
|
||||
container_name: rabbitmq
|
||||
environment:
|
||||
RABBITMQ_DEFAULT_USER: ${RABBITMQ_DEFAULT_USER:-guest}
|
||||
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_DEFAULT_PASS:-guest}
|
||||
volumes:
|
||||
- rabbitmq_data:/var/lib/rabbitmq
|
||||
restart: unless-stopped
|
||||
|
||||
web:
|
||||
image: ${FLOWER_IMAGE:-flower-app:latest}
|
||||
container_name: flower_web
|
||||
command:
|
||||
- uvicorn
|
||||
- flower.asgi:application
|
||||
- --host
|
||||
- 0.0.0.0
|
||||
- --port
|
||||
- "8000"
|
||||
- --workers
|
||||
- "${UVICORN_WORKERS:-1}"
|
||||
ports:
|
||||
- "${WEB_PORT:-8000}:8000"
|
||||
environment:
|
||||
DJANGO_SETTINGS_MODULE: flower.settings
|
||||
PYTHONPATH: /app
|
||||
DEBUG: "${DEBUG:-0}"
|
||||
ALLOWED_HOSTS: "${ALLOWED_HOSTS:-yuwenerp.yuwen.cloud}"
|
||||
DB_HOST: ${DB_HOST:-postgres}
|
||||
DB_PORT: "${DB_PORT:-5432}"
|
||||
DB_NAME: "${DB_NAME:-flower}"
|
||||
DB_USER: "${DB_USER:-postgres}"
|
||||
DB_PASSWORD: "${DB_PASSWORD:-postgres}"
|
||||
CELERY_BROKER_URL: "${CELERY_BROKER_URL:-amqp://guest:guest@rabbitmq:5672//}"
|
||||
CELERY_RESULT_BACKEND: "${CELERY_RESULT_BACKEND:-redis://redis:6379/0}"
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
- rabbitmq
|
||||
restart: unless-stopped
|
||||
|
||||
celery_worker:
|
||||
image: ${FLOWER_IMAGE:-flower-app:latest}
|
||||
container_name: celery_worker
|
||||
command:
|
||||
- celery
|
||||
- -A
|
||||
- flower
|
||||
- worker
|
||||
- -l
|
||||
- info
|
||||
- --concurrency=${CELERY_CONCURRENCY:-2}
|
||||
- --pool=solo
|
||||
environment:
|
||||
PYTHONPATH: /app
|
||||
DB_HOST: ${DB_HOST:-postgres}
|
||||
DB_PORT: "${DB_PORT:-5432}"
|
||||
DB_NAME: "${DB_NAME:-flower}"
|
||||
DB_USER: "${DB_USER:-postgres}"
|
||||
DB_PASSWORD: "${DB_PASSWORD:-postgres}"
|
||||
CELERY_BROKER_URL: "${CELERY_BROKER_URL:-amqp://guest:guest@rabbitmq:5672//}"
|
||||
CELERY_RESULT_BACKEND: "${CELERY_RESULT_BACKEND:-redis://redis:6379/0}"
|
||||
# 数据库备份输出目录(api_v1.tasks.backup_database 默认输出到 BASE_DIR/data-bak)
|
||||
volumes:
|
||||
# 默认落在 compose 同级目录的 ./data-bak,方便宿主机直接查看/拷贝
|
||||
# 也可通过 BACKUP_DIR 指定绝对路径,如 /srv/flower/data-bak
|
||||
- ${BACKUP_DIR:-./data-bak}:/app/data-bak
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
- rabbitmq
|
||||
restart: unless-stopped
|
||||
|
||||
celery_beat:
|
||||
image: ${FLOWER_IMAGE:-flower-app:latest}
|
||||
container_name: celery_beat
|
||||
command:
|
||||
- celery
|
||||
- -A
|
||||
- flower
|
||||
- beat
|
||||
- -l
|
||||
- info
|
||||
- --schedule
|
||||
- /var/lib/celery/celerybeat-schedule
|
||||
environment:
|
||||
DJANGO_SETTINGS_MODULE: flower.settings
|
||||
PYTHONPATH: /app
|
||||
DB_HOST: ${DB_HOST:-postgres}
|
||||
DB_PORT: "${DB_PORT:-5432}"
|
||||
DB_NAME: "${DB_NAME:-flower}"
|
||||
DB_USER: "${DB_USER:-postgres}"
|
||||
DB_PASSWORD: "${DB_PASSWORD:-postgres}"
|
||||
CELERY_BROKER_URL: "${CELERY_BROKER_URL:-amqp://guest:guest@rabbitmq:5672//}"
|
||||
CELERY_RESULT_BACKEND: "${CELERY_RESULT_BACKEND:-redis://redis:6379/0}"
|
||||
# Celery Beat 的持久化调度文件,避免重启后重复/错过调度
|
||||
volumes:
|
||||
- celery_beat_data:/var/lib/celery
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
- rabbitmq
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
db_data:
|
||||
redis_data:
|
||||
rabbitmq_data:
|
||||
celery_beat_data:
|
||||
|
||||
148
docs/DEPLOY_DOCKER_COMPOSE.md
Normal file
148
docs/DEPLOY_DOCKER_COMPOSE.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# 部署/开发运行说明(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/` 等不会被打进发布镜像。
|
||||
|
||||
@@ -195,6 +195,8 @@ DATABASES = {
|
||||
'PASSWORD': env('DB_PASSWORD'),
|
||||
'HOST': env('DB_HOST', default='localhost'),
|
||||
'PORT': env('DB_PORT', default='5432'),
|
||||
'CONN_HEALTH_CHECK': True,
|
||||
'CONN_MAX_AGE': 60,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user