<p>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 <code>4000</code>. When I create docker image and run a container, I can't access it from <code>localhost:4000</code> on my machine, but I can see that docker got to <code>node index.js</code> command correctly and app is running without any errors.</p>

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

<p>I'm struggling to understand what I missed and why it only works locally.</p>

<p>NodeJS app</p>

<pre><code>import fastify from 'fastify';

const server = fastify();

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

server.listen(4000, error =&gt; {
  if (error) {
    process.exit(1);
  }
});
</code></pre>

<p>Dockerfile</p>

<pre><code>FROM node:14.2-alpine

WORKDIR /app

COPY package.json yarn.lock /app/

RUN yarn

COPY . .

EXPOSE 4000

CMD ["node", "index.js"]
</code></pre>

<p>Kubernetes manifest</p>

<pre><code>---
# 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
</code></pre>

<p>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 ebcause of the fact that <code>fastify</code> by default only listen to <code>localhost</code>.</p>

<pre><code>docker build -t development-actions:latest .
docker run -it -p 4000:4000 development-actions:latest
</code></pre>

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

<pre><code>const server = require('fastify')({ logger: true })

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

server.listen(4000, '0.0.0.0', error =&gt; {
  if (error) {
    process.exit(1);
  }
});
</code></pre>

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

<p>Reference:</p>

<ol>
<li><a href="https://www.fastify.io/docs/latest/Getting-Started/#your-first-server" rel="noreferrer">https://www.fastify.io/docs/latest/Getting-Started/#your-first-server</a></li>
</ol>
