Fetch failed on Docker, but works fine locally

61 views Asked by At

I have the following simple Node app:

import dotenv from "dotenv";
import { Client, GatewayIntentBits } from "discord.js";

dotenv.config();

const client = new Client({
    intents: [
        GatewayIntentBits.Guilds,
        GatewayIntentBits.GuildMessages,
        GatewayIntentBits.GuildMembers,
        GatewayIntentBits.MessageContent
    ]
});

client.login(process.env.DISCORD_TOKEN);

client.on("messageCreate", async (message) => {
    if (message.channelId === "1202421002513158225") {
        console.log(process.env.CK_API_KEY);
        try {
            const rawResponse = await fetch(
                "http://127.0.0.1:3000/api/notifications/push",
                {
                    headers: {
                        "Api-Key": process.env.CK_API_KEY,
                    },
                    body: JSON.stringify({
                        body: {
                            id: "65f387af217854a638ae3bf3",
                            text: message.content
                        }
                    }),
                    method: "POST"
                }
            );

            const response = await rawResponse.json();
            console.info(response)
        } catch (error) {
            console.error(error);
        }
    }
});

It runs fine locally but when running it with docker run it throws an error:

TypeError: fetch failed
    at node:internal/deps/undici/undici:13737:13
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Client.<anonymous> (file:///index.ts:1:437) {
  [cause]: Error: connect ECONNREFUSED 127.0.0.1:3000
      at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1605:16) {
    errno: -111,
    code: 'ECONNREFUSED',
    syscall: 'connect',
    address: '127.0.0.1',
    port: 3000
  }

Here is my Dockerfile:

FROM node:21.7.1

WORKDIR /

COPY package.json package.json
COPY package-lock.json package-lock.json

RUN npm install

COPY . .

CMD [ "npx", "tsx", "index.ts" ]

My package.json:

{
    "name": "commerce-karma-notify",
    "version": "1.0.0",
    "description": "Push notifications from the Commerce Karma Discord Server in the updates channel to the Commerce Karma Notification Center.",
    "main": "index.ts",
    "scripts": {
        "start": "nodemon --exec npm run on",
        "on": "npx tsx index.ts",
        "test": "echo \"Error: no test specified\" && exit 1",
        "format:check": "prettier --check .",
        "format:write": "prettier --write .",
        "lint:check": "eslint .",
        "lint:fix": "eslint --fix ."
    },
    "type": "module",
    "dependencies": {
        "@types/dotenv": "^8.2.0",
        "discord.js": "^14.14.1",
        "dotenv": "^16.4.5",
        "node-fetch": "^3.3.2",
        "typescript": "^5.4.2"
    },
    "devDependencies": {
        "@typescript-eslint/eslint-plugin": "^7.2.0",
        "@typescript-eslint/parser": "^7.2.0",
        "eslint": "^8.57.0",
        "eslint-config-prettier": "^9.1.0",
        "prettier": "^3.2.5",
        "tsx": "^4.7.1"
    }
}


I've tried changing the url to my ip address. Still no luck. I'm using Docker locally. Any reason why this is not working. Please keep in mind I am new to Docker.

I'm using:

  • Docker 25.0.3
  • Node 21.7.1 (on my machine and on my Docker image)
  • node-fetch 3.3.2
  • TypeScript 5.4.2
  • MacOS Sonoma 14.4

To reproduce

  1. Create a Next.js app npx creat-next-app@latest

    a. Create a folder inside of app named /api/test

    b. Create a route.ts|js file with the following content:

import { NextResponse } from "next/server";

export async function GET (request: Request) {
    return NextResponse.json ({test: "Test"})
}
  1. Create a new Node.js app npm init -y

    a. Include the following package.json, tsconfig.json, and Dockerfile:

{
    "main": "index.ts",
    "scripts": {
        "start": "nodemon --exec npm run on",
        "on": "npx tsx index.ts",
        "test": "echo \"Error: no test specified\" && exit 1",
        "format:check": "prettier --check .",
        "format:write": "prettier --write .",
        "lint:check": "eslint .",
        "lint:fix": "eslint --fix ."
    },
    "type": "module",
    "dependencies": {
        "@types/dotenv": "^8.2.0",
        "discord.js": "^14.14.1",
        "dotenv": "^16.4.5",
        "node-fetch": "^3.3.2",
        "typescript": "^5.4.2"
    },
    "devDependencies": {
        "@typescript-eslint/eslint-plugin": "^7.2.0",
        "@typescript-eslint/parser": "^7.2.0",
        "eslint": "^8.57.0",
        "eslint-config-prettier": "^9.1.0",
        "prettier": "^3.2.5",
        "tsx": "^4.7.1"
    }
}

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "lib": ["es2020"],
    "declaration": true,
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "noImplicitThis": true,
    "alwaysStrict": true,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": false,
    "inlineSourceMap": true,
    "inlineSources": true,
    "experimentalDecorators": true,
    "strictPropertyInitialization": false,
    "baseUrl": ".",
    "esModuleInterop": true,
  },
  "exclude": [
    "node_modules/**/*"
  ]
}
FROM node:21.7.1

WORKDIR /

COPY package.json package.json
COPY package-lock.json package-lock.json

RUN npm install

COPY . .

CMD [ "npx", "tsx", "index.ts" ]
c. Create a file called `index.ts` with the following content:
const main = async () => {
            try {
                const rawResponse = await fetch(
                    "https://localhost:3000/api/test");
                
                
    
                const response = await rawResponse.json();
                console.info(response)
            } catch (error) {
                console.error(error);
            }
        }

        main()
  1. Build and run the app with Docker
0

There are 0 answers