Home > Blockchain >  SvelteKit SSR fetch() when backend is in a Docker container
SvelteKit SSR fetch() when backend is in a Docker container

Time:07-03

I use docker compose for my project. It includes these containers:

  1. Nginx
  2. PostgreSQL
  3. Backend (Node.js)
  4. Frontend (SvelteKit)

I use SvelteKit's Load function to send request to my backend. In short, it sends http request to the backend container either on client-side or server-side. Which means, the request can be send not only by browser but also by container itself.

I can't get it to work on both client-side and server-side fetch. Only one of them is working.

I tried these URLs:

  • http://api.localhost/articles (only client-side request works)
  • http://api.host.docker.internal/articles (only server-side request works)
  • http://backend:8080/articles (only server-side request works)

I get this error:

From SvelteKit: FetchError: request to http://api.localhost/articles failed, reason: connect ECONNREFUSED 127.0.0.1:80

From Nginx: Timeout error

Docker-compose.yml file:

version: '3.8'
services:

  webserver:
    restart: unless-stopped
    image: nginx:latest
    ports:
      - 80:80
      - 443:443
    depends_on:
      - frontend
      - backend
    networks:
      - webserver
    volumes:
      - ./webserver/nginx/conf/:/etc/nginx/conf.d/
      - ./webserver/certbot/www:/var/www/certbot/:ro
      - ./webserver/certbot/conf/:/etc/nginx/ssl/:ro

  backend:
    restart: unless-stopped
    build:
      context: ./backend
      target: development
    ports:
      - 8080:8080
    depends_on:
      - db
    networks:
      - database
      - webserver
    volumes:
      - ./backend:/app

  frontend:
    restart: unless-stopped
    build:
      context: ./frontend
      target: development
    ports:
      - 3000:3000
    depends_on:
      - backend
    networks:
      - webserver

networks:
  database:
    driver: bridge
  webserver:
    driver: bridge

How can I send server-side request to docker container by using http://api.localhost/articles as URL? I also want my container to be accesible by other containers as http://backend:8080 if possible.

CodePudding user response:

From a docker compose you will be able to CURL from one container using the dns (service name you gave in the compose file)

CURL -XGET backend:8080

You can achieve this also by running all of these containers on host driver network.

Regarding the http://api.localhost/articles

You can change the /etc/hosts

And specify the IP you want your computer to try to communicate with when this url : http://api.localhost/articles is used.

CodePudding user response:

Use SvelteKit's externalFetch hook to have a different and overridden API URL in frontend and backend.

In docker-compose, the containers should be able to access each other by name if they are in the same Docker network.

Your frontend docker SSR should be able to call your backend docker by using the URL:

http://backend:8080

Web browser should be able to call your backend by using the URL:

(whatever reads in your Nginx configuration files)

Naturally, there are many reasons why this could fail. The best way to tackle this is to test URLs one by one, server by server using curl and entering addresses to the web browser address. It's not possible to answer the exact reason why it fails, because the question does not contain enough information, or generally repeatable recipe for the issue.

For further information, here is our sample configuration for a dockerised SvelteKit frontend. The internal backend shortcut is defined using hooks and configuration variables. Here is our externalFetch example.

  • Related