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:
|
||||
backend:
|
||||
build: ./backend
|
||||
ports:
|
||||
- "8000:8000"
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- ./backend/.env
|
||||
environment:
|
||||
- ASTOCK_DATABASE_URL=sqlite:///./data/astock.db
|
||||
volumes:
|
||||
- ./backend:/app
|
||||
- db_data:/app/data
|
||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
||||
expose:
|
||||
- "8000"
|
||||
# 生产环境不需要映射端口,前端容器通过 Docker 网络内部访问
|
||||
|
||||
frontend:
|
||||
build: ./frontend
|
||||
build:
|
||||
context: ./frontend
|
||||
args:
|
||||
- BACKEND_URL=http://backend:8000
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "3000:3000"
|
||||
depends_on:
|
||||
- backend
|
||||
environment:
|
||||
- NEXT_PUBLIC_API_URL=http://backend:8000
|
||||
command: npm run dev
|
||||
- BACKEND_URL=http://backend:8000
|
||||
|
||||
volumes:
|
||||
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/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": [
|
||||
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
||||
"static/chunks/fd9d1056-f8a2d551cbb94c85.js",
|
||||
@ -30,12 +23,19 @@
|
||||
"static/chunks/main-app-7d7e5d1021afd90c.js",
|
||||
"static/chunks/app/page-5a303311159f23ad.js"
|
||||
],
|
||||
"/recommendations/page": [
|
||||
"/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/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": [
|
||||
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
||||
@ -44,12 +44,12 @@
|
||||
"static/chunks/main-app-7d7e5d1021afd90c.js",
|
||||
"static/chunks/app/sectors/page-2f0e16a2b83354cf.js"
|
||||
],
|
||||
"/chat/page": [
|
||||
"/recommendations/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"
|
||||
"static/chunks/app/recommendations/page-ef6715bbb27168f0.js"
|
||||
],
|
||||
"/stock/[code]/page": [
|
||||
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
"devFiles": [],
|
||||
"ampDevFiles": [],
|
||||
"lowPriorityFiles": [
|
||||
"static/77YFCNa-r_QnYgqwH2vOe/_buildManifest.js",
|
||||
"static/77YFCNa-r_QnYgqwH2vOe/_ssgManifest.js"
|
||||
"static/zyMEF2O04rWB2PcTlD48N/_buildManifest.js",
|
||||
"static/zyMEF2O04rWB2PcTlD48N/_ssgManifest.js"
|
||||
],
|
||||
"rootMainFiles": [
|
||||
"static/chunks/webpack-76aa9cbbdedb6a49.js",
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
{
|
||||
"/_not-found/page": "app/_not-found/page.js",
|
||||
"/login/page": "app/login/page.js",
|
||||
"/api/chat/stream/route": "app/api/chat/stream/route.js",
|
||||
"/page": "app/page.js",
|
||||
"/recommendations/page": "app/recommendations/page.js",
|
||||
"/sectors/page": "app/sectors/page.js",
|
||||
"/login/page": "app/login/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",
|
||||
"/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} */
|
||||
const backendUrl = process.env.BACKEND_URL || "http://localhost:8000";
|
||||
|
||||
const nextConfig = {
|
||||
output: "standalone",
|
||||
async rewrites() {
|
||||
return [
|
||||
{
|
||||
source: "/api/:path*",
|
||||
destination: "http://localhost:8000/api/:path*",
|
||||
destination: `${backendUrl}/api/:path*`,
|
||||
},
|
||||
{
|
||||
source: "/ws",
|
||||
destination: "http://localhost:8000/ws",
|
||||
destination: `${backendUrl}/ws`,
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user