Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.git
.gitignore
.gitattributes

*.pyc
.DS_Store
Thumbs.db
.idea/
.vscode/
__pycache__/
.venv/
env/
venv/
.uv-cache
.env
.env.*

node_modules/
WareHouse/
data/
temp/
logs

/frontend
README*
compose.yml
Dockerfile
10 changes: 10 additions & 0 deletions .env.docker
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
BACKEND_BIND=0.0.0.0

FRONTEND_HOST=0.0.0.0
FRONTEND_PORT=5173

# Frontend points to the backend service name and exposed port
VITE_API_BASE_URL=http://backend:6400

# Explicit CORS origins for Docker-based dev (comma-separated)
CORS_ALLOW_ORIGINS=http://localhost:5173,http://127.0.0.1:5173
63 changes: 63 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# ---- Builder: install deps with compilers and uv ----
FROM python:3.12-slim AS builder
ARG DEBIAN_FRONTEND=noninteractive

WORKDIR /app

# System deps required to build Python packages
RUN apt-get update && apt-get install -y --no-install-recommends \
pkg-config \
build-essential \
python3-dev \
libcairo2-dev \
&& rm -rf /var/lib/apt/lists/*

# Install uv just for dependency resolution/install
RUN pip install --no-cache-dir uv

# Install the project virtualenv outside /app so bind-mounts don't hide it
ENV UV_PROJECT_ENVIRONMENT=/opt/venv

# Copy dependency files first to maximize cache
COPY pyproject.toml ./
# If you have a lock file, uncomment the next line for reproducible builds:
# COPY uv.lock ./

# Create the project virtualenv and install deps
RUN uv sync --no-cache

# ---- Runtime: minimal image with only runtime libs + app ----
FROM python:3.12-slim AS runtime
ARG DEBIAN_FRONTEND=noninteractive
ARG BACKEND_BIND=0.0.0.0

WORKDIR /app

# Install only runtime system libraries (no compilers)
# Keep libcairo if your deps need it; remove if unnecessary
RUN apt-get update && apt-get install -y --no-install-recommends \
libcairo2 \
&& rm -rf /var/lib/apt/lists/*

# Copy the prebuilt virtualenv from the builder
COPY --from=builder /opt/venv /opt/venv

# Copy the rest of the application code
COPY . .

# Use the venv Python by default and keep Python output unbuffered.
# Bake default bind/port into the image; can be overridden at runtime.
ENV PATH="/opt/venv/bin:${PATH}" \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
BACKEND_BIND=${BACKEND_BIND}

# Drop privileges
RUN useradd -m appuser && chown -R appuser:appuser /app
USER appuser

# EXPOSE is informational; compose controls published ports
EXPOSE 6400

# Command to run the backend server, parameterized by env
CMD ["sh", "-c", "python server_main.py --port 6400 --host ${BACKEND_BIND:-0.0.0.0}"]
38 changes: 37 additions & 1 deletion README-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ ChatDev 已从一个专门的软件开发多智能体系统演变为一个全面
cd frontend && npm install
```

### ⚡️ 运行应用
### ⚡️ 运行应用(本地)

1. **启动后端**:
```bash
Expand All @@ -141,6 +141,42 @@ ChatDev 已从一个专门的软件开发多智能体系统演变为一个全面
> * **前端**:设置 `VITE_API_BASE_URL=http://localhost:6401`


### 🐳 使用 Docker 运行
你也可以通过 Docker Compose 运行整个应用。该方式可简化依赖管理,并提供一致的运行环境。

1. **前置条件**:
* 已安装 [Docker](https://docs.docker.com/get-docker/) 和 [Docker Compose](https://docs.docker.com/compose/install/)。
* 请确保在项目根目录中存在用于配置 API Key 的 `.env` 文件。

2. **构建并运行**:
```bash
# 在项目根目录执行
docker compose up --build
```

3. **访问地址**:
* **后端**:`http://localhost:6400`
* **前端**:`http://localhost:5173`

> 服务在异常退出后会自动重启,本地文件的修改会同步映射到容器中,便于实时开发。

#### 生产环境(Docker + nginx)

- 构建并运行:
```bash
docker compose -f compose.yml -f compose.prod.yml up -d --build
```
- 访问:
- 前端:http://localhost:8080
- 后端:不对外暴露,由 nginx 通过 /api 与 /ws 转发
- 停止:
```bash
docker compose -f compose.yml -f compose.prod.yml down
```
- 说明:
- .env 保存密钥(API Keys),.env.docker 保存容器相关配置。
- nginx 将 /api 与 /ws 代理到 backend:6400(见 frontend/nginx.conf)。

### 🔑 配置

* **环境变量**:在项目根目录创建一个 `.env` 文件。
Expand Down
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ See our paper in [Multi-Agent Collaboration via Evolving Orchestration](https://
cd frontend && npm install
```

### ⚡️ Run the Application
### ⚡️ Run the Application (Local)

1. **Start Backend** :
```bash
Expand All @@ -143,6 +143,41 @@ See our paper in [Multi-Agent Collaboration via Evolving Orchestration](https://
> * **Backend**: start with `--port 6401`
> * **Frontend**: set `VITE_API_BASE_URL=http://localhost:6401`

### 🐳 Run with Docker
Alternatively, you can run the entire application using Docker Compose. This method simplifies dependency management and provides a consistent environment.

1. **Prerequisites**:
* [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/) installed.
* Ensure you have a `.env` file in the project root for your API keys.

2. **Build and Run**:
```bash
# From the project root
docker compose up --build
```

3. **Access**:
* **Backend**: `http://localhost:6400`
* **Frontend**: `http://localhost:5173`

> The services will automatically restart if they crash, and local file changes will be reflected inside the containers for live development.

#### Production (Docker + nginx)

- Build and run:
```bash
docker compose -f compose.yml -f compose.prod.yml up -d --build
```
- Access:
- Frontend: http://localhost:8080
- Backend: not published (internal); proxied via /api and /ws by nginx
- Stop:
```bash
docker compose -f compose.yml -f compose.prod.yml down
```
- Notes:
- .env holds secrets (API keys), .env.docker holds container-only config.
- nginx proxies /api and /ws to backend:6400 (see frontend/nginx.conf).

### 🔑 Configuration

Expand Down
44 changes: 44 additions & 0 deletions compose.prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
services:
backend:
build:
context: .
dockerfile: Dockerfile
target: runtime
container_name: chatdev_backend
env_file:
- .env
- .env.docker
expose:
- "6400"
restart: unless-stopped
networks:
- appnet
# Optional healthcheck (adjust path if different)
# healthcheck:
# test: ["CMD-SHELL", "curl -fsS http://localhost:6400/api/health || exit 1"]
# interval: 10s
# timeout: 3s
# retries: 5

frontend:
build:
context: ./frontend
dockerfile: Dockerfile
target: prod
container_name: chatdev_frontend
ports:
- "8080:80"
depends_on:
- backend
restart: unless-stopped
networks:
- appnet
# Optional healthcheck
# healthcheck:
# test: ["CMD-SHELL", "wget -q -O - http://localhost/ >/dev/null 2>&1 || exit 1"]
# interval: 10s
# timeout: 3s
# retries: 5

networks:
appnet: {}
33 changes: 33 additions & 0 deletions compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
services:
backend:
build:
context: .
dockerfile: Dockerfile
target: runtime
container_name: chatdev_backend
volumes:
- .:/app
ports:
- "6400:6400"
env_file:
- .env
- .env.docker
restart: unless-stopped

frontend:
build:
context: ./frontend
dockerfile: Dockerfile
target: dev
container_name: chatdev_frontend
volumes:
- ./frontend:/app
- /app/node_modules
ports:
- "${FRONTEND_PORT:-5173}:5173"
env_file:
- .env
- .env.docker
depends_on:
- backend
restart: unless-stopped
24 changes: 24 additions & 0 deletions frontend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.git
.gitignore
.gitattributes

*.pyc
.DS_Store
Thumbs.db
.idea/
.vscode/
__pycache__/
.venv/
env/
venv/
.uv-cache
.env
.env.*

node_modules/
temp/
logs

README*
compose.yml
Dockerfile
33 changes: 33 additions & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# ---- Dependencies: install node_modules once (cached) ----
FROM node:24-alpine AS deps
WORKDIR /app
COPY package*.json ./
# Prefer reproducible installs; fall back if no lockfile
RUN npm ci --no-audit --no-fund || npm install --no-audit --no-fund

# ---- Dev runtime: hot-reload server ----
FROM node:24-alpine AS dev
WORKDIR /app
ENV NODE_ENV=development
COPY --from=deps /app/node_modules /app/node_modules
COPY . .
EXPOSE 5173
CMD ["npm", "run", "dev", "--", "--host"]

# ---- Build: create production assets ----
FROM node:24-alpine AS build
WORKDIR /app
ENV NODE_ENV=production
ARG VITE_API_BASE_URL=http://backend:6400
ENV VITE_API_BASE_URL=""
COPY --from=deps /app/node_modules /app/node_modules
COPY . .
RUN npm run build

# ---- Prod runtime: serve static dist with nginx ----
FROM nginx:alpine AS prod
# For SPA deep links you might add a custom nginx.conf with index.html fallback.
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
32 changes: 32 additions & 0 deletions frontend/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
server {
listen 80;
server_name _;

# Serve built assets
root /usr/share/nginx/html;
index index.html;

# Proxy API
location /api/ {
proxy_pass http://backend:6400/api/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

# Proxy WebSocket
location /ws {
proxy_pass http://backend:6400/ws;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}

# SPA fallback
location / {
try_files $uri $uri/ /index.html;
}
}
Loading