0

Context

I have two dockerized apps, one contains the frontend (Sveltekit) and one contains the backend API (Laravel). Both apps are on their own directory and contain separate docker-compose files. There's a docker-compose for the frontend app and a docker-compose for the backend API app. So far, while testing I simply run my frontend app locally (not in a container) and was able to fetch data from the API which was running on a container.

Problem The problem I encountered first was when I tried to use the dockerized version of the frontend app. The container built correctly and the UI loaded but it can't fetch data from the API since the API lives in a different container. Remember, both apps have their own docker-compose file so for each app I run docker-compose up --build. It makes sense that I cannot access the backend API from the frontend container, after all I guess they are in different networks. So I tried to get rid of the docker-compose file in my frontend project and simply create a service in the docker-compose that belongs to the backend to load the frontend by referencing the existing Dockerfile that belongs to the frontend project. When running: docker-compose up --build the build seems to be successful (no errors) but now I cannot access the frontend via the URL.

What's going on?

Here's the frontend's Dockerfile:

# Dockerfile

# base stage
FROM node:21-alpine AS base

WORKDIR /app

# copy everything
COPY . .

# install dependencies
RUN npm install

# ----------------------------------------------------------
FROM base AS dev
# Set the Node environment to development to ensure all packages are installed
ENV NODE_ENV development
EXPOSE 5137
CMD ["npm", "run", "dev"]

# ----------------------------------------------------------
FROM base AS build
# build the app
RUN npm run build

# run stage, to separate it from the build stage, to save disk storage
FROM node:21-alpine AS prod

WORKDIR /app

# Set the Node environment to development to ensure all packages are installed
ENV NODE_ENV production

# copy stuff from the build stage
COPY --from=build /app/package*.json ./
COPY --from=build /app/build ./build

# expose the app's port
EXPOSE 3000

# run the server
CMD ["node", "./build/index.js"]

And here's the docker-compose file:

version: "3.9"
services:
  app:
    build:
      context: ./
      dockerfile: Dockerfile
    image: dmc
    container_name: dmc-app
    restart: unless-stopped
    working_dir: /var/www/
    depends_on:
      - db
      - nginx
    volumes:
      - ./:/var/www/
      - ./docker/php/conf.d/xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
      - ./docker/php/conf.d/error_reporting.ini:/usr/local/etc/php/conf.d/error_reporting.ini
      - ./images:/public/images
    expose:
      - "9003"
    networks:
      - dmc-net

  nginx:
    image: nginx:1.23.2-alpine
    container_name: dmc-nginx
    restart: unless-stopped
    ports:
      - "8000:80"
    volumes:
      - ./:/var/www
      - ./docker-compose/nginx:/etc/nginx/conf.d
    networks:
      - dmc-net

  supervisor:
    image: dmc
    container_name: dmc-supervisor
    networks:
      - dmc-net
    depends_on:
      - app
      - nginx
    command:
      - supervisord

  db:
    image: mysql:8.0.31
    container_name: dmc-db
    restart: unless-stopped
    # using 3307 on the host machine to avoid collisions in case there's a local MySQL instance installed already.
    ports:
      - "3307:3306"
    # use the variables declared in .env file
    environment:
      MYSQL_HOST: ${DB_HOST}
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: abcd1234
      MYSQL_USER: ${DB_USERNAME}
      SERVICE_TAGS: dev
      SERVICE_NAME: mysql
    volumes:
      - ./docker-compose/mysql:/docker-entrypoint-initdb.d
      - mysql-data:/var/lib/mysql
    networks:
      - dmc-net

  dmc-web:
    build:
      context: .
      dockerfile: /Users/hansgruber/Desktop/webdev/projects/dundermifflin-ui/Dockerfile
      target: dev
    container_name: dmc-web
    restart: always
    ports:
      - "5173:5173"
    volumes:
      # it avoids mounting the workspace root
      # because it may cause OS specific node_modules folder
      # or build folder(.svelte-kit) to be mounted.
      # they conflict with the temporary results from docker space.
      # this is why many mono repos utilize ./src folder
      - ./src:/app/src
      - ./static:/app/app/static
      - ./static:/app/static/
    depends_on:
      - app
      - nginx
      - db
    networks:
      - dmc-net

networks:
  dmc-net:
    driver: bridge

volumes:
  mysql-data:

I don't see any port collision and the service also uses the same network.

Any idea what's wrong?

Initially I thought it was perhaps a CORS issue or something like that, but I'd expect to see any output in the console when attempting to access http://localhost:5173/ which is the URL displayed in the build output:

dmc-web         | 
dmc-web         | > dev
dmc-web         | > vite
dmc-web         | 
dmc-web         | 
dmc-web         |   VITE v3.2.1  ready in 403 ms
dmc-web         | 
dmc-web         |   ➜  Local:   http://localhost:5173/
dmc-web         |   ➜  Network: use --host to expose
dmc-web         | 
dmc-web         |   LARAVEL v9.40.1  plugin v0.5.4
dmc-web         | 
dmc-web         |   ➜  APP_URL: http://localhost

UPDATE

So I was able to partially make it work. Here's what I did differently:

  1. My frontend project lives in a separate location, it is not located at the same location where the backend project resides. In docker-compose I was using context: . but it should have been context: /Users/hansgruber/Desktop/webdev/projects/dundermifflin-ui which is actually pointing to the folder where the project resides. I have updated this in my docker-compose.

Now, if I tried to build it using target: dev for the frontend project (dmc-web) then I still cannot access the UI, BUT if I run it using target: dev then the UI loads. It's not fetching anything from the backend, meaning that it's not connecting to it and that's something I'm looking into.

Now the issue is that the build using target: dev is failing.

Any suggestions?

UPDATE 2

I've updated vite.config.js and added a server property. Tried different ports and for each port I built the app again. The ports used were 3000, 5137 and 5173. Here's the file contents:

import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vitest/config';

export default defineConfig({
    plugins: [sveltekit()],
    test: {
        include: ['src/**/*.{test,spec}.{js,ts}']
    },
    server: {
        host: '0.0.0.0',
        port: 5137, // tested 5137, 3000, 5173
    }
});

When using 3000 and 5173 I'm getting:

dmc-web | src/app.html does not exist

which seems like it is establishing a connection but it's not finding the files.

When using 5137 I'm getting:

This site can’t be reached. localhost refused to connect.

Meaning that it cannot establish connection at all.

4
  • Does this answer your question? Fail to resolve docker compose service name from front end Commented Jan 19, 2024 at 1:46
  • ...or "Unknown host" error calling containerized backend from frontend? Unable to Dockerize Vite React-Typescript Project also discusses why your frontend container in isolation might be unreachable. Commented Jan 19, 2024 at 2:03
  • Does not really matter even if both lives on different container. FE (svelte) should consume API (laravel)'s endpoint using routes (with the exported ports). How do you access the API routes? localhost:8080? Then access them the same as localhost:8080 or whatever port you used unless there are ports missing or conflicting Commented Jan 19, 2024 at 2:20
  • @Mr.Kenneth my API routes are accessible using http://localhost:8000/api/. The issue is the frontend, I mean, at the moment is not even that the frontend is cannot fetch data from the backend, the problem is that the frontend is not loading at all. Some UI should load but fail to fetch data, but that's not happening Commented Jan 20, 2024 at 16:39

1 Answer 1

0

I think Network: use --host to expose suggests that Vite only allows connections from apps running inside the container itself. You need to configure Vite using the server.host to allow apps from outside the container (i.e. your web browser) to connect to it.

Sign up to request clarification or add additional context in comments.

8 Comments

Hi Peppe. This is basically what this answer is suggesting stackoverflow.com/questions/68595151/… right? I tried this but didn't work.
@MrCujo Yep, I meant something like that. Using that option + using port mapping is all I've needed to make it work, if I remember right.
I believe that perhaps the solution is in this direction, I've updated my question, still not working though
When it complains that src/app.html doesn't exist, then the problem can be that your volumes paths are wrong. Try building and running without volumes first, and if that works, then the volumes paths are wrong. If a volume path points to a none-existing folder on the host computer, then Docker will create an empty folder there, and it won't contain the index.html file, hence the error you are getting.
Sounds like the volume paths were wrong, so adding them back and changing their paths to correct values would be a step in the right direction. Which there correct values are I don't know, since I don't know the folder structure of your project.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.