1

I am trying to make a fetch request using a dockerized NodeJS( + nest framework ) (version 16.20.0) server. The docker image contains a strapi container running on http://localhost:1337/ and nodejs_api container running on http://localhost:4000/.

I am trying to make a GET request to strapi, but i am getting the following error:

[2] FetchError: request to http://127.0.0.1:1337/api/login-page failed, reason: connect ECONNREFUSED 127.0.0.1:1337

So I created two servers (BOTH with the same code) to see what the problem is, one running in a dockerized container and one that is not dockerized. The dockerized one seems to be the one with the error. The NOT dockerized one is fine and i can make requests that work.

I tried fetching (as you will see below in the globalLabels.service file) using http://localhost:3000/ and http://127.0.0.1:1337/ BUT nothing seems to work. Also tried rebuilding the docker image.

What could be the issue?

Here's the code for both the servers: panel-content.controller.ts

import { Controller, Get } from '@nestjs/common';
import { GetLabelsService } from '../get-labels/get-labels.service';
import fetch from 'node-fetch';

//Get all the labels related to the admin-panel
@Controller('panel-content')
export class PanelContentController {
    constructor(private readonly getLabels: GetLabelsService){}

    @Get('ad-board-page')
    async getAdBoardLabels(){
        const labels = this.getLabels.getRouteLabels('/api/ad-board-page');
        return labels
    }

    @Get('chats-page')
    async getChatsLabels(){
        const labels = this.getLabels.getRouteLabels('/api/chats-page');
        return labels
    }
    
    @Get('collections-page')
    async getCollectionsLabels(){
        const labels = await this.getLabels.getRouteLabels('/api/collections-page');
        return labels
    }

    @Get('events-page')
    async getEventsLabels(){
        const labels = await this.getLabels.getRouteLabels('/api/events-page');
        return labels
    }

    @Get('home-page')
    async getHomepageLabels(){
        const labels = await this.getLabels.getRouteLabels('/api/home-page');
        return labels
    }

    @Get('login-page')
    async getLoginPageLabels(){
        const labels = await this.getLabels.getRouteLabels('/api/login-page');
        
        return labels
    }

    @Get('news-page')
    async getNewsPageLabels(){
        const labels = await this.getLabels.getRouteLabels('/api/news-page');
        return labels
    }

    @Get('notifications-page')
    async getNotificationsPageLabels(){
        const labels = await this.getLabels.getRouteLabels('/api/notifications-page');
        return labels
    }

    @Get('orders-page')
    async getOrdersPageLabels(){
        const labels = await this.getLabels.getRouteLabels('/api/orders-page');
        return labels
    }

    @Get('shop-page')
    async getShopPageLabels(){
        const labels = await this.getLabels.getRouteLabels('/api/shop-page');
        return labels
    }

    @Get('users-page')
    async getUsersPageLabels(){
        const labels = await this.getLabels.getRouteLabels('/api/users-page');
        return labels
    }
}

getLabels.service.ts

import { Injectable } from "@nestjs/common";
import fetch from 'node-fetch';

@Injectable()
export class GetLabelsService {
    async getRouteLabels(labelPath: string) {
        const request = `http://127.0.0.1:1337${labelPath}`;
        console.log(request)
        const res = await fetch(request);
        const labels_data = await res.json();
        delete labels_data.data.attributes.createdAt;
        delete labels_data.data.attributes.publishedAt;
        delete labels_data.data.attributes.updatedAt;
        delete labels_data.meta;
        return labels_data
    }
}

here's my package.json

{
  "name": "mypta-backend",
  "version": "0.0.1",
  "description": "",
  "author": "",
  "private": true,
  "license": "UNLICENSED",
  "scripts": {
    "prebuild": "rimraf dist",
    "build": "nest build",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
    "start": "concurrently --kill-others \"node index.js\" \"node socket.js\" \"nest start\"",
    "start:dev": "concurrently --kill-others \"node index.js\" \"node socket.js\" \"nest start --watch\"",
    "start:debug": "nest start --debug --watch",
    "start:prod": "node dist/main",
    "typeorm": "ts-node ./node_modules/typeorm/cli.js",
    "migration:create": "typeorm migration:create -n",
    "migration:run": "NODE_ENV=dev&& ts-node ./node_modules/typeorm/cli.js migration:run",
    "migration:revert": "set NODE_ENV=dev&& ts-node ./node_modules/typeorm/cli.js migration:revert",
    "migration:generate": "set NODE_ENV=dev&& yarn typeorm migration:generate -n",
    "schema:sync": "yarn typeorm schema:sync",
    "schema:drop": "yarn typeorm schema:drop",
    "cache:clear": "yarn typeorm cache:clear",
    "seed:run": "set NODE_ENV=dev&& ts-node ./node_modules/typeorm-seeding/dist/cli.js seed",
    "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json"
  },
  "dependencies": {
    "@ffmpeg-installer/ffmpeg": "^1.1.0",
    "@nestjs-modules/mailer": "^1.8.1",
    "@nestjs/common": "^8.0.0",
    "@nestjs/config": "^1.1.0",
    "@nestjs/core": "^8.0.0",
    "@nestjs/jwt": "^8.0.0",
    "@nestjs/passport": "^8.0.1",
    "@nestjs/platform-express": "^8.4.7",
    "@nestjs/platform-socket.io": "^8.4.5",
    "@nestjs/typeorm": "^8.0.2",
    "@types/fluent-ffmpeg": "^2.1.20",
    "@types/randomstring": "^1.1.8",
    "@types/validator": "^13.6.6",
    "bcrypt": "^5.0.1",
    "bcryptjs": "^2.4.3",
    "class-transformer": "^0.4.0",
    "class-validator": "^0.13.1",
    "concurrently": "^7.2.2",
    "dotenv": "^16.0.1",
    "ejs": "^3.1.9",
    "firebase-admin": "^10.0.0",
    "fluent-ffmpeg": "^2.1.2",
    "lodash": "^4.17.21",
    "moment": "^2.29.1",
    "mysql2": "^2.3.3",
    "node-fetch": "2",
    "nodemailer": "^6.7.1",
    "passport": "^0.5.0",
    "passport-jwt": "^4.0.0",
    "passport-local": "^1.0.0",
    "randomstring": "^1.2.1",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.2",
    "rxjs": "^7.2.0",
    "socket.io": "3.1.2",
    "stripe": "^8.191.0",
    "typeorm": "^0.2.40",
    "typeorm-seeding": "^1.6.1",
    "yarn": "^1.22.18"
  },
  "devDependencies": {
    "@nestjs/cli": "^8.0.0",
    "@nestjs/schematics": "^8.0.0",
    "@nestjs/testing": "^8.0.0",
    "@types/express": "^4.17.13",
    "@types/jest": "^27.0.1",
    "@types/node": "^16.0.0",
    "@types/passport-local": "^1.0.34",
    "@types/supertest": "^2.0.11",
    "@typescript-eslint/eslint-plugin": "^5.0.0",
    "@typescript-eslint/parser": "^5.0.0",
    "eslint": "^8.0.1",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-prettier": "^4.0.0",
    "jest": "^27.2.5",
    "prettier": "^2.3.2",
    "source-map-support": "^0.5.20",
    "supertest": "^6.1.3",
    "ts-jest": "^27.0.3",
    "ts-loader": "^9.2.3",
    "ts-node": "^10.0.0",
    "tsconfig-paths": "^3.10.1",
    "typescript": "^4.3.5"
  },
  "jest": {
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": "src",
    "testRegex": ".*\\.spec\\.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "collectCoverageFrom": [
      "**/*.(t|j)s"
    ],
    "coverageDirectory": "../coverage",
    "testEnvironment": "node"
  }
}

docker-compose file

version: "3.8"
services:
  api:
    build:
      context: .
      dockerfile: Dockerfile-api
    environment:
      DB_TYPE: ${DB_TYPE}
      DB_HOST: ${DB_HOST}
      DB_PORT: ${DB_PORT}
      DB_USERNAME: ${DB_USERNAME}
      DB_PASSWORD: ${DB_PASSWORD}
      DB_DATABASE: ${DB_DATABASE}
      APP_HOST: ${APP_HOST}
      JWT_SECRET: ${JWT_SECRET}
      JWT_EXIPRY_TIME: ${JWT_EXIPRY_TIME}
      STRIPE_PUBLISH_KEY: ${STRIPE_PUBLISH_KEY}
      STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY}
      currency: ${currency}
      FCM_DATABASE_URL: ${FCM_DATABASE_URL}
      SMTP_HOST: ${SMTP_HOST}
      SMTP_USERNAME: ${SMTP_USERNAME}
      SMTP_PASSWORD: ${SMTP_PASSWORD}
    ports:
      - 4000:4000
    networks:
      - app-network

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: phpmyadmin_container
    restart: always
    environment:
      PMA_HOST: ${DB_HOST}
      PMA_USER: ${DB_USERNAME}
      PMA_PASSWORD: ${DB_PASSWORD}
      UPLOAD_LIMIT: 64M
    ports:
      - "8080:80"
    networks:
      - app-network
      
  strapi:
    build:
      context: ./cms
      dockerfile: Dockerfile-cms
    environment:
      DATABASE_CLIENT: ${DATABASE_CLIENT}
      DATABASE_HOST: ${DATABASE_HOST}
      DATABASE_PORT: ${DATABASE_PORT}
      DATABASE_NAME: ${DATABASE_NAME}
      DATABASE_USERNAME: ${DATABASE_USERNAME}
      DATABASE_PASSWORD: ${DATABASE_PASSWORD}
      APP_KEYS: ${APP_KEYS}
      API_TOKEN_SALT: ${API_TOKEN_SALT}
      ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET}
      JWT_SECRET: ${JWT_SECRET}
      NODE_ENV: ${NODE_ENV}
      MASTER_KEY: ${MASTER_KEY}
      MEILI_HOST: http://meilisearch:7700
      CLOUDINARY_KEY: ${CLOUDINARY_KEY}
      CLOUDINARY_NAME: ${CLOUDINARY_NAME}
      CLOUDINARY_SECRET: ${CLOUDINARY_SECRET}
    volumes:
      - ./cms/config:/srv/app/config
      - ./cms/src:/srv/app/src
      - ./cms/package.json:/srv/package.json
      - ./cms/yarn.lock:/srv/yarn.lock
      - ./cms/datadump:/srv/app/datadump
      - ./cms/public:/srv/app/public
    ports:
      - 1337:1337
    depends_on:
      - postgres
    networks:
      - app-network
    command: yarn develop

  meilisearch:
    image: getmeili/meilisearch:latest
    environment:
      MEILI_MASTER_KEY: ${MASTER_KEY}
    ports:
      - 7700:7700
    networks:
      - app-network
    volumes:
      - ./data:/srv/app/data
      
  pgadmin:
    image: dpage/pgadmin4
    environment:
      PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
      PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
    ports:
      - 8088:80
    depends_on:
      - postgres
    networks:
      - app-network
      
  # Back-end services 
  postgres:
    image: postgres:12
    environment:
      POSTGRES_USER: ${DATABASE_USERNAME}
      POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
      POSTGRES_DB: ${DATABASE_NAME}
    volumes:
      - pgdata:/var/lib/postgresql/data
    ports:
      - 5432:5432
    networks:
      - app-network

volumes:
  db_data:
  pgdata:

networks:
  app-network:
    driver: bridge

DockerFile

# Dockerfile
FROM node:16-alpine

# create destination directory
RUN mkdir -p /usr/src/api
WORKDIR /usr/src/api

# update and install dependency
RUN apk update && apk upgrade

# copy the app, note .dockerignore
COPY . /usr/src/api/

RUN yarn
RUN yarn build

EXPOSE 3000

CMD [ "yarn", "start:dev" ]

as you can see, im using node-fetch to also make requests.

1 Answers1

0

If you're running the Nest API from within a docker container (looks like you are via your docker-compose) you can use the compose service's name as the host, so instead of using 127.0.0.1 you can use strapi and docker should set up the DNS resolution to point to the strapi container's IP.

Jay McDoniel
  • 57,339
  • 7
  • 135
  • 147