Search code examples
windowsdockerdockerfiledocker-network

Docker, Windows 11 - How can I access localhost in a docker container from host?


Summary

  • I'm trying to set up a Docker container to run an app on http://localhost:3000
  • My container in Windows runs, but I don't get any response when accessing http://localhost:3000
  • I would like to find out how to access http://localhost:3000 from my browser outside of the docker container please

Configuration

DockerFile

FROM node:20

WORKDIR /code
COPY app.js /code/app.js

EXPOSE 3000

ENTRYPOINT [ "node", "/code/app.js", "-l", "-c" ]

app.js

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Build Image:

docker image build -t node-temp .

Run Container:

docker container run --rm -it -p 3000:3000 --name node-temp-container node-temp

It shows:

Server running at http://127.0.0.1:3000/

Problem:

But this is what I get when I access it from my browser. (Ignore the image requests, they are just some google dinosaur icons)

enter image description here

Note:

I get "Hello World" when running exec

docker container exec -it node-temp-container curl http://localhost:3000
Hello World

docker container inspect node-temp-container

[
    {
        "Id": "0bbdd48455c6600dc9fa6256f91c1bd30ae8e49b0e641949c00c10f7c11a51f0",
        "Created": "2023-07-09T13:29:25.113334992Z",
        "Path": "node",
        "Args": [
            "/code/app.js",
            "-l",
            "-c"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 10523,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2023-07-09T13:29:29.399906481Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:724b009dc9067af9a7b35eda3f95cc54ff12f50a285ff38fa50d32a0cf31b697",
        "ResolvConfPath": "/var/lib/docker/containers/0bbdd48455c6600dc9fa6256f91c1bd30ae8e49b0e641949c00c10f7c11a51f0/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/0bbdd48455c6600dc9fa6256f91c1bd30ae8e49b0e641949c00c10f7c11a51f0/hostname",
        "HostsPath": "/var/lib/docker/containers/0bbdd48455c6600dc9fa6256f91c1bd30ae8e49b0e641949c00c10f7c11a51f0/hosts",
        "LogPath": "/var/lib/docker/containers/0bbdd48455c6600dc9fa6256f91c1bd30ae8e49b0e641949c00c10f7c11a51f0/0bbdd48455c6600dc9fa6256f91c1bd30ae8e49b0e641949c00c10f7c11a51f0-json.log",
        "Name": "/node-temp-container",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {
                "3000/tcp": [
                    {
                        "HostIp": "",
                        "HostPort": "3000"
                    }
                ]
            },
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": true,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "ConsoleSize": [
                89,
                178
            ],
            "CapAdd": null,
            "CapDrop": null,
            "CgroupnsMode": "host",
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": [],
            "BlkioDeviceWriteBps": [],
            "BlkioDeviceReadIOps": [],
            "BlkioDeviceWriteIOps": [],
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/0d809c1293fffedf337773da406bd79fea8790d15c8afbd5954e9379ae58e086-init/diff:/var/lib/docker/overlay2/p14b2jt8c0wy4viexwn1ng3p0/diff:/var/lib/docker/overlay2/44pxwvm3lf1m78yno7zkn4ayn/diff:/var/lib/docker/overlay2/a52e4f60ff3f1d8743a73f55171951ac3db32653bb2b72be8f7a2ba202cc5e60/diff:/var/lib/docker/overlay2/2cc4aee08b2995aa3326ed2e7323cb30a57eed60bd11568d80ff974a411d95c2/diff:/var/lib/docker/overlay2/6bf164e32d1d2c11dc6903198cc538465bf9201b8218a5d09064a4769e2ce479/diff:/var/lib/docker/overlay2/4684a5c8dce524e9a8bd11195affe7a7c5577c58e298a40ea4c1fd22a16d7e14/diff:/var/lib/docker/overlay2/b4e94897f778e922f01bef76f02551c1227323aeed5082f3014b6ef158afb274/diff:/var/lib/docker/overlay2/86847656ba4eb5d0e1ab5ad89bf9c92e333631f79205c10a49afcbc52493d0a7/diff:/var/lib/docker/overlay2/82fb9f9033d02fcbaea0edcc33126f5dc54c5d4d28a8e26d9beb609432425383/diff:/var/lib/docker/overlay2/523acd47c7904aca441e6a8daf793a4757a6a4368f6fe58e98fd4ffd6e717259/diff",
                "MergedDir": "/var/lib/docker/overlay2/0d809c1293fffedf337773da406bd79fea8790d15c8afbd5954e9379ae58e086/merged",
                "UpperDir": "/var/lib/docker/overlay2/0d809c1293fffedf337773da406bd79fea8790d15c8afbd5954e9379ae58e086/diff",
                "WorkDir": "/var/lib/docker/overlay2/0d809c1293fffedf337773da406bd79fea8790d15c8afbd5954e9379ae58e086/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "0bbdd48455c6",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "3000/tcp": {}
            },
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "NODE_VERSION=20.3.1",
                "YARN_VERSION=1.22.19"
            ],
            "Cmd": null,
            "Image": "node-temp",
            "Volumes": null,
            "WorkingDir": "/code",
            "Entrypoint": [
                "node",
                "/code/app.js",
                "-l",
                "-c"
            ],
            "OnBuild": null,
            "Labels": {}
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "7ccc4b679d0827b61f25dc7102396e8be5cee53cd9cdaf74279613d74542a9bf",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
                "3000/tcp": [
                    {
                        "HostIp": "0.0.0.0",
                        "HostPort": "3000"
                    }
                ]
            },
            "SandboxKey": "/var/run/docker/netns/7ccc4b679d08",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "3beb1faa5fbd8b0308577e2076267a44866701b34f6b7057e8e85ed992cd7456",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "abad347ccca84500ade5564fcc045e47a497ae1cf666d5403855e7f93d351cb1",
                    "EndpointID": "3beb1faa5fbd8b0308577e2076267a44866701b34f6b7057e8e85ed992cd7456",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]

docker network inspect bridge

[
    {
        "Name": "bridge",
        "Id": "abad347ccca84500ade5564fcc045e47a497ae1cf666d5403855e7f93d351cb1",
        "Created": "2023-07-08T08:59:39.380269538Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "0bbdd48455c6600dc9fa6256f91c1bd30ae8e49b0e641949c00c10f7c11a51f0": {
                "Name": "node-temp-container",
                "EndpointID": "3beb1faa5fbd8b0308577e2076267a44866701b34f6b7057e8e85ed992cd7456",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

Environment

Test Installation

The installation is fine because it works when running the below:

  • docker pull nginx
  • docker container run -p 80:80 --name nginx-container nginx
  • Open (in host browser) http://localhost

This proves that I must have something wrong in my setup, because I can run the default nginx container, and access it from my browser outside of docker.


I basically want to set up a docker container for my dev environment of an app, but I can't access my app if it runs in a Docker container.

Any help would be really appreciated.


Solution

  • Please, be sure that node is listening in every network interface, not the container specific one.

    Basically, in a standalone container, it means ensuring that node is listening for requests on 0.0.0.0.

    The way in which this behavior should be configured depends on the actual server side framework you are using.

    As exemplified in the nodejs documentation, if using express, for instance, you need to perform something similar to the following:

    'use strict';
    
    const express = require('express');
    
    // Constants
    const PORT = 8080;
    const HOST = '0.0.0.0';
    
    // App
    const app = express();
    app.get('/', (req, res) => {
      res.send('Hello World');
    });
    
    app.listen(PORT, HOST, () => {
      console.log(`Running on http://${HOST}:${PORT}`);
    });