Докеры не открыты

Я установил простой сервер узлов в Docker.

Dockerfile

FROM node:latest
RUN apt-get -y update
ADD example.js .
EXPOSE 1337   
CMD node example.js

example.js

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n'+new Date);
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

Теперь создадим образ

$ docker build -t node_server.

Теперь запустите контейнер

$ docker run -p 1337: 1337 -d node_server
Долл. США

Убедитесь, что контейнер запущен и отображаются порты:

$ docker ps

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
5909e87302ab        node_server         "/bin/sh -c 'node exa"   7 seconds ago       Up 6 seconds        0.0.0.0:1337->1337/tcp   grave_goldberg

Теперь добавьте в контейнер и убедитесь, что сервер запущен внутри:

$ docker exec -it 5909e87302ab7520884060437e19ef543ffafc568419c04630abffe6ff731f70/bin/bash

И в командной строке контейнера введите:

[email protected]:/# curl http://localhost:1337
Hello World
Mon Feb 15 2016 16:28:38 GMT+0000 (UTC)

Выглядит хорошо?

Проблема

Когда я выполняю ту же команду curl на хосте (или перемещаюсь с моим браузером на http://localhost: 1337), я ничего не вижу.

Любая идея, почему сопоставление портов между контейнером и хостом не работает?

Вещи, которые я уже пробовал:

  • Запуск с --expose 1337

Ответы

Ответ 1

Ваши порты отображаются правильно, но ваш сервер прослушивает соединения на 127.0.0.1 внутри вашего контейнера:

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n'+new Date);
}).listen(1337, '127.0.0.1');

Вам нужно запустить сервер следующим образом:

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n'+new Date);
}).listen(1337, '0.0.0.0');

Обратите внимание на 0.0.0.0 вместо 127.0.0.1.

Ответ 2

Добавление EXPOSE 1337 в файл докеров

EXPOSE обязательное если вы хотите "выставить" этот порт в другие контейнеры.

Как комментирует BMitch:

Expose не требуется для публикации порта или для подключения контейнера к контейнеру через общую сеть докеров.
Это метаданные для публикации всех портов с помощью -P и проверки изображения/контейнера.

Так:

Запуск с --expose 1337

Не совсем: вам нужно докер запустить его с -P 1337:1337

Вам нужно:

  • постройте изображение с директивой EXPOSE в нем (используется -P)
  • или запустить его с портом, опубликованным на хосте -P 1337:1337

Тестовый curl http://localhost:1337 было сделано из контейнера (нет EXPOSE или публикации).
Если вы хотите, чтобы он работал с хостом Linux, вам нужно EXPOSE+-P или вам нужно -P 1337:1337.
Или.

Заявить, что он разоблачен в одиночку, хорошо для документирования намерения, но не делает ничего в одиночку.

Например:

/img/0d72ae2daacfe4fc3a8231cd1493f43b.png

На этой фигуре 8080 EXPOSE'd, опубликованной на хосте Linux 8888.
И если этот хост Linux не является фактическим хостом, тот же порт должен быть быстро перенесен на фактический хост. См. " Как получить доступ к tomcat в контейнере докера из браузера? ".

Если localhost не работает с хостом Linux, попробуйте его IP-адрес:

CID=$(docker run -p 1337:1337 -d node_server)
CIP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${CID})
curl http://${CIP}:1337

Или, как упоминалось выше, заставьте ваш сервер прослушивать соединения, исходящие от любого IP: 0.0.0.0 который является широковещательным адресом или нулевой сетью.