Search code examples
node.jsdockerkubernetesdigital-oceanfastify

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

Solution

  • 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