You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SvelteKit Docker容器中Fetch请求失败问题求助

Docker容器中SvelteKit调用FastAPI后端出现TLS连接错误

我花了好几个小时排查都没解决:部署了两个Docker容器,分别运行FastAPI后端和SvelteKit前端应用。通过OpenAPI文档发送请求正常,本地使用npm run dev运行SvelteKit也没问题,但Docker容器中的SvelteKit发起Fetch请求时抛出如下错误:

frontend  | TypeError: fetch failed
frontend  |     at node:internal/deps/undici/undici:12443:11
frontend  |     at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
frontend  |     at async resolve2 (file:///app/build/server/index.js:4118:14)
frontend  |     at async respond (file:///app/build/server/index.js:3941:22)
frontend  |     at async fetch (file:///app/build/server/index.js:3696:26) {
frontend  |   cause: Error: Client network socket disconnected before secure TLS connection was established   
frontend  |       at TLSSocket.onConnectEnd (node:_tls_wrap:1727:19)
frontend  |       at TLSSocket.emit (node:events:531:35)
frontend  |       at endReadableNT (node:internal/streams/readable:1696:12)
frontend  |       at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
frontend  |     code: 'ECONNRESET',
frontend  |     path: undefined,
frontend  |     host: '192.168.0.13',
frontend  |     port: 443,
frontend  |     localAddress: null
frontend  |   }
frontend  | }

我的Vite配置

export default defineConfig({
    plugins: [sveltekit()],

    server: {
        host: true,
        proxy: {
            '/api': {
                target: 'http://127.0.0.1:8000', // see here
                changeOrigin: true,
                secure: false,
                rewrite: (path) => path.replace(/^\/api/, '')
            }
        }
    }
});

我尝试将target改为http://localhost:8000和http://backend:8000,但均无效。

前端Dockerfile

FROM node:latest AS builder

RUN mkdir /app && mkdir /app/data

COPY . /app

RUN cd /app && yarn install && \
    yarn build 



FROM node:latest

RUN mkdir /app

COPY --from=builder /app/build /app/build
COPY --from=builder /app/package.json /app/yarn.lock /app/

RUN cd /app && \
    yarn install --production && \
    yarn cache clean

WORKDIR /app

CMD ["node", "build/index.js"]

Docker Compose配置

services:
  api:
    build:
      context: ./backend
      target: builder
    container_name: backend
    environment:
      - PORT=8000
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_HOST=${POSTGRES_HOST}
      - POSTGRES_PORT=${POSTGRES_PORT}
      - POSTGRES_NAME=${POSTGRES_NAME}
      - POSTGRES_DB_URL=${POSTGRES_DB_URL}
      - POSTGRES_ECHO=${POSTGRES_ECHO}

      - EMAIL_USERNAME=${EMAIL_USERNAME}
      - EMAIL_PASSWORD=${EMAIL_PASSWORD}
      - EMAIL_FROM=${EMAIL_FROM}
      - EMAIL_PORT=${EMAIL_PORT}
      - EMAIL_HOST=${EMAIL_HOST}
      - EMAIL_STARTTLS=${EMAIL_STARTTLS}
      - EMAIL_SSL_TLS=${EMAIL_SSL_TLS}
      - USE_CREDENTIALS=${USE_CREDENTIALS}
      - VALIDATE_CERTS=${VALIDATE_CERTS}

      - REDIS_HOST=redis
      - REDIS_PORT=${REDIS_PORT}
      - REDIS_DB=${REDIS_DB}

      - OAUTH_SECRET_KEY=${OAUTH_SECRET_KEY}
      - OAUTH_ACCESS_TOKEN_EXPIRE_MINUTES=${OAUTH_ACCESS_TOKEN_EXPIRE_MINUTES}
    ports:
      - "8000:8000"
    expose:
      - "8000:8000"
    depends_on:
      - postgres
      - redis
  frontend:
    build:
      context: ./frontend
    container_name: frontend
    expose:
      - "80:3000"
    ports:
      - "80:3000"
  postgres:
    image: postgres:latest
    container_name: postgres
    environment:
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=${POSTGRES_NAME}
      - POSTGRES_USER=${POSTGRES_USER}
    expose:
      - 5432
    volumes:
      - postgres_data:/var/lib/postgresql/data
  redis:
    image: redis
    ports:
      - "6380:6379"
    expose:
      - "6379"
    volumes:
      - redis_data:/data
  worker:
    build:
      context: ./backend
      dockerfile: Celerybuild

    environment:
      - PORT=8000
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_HOST=${POSTGRES_HOST}
      - POSTGRES_PORT=${POSTGRES_PORT}
      - POSTGRES_NAME=${POSTGRES_NAME}
      - POSTGRES_DB_URL=${POSTGRES_DB_URL}
      - POSTGRES_ECHO=${POSTGRES_ECHO}

      - EMAIL_USERNAME=${EMAIL_USERNAME}
      - EMAIL_PASSWORD=${EMAIL_PASSWORD}
      - EMAIL_FROM=${EMAIL_FROM}
      - EMAIL_PORT=${EMAIL_PORT}
      - EMAIL_HOST=${EMAIL_HOST}
      - EMAIL_STARTTLS=${EMAIL_STARTTLS}
      - EMAIL_SSL_TLS=${EMAIL_SSL_TLS}
      - USE_CREDENTIALS=${USE_CREDENTIALS}
      - VALIDATE_CERTS=${VALIDATE_CERTS}

      - REDIS_HOST=redis
      - REDIS_PORT=${REDIS_PORT}
      - REDIS_DB=${REDIS_DB}

      - OAUTH_SECRET_KEY=${OAUTH_SECRET_KEY}
      - OAUTH_ACCESS_TOKEN_EXPIRE_MINUTES=${OAUTH_ACCESS_TOKEN_EXPIRE_MINUTES}
    depends_on:
      - redis
  flower:
    image: mher/flower:0.9.7
    command: ["flower", "--broker=redis://redis:6379", "--port=5555"]
    expose:
      - 5555
    depends_on:
      - redis
volumes:
  postgres_data:
  redis_data:

问题分析与解决

核心问题

错误日志显示请求发往了192.168.0.13:443,说明前端容器内的请求未正确指向后端服务,反而尝试用HTTPS访问本地IP的443端口——但你的后端是运行在8000端口的HTTP服务,直接导致TLS连接失败。

解决步骤

  1. 配置生产环境API地址
    Vite的server.proxy仅在开发环境生效,生产环境需通过环境变量配置API地址:

    • 前端项目根目录创建.env文件,添加:
      VITE_API_URL=http://backend:8000
      
    • 代码中使用该变量发起请求:
      const apiUrl = import.meta.env.VITE_API_URL;
      const response = await fetch(`${apiUrl}/your-endpoint`);
      
  2. 修正Docker Compose配置
    Docker Compose默认创建共享网络,服务名/容器名可直接作为域名访问。同时修正前端服务的expose格式:

    frontend:
      build:
        context: ./frontend
      container_name: frontend
      environment:
        - VITE_API_URL=http://backend:8000
      expose:
        - "3000"
      ports:
        - "80:3000"
    
  3. 确保后端监听所有地址
    确认FastAPI启动时绑定0.0.0.0,而非仅127.0.0.1,否则其他容器无法访问:

    if __name__ == "__main__":
        uvicorn.run("main:app", host="0.0.0.0", port=8000)
    

验证

重启所有容器后,前端请求将正确指向http://backend:8000,TLS连接错误即可解决。


内容的提问来源于stack exchange,提问作者Efremov Egor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 17:02:31