Short story
There is a common docker issue when running existing services that listen on localhost.
We put the app in the container, forward the port, but not service is available on the host.
The service runs fine when running outside docker.
It can happen if the service is listening on localhost
instead of 0.0.0.0
interface.
Long story
Let's say we have a simple webserver, listening on localhost.
const http = require("http");
http
.createServer(function (req, res) {
res.writeHead(200, { "Content-Type": "application/json" });
res.end('{"version": 42 }');
})
.listen(3030, "localhost");
We write a Dockerfile, that encapsulates this service.
FROM node:lts-alpine3.11
COPY ./server.js /app/server.js
CMD [ "node", "/app/server.js" ]
We build a docker image and run it, call the service, but the server returns Connection reset by peer
.
> docker build -t mockserver .
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM node:lts-alpine3.11
---> 927d03058714
Step 2/3 : COPY ./server.js /app/server.js
---> Using cache
---> 517a41b32afc
Step 3/3 : CMD [ "node", "/app/server.js" ]
---> Using cache
---> 2cef59dd0b9e
Successfully built 2cef59dd0b9e
Successfully tagged mockserver:latest
> docker run -p 3030:3030 mockserver &
> curl http://localhost:3030/health
curl: (56) Recv failure: Connection reset by peer
We launch the service on the host and it works fine.
node server.js &
> curl http://localhost:3030/health
{"version": 42 }⏎
> kill %1
The issue is a rather insidious one. The fix is to change the server to listen on 0.0.0.0
instead of localhost
.
const http = require("http");
http
.createServer(function (req, res) {
res.writeHead(200, { "Content-Type": "application/json" });
res.end('{"version": 42 }');
})
.listen(3030, "0.0.0.0");
We rebuild the docker image, relaunch it, and everything works.
> docker build -t mockserver .
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM node:lts-alpine3.11
---> 927d03058714
Step 2/3 : COPY ./server.js /app/server.js
---> Using cache
---> b5c0956c4cc6
Step 3/3 : CMD [ "node", "/app/server.js" ]
---> Using cache
---> f7f998801c5b
Successfully built f7f998801c5b
Successfully tagged mockserver:latest
> docker run -p 3030:3030 mockserver &
> curl http://localhost:3030/health
{"version": 42 }