Containe runs locally on port 80, but crashes on Kubernetes

7/30/2021

I have an image, which is a simple web server running on port 80. When I run it locally, I get:

The app is listening at http://localhost:80

and everything is fine.

However, when I deploy the following to K8s, it crashes constantly.

Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: apps
  labels:
    app: my-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: myimage:dev
        imagePullPolicy: Always
        ports:
        - containerPort: 80

Logs of one of the pods:

node:events:371
throw er; // Unhandled 'error' event
^

Error: listen EACCES: permission denied 0.0.0.0:80
at Server.setupListenHandle [as _listen2] (node:net:1298:21)
at listenInCluster (node:net:1363:12)
at Server.listen (node:net:1450:7)
at Function.listen (/app/node_modules/express/lib/application.js:618:24)
at Object.<anonymous> (/app/index.js:17:5)
at Module._compile (node:internal/modules/cjs/loader:1095:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1124:10)
at Module.load (node:internal/modules/cjs/loader:975:32)
at Function.Module._load (node:internal/modules/cjs/loader:816:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:79:12)
Emitted 'error' event on Server instance at:
at emitErrorNT (node:net:1342:8)
at processTicksAndRejections (node:internal/process/task_queues:83:21) {
code: 'EACCES',
errno: -13,
syscall: 'listen',
address: '0.0.0.0',
port: 80
}

Why my image is able to run successfully on my local machine, and it fails on the Kubernetes?

-- mnj
kubernetes
networking
node.js

1 Answer

8/2/2021

Non-root users (non privileged) can't open a listening socket on ports below 1024.

You can find the solution here:

Remember, we do NOT want to run your applications as the root user, but there is a hitch: your safe user does not have permission to use the default HTTP port (80). You goal is to be able to publish a website that visitors can use by navigating to an easy to use URL like http://example.com.

Unfortunately, unless you sign on as root, you’ll normally have to use a URL like http://example.com:3000 - notice the port number.

A lot of people get stuck here, but the solution is easy. There a few options but this is the one I like. Type the following commands:

sudo apt-get install libcap2-bin
sudo setcap cap_net_bind_service=+ep /usr/local/bin/node

You can also see this similar question.

-- Mikołaj Głodziak
Source: StackOverflow