Fastify not working on Docker / Kubernetes
Asked Answered
I

4

20

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
Infantine answered 15/5, 2020 at 15:5 Comment(0)
C
46

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
Conductor answered 15/5, 2020 at 15:59 Comment(2)
That was it! Thank you, was stuck with it for a whileInfantine
that actually saved my day!Aboulia
P
15

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}`);
});
Proem answered 10/4, 2023 at 2:20 Comment(0)
L
1

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.

Launderette answered 22/6, 2023 at 16:31 Comment(0)
D
-2

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}`)
})
Db answered 19/4, 2024 at 20:43 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.