node.jsdockerdockerfiledocker-image

Docker Image: why page not accessible?


I am trying to create a Docker image for a little API I built with Fastify and Node. I came up with the following Dockerfile:

FROM node:current-alpine3.19

WORKDIR /usr/src/app

RUN chown -R node:node /usr/src/app

COPY src/package.json ./
COPY src/package-lock.json ./

RUN npm install

USER node

COPY --chown=node:node ./src .

CMD [ "npm", "start" ]

The build worked and I started the container with "docker run -p 3000:3000 [my-project]".

The file structure seems to be correct and I get the expected response when trying "wget 127.0.0.1:3000" inside the container.

But I can't open the page from my PC with localhost:3000 or 127.0.0.1:3000. Firefox: "The connection to the server was reset while the page was loading." Curl: "curl: (56) Recv failure: Connection reset by peer"

Fastify runs under port 3000, port 3000 is also used in the "docker run" command and I open the page with port 3000.

What am I doing wrong?


Solution

  • You need to accept connections from 0.0.0.0 because 127.0.0.1 references the container and not the host.

    So, for example, supposing that your project looks like this (very simplified!):

    ├── Dockerfile
    └── src
        ├── index.js
        ├── package.json
        └── package-lock.json
    

    then your index.js might be:

    const fastify = require('fastify')({
        logger: true
      });
      
      fastify.get('/', async (request, reply) => {
        return { hello: 'world' }
      });
      
      const start = async () => {
        try {
          await fastify.listen({ port: 3000, host: '0.0.0.0' });
          console.log(`Server is running at ${fastify.server.address().port}`);
        } catch (err) {
          fastify.log.error(err);
          process.exit(1);
        }
      }
      start();
    

    The important bit is specifying host: '0.0.0.0' to fastify.listen(). You also need to share this port with the host when you do docker run by giving -p 3000:3000.

    enter image description here