docker
This commit is contained in:
parent
95047b353b
commit
02e68341f7
10
backend/.dockerignore
Normal file
10
backend/.dockerignore
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
__pycache__
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
.env
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
venv
|
||||||
|
.venv
|
||||||
|
*.db
|
||||||
|
data/
|
||||||
19
backend/.env.production
Normal file
19
backend/.env.production
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Tushare 数据源
|
||||||
|
ASTOCK_TUSHARE_TOKEN=your_tushare_token_here
|
||||||
|
|
||||||
|
# 调试模式(生产环境设为 false)
|
||||||
|
ASTOCK_DEBUG=false
|
||||||
|
|
||||||
|
# DeepSeek LLM(不使用 AI 对话可留空)
|
||||||
|
ASTOCK_DEEPSEEK_API_KEY=
|
||||||
|
|
||||||
|
# JWT 安全配置(生产环境务必修改!)
|
||||||
|
ASTOCK_JWT_SECRET=替换为一个随机长字符串
|
||||||
|
ASTOCK_JWT_EXPIRY_HOURS=24
|
||||||
|
|
||||||
|
# 默认管理员账号(首次启动自动创建)
|
||||||
|
ASTOCK_ADMIN_USERNAME=admin
|
||||||
|
ASTOCK_ADMIN_PASSWORD=替换为一个安全密码
|
||||||
|
|
||||||
|
# 前端地址(用于 CORS)
|
||||||
|
ASTOCK_FRONTEND_URL=http://your-server-ip:3000
|
||||||
15
backend/Dockerfile
Normal file
15
backend/Dockerfile
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
FROM python:3.13-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# 数据库文件存放在 /app/data 目录,通过 volume 持久化
|
||||||
|
RUN mkdir -p /app/data
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
@ -1,26 +1,29 @@
|
|||||||
version: "3.8"
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
backend:
|
backend:
|
||||||
build: ./backend
|
build: ./backend
|
||||||
ports:
|
restart: unless-stopped
|
||||||
- "8000:8000"
|
|
||||||
env_file:
|
env_file:
|
||||||
- ./backend/.env
|
- ./backend/.env
|
||||||
|
environment:
|
||||||
|
- ASTOCK_DATABASE_URL=sqlite:///./data/astock.db
|
||||||
volumes:
|
volumes:
|
||||||
- ./backend:/app
|
|
||||||
- db_data:/app/data
|
- db_data:/app/data
|
||||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
expose:
|
||||||
|
- "8000"
|
||||||
|
# 生产环境不需要映射端口,前端容器通过 Docker 网络内部访问
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
build: ./frontend
|
build:
|
||||||
|
context: ./frontend
|
||||||
|
args:
|
||||||
|
- BACKEND_URL=http://backend:8000
|
||||||
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
depends_on:
|
depends_on:
|
||||||
- backend
|
- backend
|
||||||
environment:
|
environment:
|
||||||
- NEXT_PUBLIC_API_URL=http://backend:8000
|
- BACKEND_URL=http://backend:8000
|
||||||
command: npm run dev
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
db_data:
|
db_data:
|
||||||
|
|||||||
4
frontend/.dockerignore
Normal file
4
frontend/.dockerignore
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
node_modules
|
||||||
|
.next
|
||||||
|
.git
|
||||||
|
.env*
|
||||||
@ -16,13 +16,6 @@
|
|||||||
"static/chunks/448-92a7b932cf4502ac.js",
|
"static/chunks/448-92a7b932cf4502ac.js",
|
||||||
"static/chunks/app/layout-97bdd231e78ddf3f.js"
|
"static/chunks/app/layout-97bdd231e78ddf3f.js"
|
||||||
],
|
],
|
||||||
"/login/page": [
|
|
||||||
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
|
||||||
"static/chunks/fd9d1056-f8a2d551cbb94c85.js",
|
|
||||||
"static/chunks/117-d0aa9486d6cf1a7a.js",
|
|
||||||
"static/chunks/main-app-7d7e5d1021afd90c.js",
|
|
||||||
"static/chunks/app/login/page-778febf452923618.js"
|
|
||||||
],
|
|
||||||
"/page": [
|
"/page": [
|
||||||
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
||||||
"static/chunks/fd9d1056-f8a2d551cbb94c85.js",
|
"static/chunks/fd9d1056-f8a2d551cbb94c85.js",
|
||||||
@ -30,12 +23,19 @@
|
|||||||
"static/chunks/main-app-7d7e5d1021afd90c.js",
|
"static/chunks/main-app-7d7e5d1021afd90c.js",
|
||||||
"static/chunks/app/page-5a303311159f23ad.js"
|
"static/chunks/app/page-5a303311159f23ad.js"
|
||||||
],
|
],
|
||||||
"/recommendations/page": [
|
"/login/page": [
|
||||||
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
||||||
"static/chunks/fd9d1056-f8a2d551cbb94c85.js",
|
"static/chunks/fd9d1056-f8a2d551cbb94c85.js",
|
||||||
"static/chunks/117-d0aa9486d6cf1a7a.js",
|
"static/chunks/117-d0aa9486d6cf1a7a.js",
|
||||||
"static/chunks/main-app-7d7e5d1021afd90c.js",
|
"static/chunks/main-app-7d7e5d1021afd90c.js",
|
||||||
"static/chunks/app/recommendations/page-ef6715bbb27168f0.js"
|
"static/chunks/app/login/page-778febf452923618.js"
|
||||||
|
],
|
||||||
|
"/chat/page": [
|
||||||
|
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
||||||
|
"static/chunks/fd9d1056-f8a2d551cbb94c85.js",
|
||||||
|
"static/chunks/117-d0aa9486d6cf1a7a.js",
|
||||||
|
"static/chunks/main-app-7d7e5d1021afd90c.js",
|
||||||
|
"static/chunks/app/chat/page-2dd3304322bd4036.js"
|
||||||
],
|
],
|
||||||
"/sectors/page": [
|
"/sectors/page": [
|
||||||
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
||||||
@ -44,12 +44,12 @@
|
|||||||
"static/chunks/main-app-7d7e5d1021afd90c.js",
|
"static/chunks/main-app-7d7e5d1021afd90c.js",
|
||||||
"static/chunks/app/sectors/page-2f0e16a2b83354cf.js"
|
"static/chunks/app/sectors/page-2f0e16a2b83354cf.js"
|
||||||
],
|
],
|
||||||
"/chat/page": [
|
"/recommendations/page": [
|
||||||
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
||||||
"static/chunks/fd9d1056-f8a2d551cbb94c85.js",
|
"static/chunks/fd9d1056-f8a2d551cbb94c85.js",
|
||||||
"static/chunks/117-d0aa9486d6cf1a7a.js",
|
"static/chunks/117-d0aa9486d6cf1a7a.js",
|
||||||
"static/chunks/main-app-7d7e5d1021afd90c.js",
|
"static/chunks/main-app-7d7e5d1021afd90c.js",
|
||||||
"static/chunks/app/chat/page-2dd3304322bd4036.js"
|
"static/chunks/app/recommendations/page-ef6715bbb27168f0.js"
|
||||||
],
|
],
|
||||||
"/stock/[code]/page": [
|
"/stock/[code]/page": [
|
||||||
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
"devFiles": [],
|
"devFiles": [],
|
||||||
"ampDevFiles": [],
|
"ampDevFiles": [],
|
||||||
"lowPriorityFiles": [
|
"lowPriorityFiles": [
|
||||||
"static/77YFCNa-r_QnYgqwH2vOe/_buildManifest.js",
|
"static/zyMEF2O04rWB2PcTlD48N/_buildManifest.js",
|
||||||
"static/77YFCNa-r_QnYgqwH2vOe/_ssgManifest.js"
|
"static/zyMEF2O04rWB2PcTlD48N/_ssgManifest.js"
|
||||||
],
|
],
|
||||||
"rootMainFiles": [
|
"rootMainFiles": [
|
||||||
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"/_not-found/page": "app/_not-found/page.js",
|
"/_not-found/page": "app/_not-found/page.js",
|
||||||
"/login/page": "app/login/page.js",
|
|
||||||
"/api/chat/stream/route": "app/api/chat/stream/route.js",
|
"/api/chat/stream/route": "app/api/chat/stream/route.js",
|
||||||
"/page": "app/page.js",
|
"/page": "app/page.js",
|
||||||
"/recommendations/page": "app/recommendations/page.js",
|
"/login/page": "app/login/page.js",
|
||||||
"/sectors/page": "app/sectors/page.js",
|
|
||||||
"/chat/page": "app/chat/page.js",
|
"/chat/page": "app/chat/page.js",
|
||||||
|
"/sectors/page": "app/sectors/page.js",
|
||||||
|
"/recommendations/page": "app/recommendations/page.js",
|
||||||
"/stock/[code]/page": "app/stock/[code]/page.js",
|
"/stock/[code]/page": "app/stock/[code]/page.js",
|
||||||
"/users/page": "app/users/page.js"
|
"/users/page": "app/users/page.js"
|
||||||
}
|
}
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
{"node":{},"edge":{},"encryptionKey":"mEKzCdLXC9Tw5xpwGdIONxBrCnit3XJOsa5Cm7fALlw="}
|
{"node":{},"edge":{},"encryptionKey":"f3swqWaUk34ppPaPfJEtsu7hIqrZ76kvi8fuvlEN4Xc="}
|
||||||
File diff suppressed because one or more lines are too long
32
frontend/Dockerfile
Normal file
32
frontend/Dockerfile
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
FROM node:20-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json package-lock.json* ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# 构建时注入后端地址(运行时通过 rewrites 代理,这里设为内部地址)
|
||||||
|
ARG BACKEND_URL=http://backend:8000
|
||||||
|
ENV BACKEND_URL=${BACKEND_URL}
|
||||||
|
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# ---- Production image ----
|
||||||
|
FROM node:20-alpine AS runner
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
|
COPY --from=builder /app/.next/standalone ./
|
||||||
|
COPY --from=builder /app/.next/static ./.next/static
|
||||||
|
COPY --from=builder /app/public ./public
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
ENV PORT=3000
|
||||||
|
ENV HOSTNAME="0.0.0.0"
|
||||||
|
|
||||||
|
CMD ["node", "server.js"]
|
||||||
@ -1,14 +1,17 @@
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
|
const backendUrl = process.env.BACKEND_URL || "http://localhost:8000";
|
||||||
|
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
|
output: "standalone",
|
||||||
async rewrites() {
|
async rewrites() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
source: "/api/:path*",
|
source: "/api/:path*",
|
||||||
destination: "http://localhost:8000/api/:path*",
|
destination: `${backendUrl}/api/:path*`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
source: "/ws",
|
source: "/ws",
|
||||||
destination: "http://localhost:8000/ws",
|
destination: `${backendUrl}/ws`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user