优化 Docker 部署和修复 Markdown 渲染

- 修复 AI 讨论框 Markdown 粗体渲染问题
- 增加数据库连接池到 50 最大并发连接
- 移除 Google Fonts 依赖,使用系统默认字体
- 添加 Docker DNS 配置支持多服务器访问
- 优化 Dockerfile 构建流程,直接复制 node_modules
- 添加 mTLS 证书文件
This commit is contained in:
xucheng 2026-01-14 22:12:14 +08:00
parent 89644fbf97
commit f2697149f7
6 changed files with 22 additions and 8 deletions

View File

@ -51,9 +51,8 @@ COPY frontend/package*.json ./frontend/
# Copy the built .next folder and public assets # Copy the built .next folder and public assets
COPY --from=frontend-builder /app/frontend/.next ./frontend/.next COPY --from=frontend-builder /app/frontend/.next ./frontend/.next
COPY --from=frontend-builder /app/frontend/public ./frontend/public COPY --from=frontend-builder /app/frontend/public ./frontend/public
# Install ONLY production dependencies for frontend # 复制 node_modules 而不是重新安装(避免网络超时问题)
WORKDIR /app/frontend COPY --from=frontend-builder /app/frontend/node_modules ./frontend/node_modules/
RUN npm ci --only=production
# 5. Copy Backend & Application Code # 5. Copy Backend & Application Code
WORKDIR /app WORKDIR /app

View File

@ -16,7 +16,11 @@ DATABASE_URL = f"postgresql+asyncpg://{os.getenv('DB_USER')}:{os.getenv('DB_PASS
engine = create_async_engine( engine = create_async_engine(
DATABASE_URL, DATABASE_URL,
echo=False, # 设置为 True 可以看到 SQL 日志 echo=False, # 设置为 True 可以看到 SQL 日志
future=True future=True,
pool_size=20, # 核心连接池大小
max_overflow=30, # 溢出连接池大小
pool_timeout=30, # 获取连接的超时时间(秒)
pool_recycle=3600 # 连接回收时间1小时防止长时间闲置连接被数据库关闭
) )
# 创建异步 Session 工厂 # 创建异步 Session 工厂

0
bastian/ca.crt Normal file
View File

View File

@ -39,6 +39,9 @@ docker rm -f $CONTAINER_NAME 2>/dev/null || true
echo "启动新容器..." echo "启动新容器..."
docker run -d \ docker run -d \
--name $CONTAINER_NAME \ --name $CONTAINER_NAME \
--dns 8.8.8.8 \
--dns 8.8.4.4 \
--dns 114.114.114.114 \
-e PW_SERVICE_ID="$PW_SERVICE_ID" \ -e PW_SERVICE_ID="$PW_SERVICE_ID" \
-e PW_SERVER_ADDRS="$PW_SERVER_ADDRS" \ -e PW_SERVER_ADDRS="$PW_SERVER_ADDRS" \
-e PW_LOCAL_PORT="$PW_LOCAL_PORT" \ -e PW_LOCAL_PORT="$PW_LOCAL_PORT" \

View File

@ -1,10 +1,7 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import { Inter } from "next/font/google"; // Using Inter for now as safe default or stick to Geist
import "./globals.css"; import "./globals.css";
import { NavHeader } from "@/components/nav-header"; import { NavHeader } from "@/components/nav-header";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Stock Analysis App", title: "Stock Analysis App",
description: "AI Powered Stock Analysis", description: "AI Powered Stock Analysis",
@ -17,7 +14,7 @@ export default function RootLayout({
}>) { }>) {
return ( return (
<html lang="en"> <html lang="en">
<body className={inter.className}> <body className="font-sans antialiased">
<NavHeader /> <NavHeader />
<main>{children}</main> <main>{children}</main>
</body> </body>

View File

@ -478,6 +478,17 @@ function ChatPane({
<ReactMarkdown <ReactMarkdown
remarkPlugins={[remarkGfm]} remarkPlugins={[remarkGfm]}
components={{ components={{
p: ({ node, children, ...props }) => <p className="mb-2 last:mb-0" {...props}>{children}</p>,
strong: ({ node, children, ...props }) => <strong className="font-bold text-foreground" {...props}>{children}</strong>,
em: ({ node, children, ...props }) => <em className="italic" {...props}>{children}</em>,
a: ({ node, href, children, ...props }) => <a href={href} className="text-blue-500 hover:underline" target="_blank" rel="noopener noreferrer" {...props}>{children}</a>,
ul: ({ node, children, ...props }) => <ul className="list-disc list-inside mb-2" {...props}>{children}</ul>,
ol: ({ node, children, ...props }) => <ol className="list-decimal list-inside mb-2" {...props}>{children}</ol>,
li: ({ node, children, ...props }) => <li className="mb-1" {...props}>{children}</li>,
h1: ({ node, children, ...props }) => <h1 className="text-lg font-bold mb-2" {...props}>{children}</h1>,
h2: ({ node, children, ...props }) => <h2 className="text-base font-bold mb-2" {...props}>{children}</h2>,
h3: ({ node, children, ...props }) => <h3 className="text-sm font-bold mb-1" {...props}>{children}</h3>,
blockquote: ({ node, children, ...props }) => <blockquote className="border-l-4 border-muted-foreground/30 pl-3 italic text-muted-foreground my-2" {...props}>{children}</blockquote>,
pre: ({ node, className, ...props }) => <pre className={`overflow-auto w-full my-2 bg-black/10 dark:bg-black/30 p-2 rounded ${className || ''}`} {...props} />, pre: ({ node, className, ...props }) => <pre className={`overflow-auto w-full my-2 bg-black/10 dark:bg-black/30 p-2 rounded ${className || ''}`} {...props} />,
code: ({ node, className, children, ...props }) => { code: ({ node, className, children, ...props }) => {
const match = /language-(\w+)/.exec(className || '') const match = /language-(\w+)/.exec(className || '')