SvelteKit Docker fetch issue

112 views Asked by At

I have searched for many hours but haven't found any answer to this problem: I have 2 docker containers. One with FastAPI backend and one with Sveltekit app.

Containers

Sending requests with openapi docs is fine. Sveltekit with npm run dev works fine too. But SvelteKit fetch in docker container throws error:

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  | }

My vite config

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/, '')
            }
        }
    }
});

Tried changing target to http://localhost:8000 and http://backend:8000 but nothing helped.

Frontend 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:

1

There are 1 answers

0
Efremov Egor On BEST ANSWER

I added this to hooks.server.js and it worked: reference

import { backend_url } from './utils';

export async function handleFetch({ request, fetch }) {
    request = new Request(`http://api:8000${request.url.split(backend_url)[1]}`, request);
    return fetch(request);
}

Where api is name of docker container