Docker环境下Bun(oven/bun)热重载失效问题求助
Docker + Bun 项目容器内热重载失效问题
我有一个基于Docker和Bun的项目,包含Astro网站与Bun API服务,二者均由Bun编译。本地独立启动项目时热重载功能正常,但容器内的文件变更始终无法触发热重载,尝试多种网络上的方法都未解决。以下是项目相关文件信息:
项目结构
. ├── README.md ├── api │ ├── Dockerfile │ ├── bun.lockb │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── docker-compose.yml ├── nginx │ └── nginx.conf └── web ├── Dockerfile ├── README.md ├── astro.config.mjs ├── bun.lockb ├── index.html ├── package.json ├── public │ └── favicon.svg ├── src │ ├── components │ │ ├── Card.astro │ │ ├── Post.vue │ │ ├── Posts.vue │ │ ├── atoms │ │ │ └── Button.vue │ │ ├── molecules │ │ ├── organisms │ │ └── templates │ ├── env.d.ts │ ├── layouts │ │ └── Layout.astro │ ├── pages │ │ ├── api │ │ │ └── posts │ │ │ ├── [id].ts │ │ │ └── index.ts │ │ ├── index.astro │ │ └── posts │ │ ├── [id].astro │ │ └── index.astro │ └── utils ├── tsconfig.json └── tsconfig.node.json 17 directories, 28 files
docker-compose.yml
version: '3.8' networks: cv_network: driver: bridge volumes: web_node_modules: api_node_modules: services: web: container_name: cv_web build: web image: web restart: "no" networks: - cv_network volumes: - ./web/:/app - web_node_modules:/app/node_modules ports: - 3000:3000 env_file: - project.env api: container_name: cv_api build: api image: api restart: "no" networks: - cv_network volumes: - ./api/:/app - api_node_modules:/app/node_modules ports: - 8000:8000 nginx: container_name: cv_nginx image: nginx:1.25.2-alpine-slim networks: - cv_network volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro depends_on: - web - api ports: - 7800:7800
api/Dockerfile
FROM oven/bun:1.0.3-slim WORKDIR /api COPY package*.json bun.lockb ./ RUN bun install COPY . . CMD [ "bun", "run", "dev" ]
api/package.json
{ "name": "bun_app", "version": "1.0.50", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "bun --watch run src/index.ts" }, "dependencies": { }, "devDependencies": { "bun-types": "1.0.3" }, "module": "src/index.js" }
api/src/index.ts
import { type Serve } from "bun"; type Middleware = (req: any, res: any, next: () => void) => void; type RequestHandler = (req: any, res: any) => Response; const loggerMiddleware: Middleware = (req, res, next) => { const url = new URL(req.url); const method = req.method; const currentTime = new Date().toISOString(); console.log(`[${currentTime}] ${method} - ${url.pathname}`); next(); }; class Router { routes: { [method: string]: { [path: string]: RequestHandler } } = {}; get(path: string, handler: RequestHandler) { this.addRoute("GET", path, handler); } post(path: string, handler: RequestHandler) { this.addRoute("POST", path, handler); } put(path: string, handler: RequestHandler) { this.addRoute("PUT", path, handler); } private addRoute(method: string, path: string, handler: RequestHandler) { if (!this.routes[method]) { this.routes[method] = {}; } this.routes[method][path] = handler; } } class Server { middlewares: Middleware[] = []; routes: { [method: string]: { [path: string]: RequestHandler } } = {}; use(middleware: Middleware) { this.middlewares.push(middleware); } get(path: string, handler: RequestHandler) { this.addRoute("GET", path, handler); } post(path: string, handler: RequestHandler) { this.addRoute("POST", path, handler); } // Agregar más métodos HTTP según sea necesario private addRoute(method: string, path: string, handler: RequestHandler) { if (!this.routes[method]) { this.routes[method] = {}; } this.routes[method][path] = handler; } useRouter(path: string, router: Router) { for (const [method, routes] of Object.entries(router.routes)) { for (const [routePath, handler] of Object.entries(routes)) { const fullPath = path + routePath; this.addRoute(method, fullPath, handler); } } } async fetch(request: Request, server: Server): Promise<Response> { try { if (!request || !server) { console.error("Request o Server no definidos"); return new Response("Internal Server Error", { status: 500 }); } const url = new URL(request.url); const pathname = url.pathname; const method = request.method; let response: Response; // Ejecutamos los middlewares en orden for (const middleware of this.middlewares) { middleware(request, response, () => {}); } if (this.routes[method] && this.routes[method][pathname]) { const handler = this.routes[method][pathname]; response = handler(request, new Response("")); } else { throw new Error("Route not found"); // Lanza un error si la ruta no se encuentra } return response; } catch (error) { console.error(`Error: ${error.message}`); return new Response(error.message, { status: 500 }); } } } const app = new Server(); app.use(loggerMiddleware); // Agregar middlewares app.use((req, res, next) => { console.log("Middleware 1"); next(); }); // Agregar rutas app.get("/", (req, res) => { res = new Response("Hello, world!", { status: 200 }); return res; }); const router = new Router(); router.get("", (req, res) => { return new Response(JSON.stringify({ message: "aaaaaaaaaa" }), { status: 200, }); }); router.post("", (req, res) => { return new Response(JSON.stringify({ message: "Router POST succeed" }), { status: 200, }); }); router.put("", (req, res) => { return new Response(JSON.stringify({ message: "Router PUT succeed" }), { status: 200, }); }); app.useRouter("/test", router); // Iniciar el servidor export default { port: 8000, fetch(req) { return app.fetch(req, app); }, error(error: Error) { return new Response(`<pre>${error} ${error.stack}</pre>`, { headers: { "Content-Type": "text/html", }, }); }, } satisfies Serve;
nginx/nginx.conf
worker_processes 1; events { worker_connections 1024; } http { # proxy_cache_path /var/cache/nginx keys_zone=astro_ssg_cache:1m inactive=5m max_size=512m; upstream web { server web:3000; } upstream api { server api:8000; } server { gzip on; gzip_types text/css application/javascript application/json image/svg+xml; gzip_min_length 1000; listen 7800; server_name localhost; location / { proxy_pass http://web; proxy_http_version 1.1; # proxy_cache astro_ssg_cache; # proxy_cache_key $uri; # proxy_cache_valid 5m; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header Host $host; proxy_redirect off; } } # Para la API server { listen 7800; server_name api.localhost; location / { proxy_pass http://api; # Suponiendo que "api" es el nombre del servicio en docker-compose.yml # ... (otros ajustes de proxy aquí) } } # Para el panel de administración server { listen 7800; server_name admin.localhost; location / { proxy_pass http://web; # Asumiendo que "admin" es otro servicio en docker-compose.yml # ... (otros ajustes de proxy aquí) } } # Para otros subdominios dinámicos server { listen 7800; server_name ~^(?<subdomain>.+)\.localhost$; location / { proxy_pass http://web; # Redirige todos los demás subdominios al servicio "web" # ... (otros ajustes de proxy aquí) } } }
环境信息
- 操作系统:Windows 11
- WSL2:Ubuntu 20.04.6 LTS
内容的提问来源于stack exchange,提问作者bypabloc_
相关产品推荐
相关产品推荐

