Ilja
Ilja

Reputation: 46519

Fastify not working on Docker / Kubernetes

I have very simple app that returns "Hello World" string, it works fine locally. As you will see from app code below it runs on port 4000. When I create docker image and run a container, I can't access it from localhost:4000 on my machine, but I can see that docker got to node index.js command correctly and app is running without any errors.

I also tried to deploy it to Kubernetes cluster, when I access load balancer ip I get ERR_EMPTY_RESPONSE. After inspecting this app through kubectl I can see that everything is running fine, image was downloaded and pod is running.

I'm struggling to understand what I missed and why it only works locally.

NodeJS app

import fastify from 'fastify';

const server = fastify();

server.get('/', (_request, reply) => {
   reply.status(200).send("Hello World");
});

server.listen(4000, error => {
  if (error) {
    process.exit(1);
  }
});

Dockerfile

FROM node:14.2-alpine

WORKDIR /app

COPY package.json yarn.lock /app/

RUN yarn

COPY . .

EXPOSE 4000

CMD ["node", "index.js"]

Kubernetes manifest

---
# Load balancer
apiVersion: v1
kind: Service
metadata:
  name: development-actions-lb
  annotations:
    service.beta.kubernetes.io/do-loadbalancer-name: "development-actions-lb"
    service.beta.kubernetes.io/do-loadbalancer-algorithm: "round_robin"
spec:
  type: LoadBalancer
  selector:
    app: development-actions
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 4000
---
# Actions deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: development-actions
spec:
  replicas: 1
  selector:
    matchLabels:
      app: development-actions
  template:
    metadata:
      labels:
        app: development-actions
    spec:
      containers:
        - image: registry.digitalocean.com/myapp/my-image:latest
          name: development-actions
          ports:
            - containerPort: 4000
              protocol: TCP
      imagePullSecrets:
        - name: registry-myapp

Upvotes: 21

Views: 10340

Answers (5)

Aditya
Aditya

Reputation: 468

Yes after hours of troubleshooting with my team we we have to manually bind the IP address over here we tried adding it via both ways IPv4 and IPv6

app.listen((configService.get('SERVER_PORT') | 3000), "0.0.0.0"); -> For IPV4

app.listen((configService.get('SERVER_PORT') | 3000), "::"); -> For IPv6

Upvotes: 0

Ali Mansoori
Ali Mansoori

Reputation: 1

Try it:

server.listen({port: 4000, host: "0.0.0.0"}, (err: Error|null, address: 
    string) => {
        if (err) {
            console.error(err)
            process.exit(1)
        }
        console.log(`Server listening at ${address}`)
})

Upvotes: -2

irvifa
irvifa

Reputation: 2083

First when I tried your code, I try it using a local docker but the behavior is just the same, so I expect it to be because of the fact that fastify by default only listen to localhost.

docker build -t development-actions:latest .
docker run -it -p 4000:4000 development-actions:latest

Inside of Docker you should mentioned explicitly '0.0.0.0' since By default fastify is istening only on the localhost 127.0.0.1 interface. To listen on all available IPv4 interfaces the example should be modified to listen on 0.0.0.0 like so I change it to the following:

const server = require('fastify')({ logger: true })

server.get('/', (_request, reply) => {
   reply.status(200).send("Hello World");
});

server.listen(4000, '0.0.0.0', error => {
  if (error) {
    process.exit(1);
  }
});

The rest should be the same. To try it locally you can do it by using:

Reference:

  1. https://www.fastify.io/docs/latest/Getting-Started/#your-first-server

Upvotes: 47

Fred Peixoto
Fred Peixoto

Reputation: 51

I solved my problem setting host variable as '0.0.0.0' on fastify.listen({port:3000, host: '0.0.0.0'}, () -> {}) and everything worked fine.

Upvotes: 2

rodo
rodo

Reputation: 913

If you're reading this after 2023, the API has changed. Try:

fastify.listen({ port: 4000, host: '0.0.0.0' }, (err, address) => {
  if (err) {
    console.error(err);
    process.exit(1);
  }
  console.info(`Server listening on ${address}`);
});

Upvotes: 18

Related Questions