Docker - Почему этот контейнер express.js с открытым / опубликованным портом отклоняет соединения? (используя boot2docker)
У меня есть простое приложение hello world express.js внутри контейнера Docker. Он настроен на работу с портом 8080, и файл Docker отображает этот порт в образе. Кроме того, я публикую порт при запуске образа. Тем не менее, когда я пытаюсь сделать простой запрос curl, соединение отклоняется. Вот как я настроил этот тест:
Мой Dockerfile довольно прост:
FROM node
ADD ./src /src
WORKDIR /src
# install your application's dependencies
RUN npm install
# replace this with your application's default port
EXPOSE 8080
# replace this with your main "server" script file
CMD [ "node", "server.js" ]
И внутри моего каталога./src у меня есть файл server.js, который выглядит так:
var express = require('express');
var app = express();
app.get('/', function(req, res){
res.send('Hello World');
});
var server = app.listen(8080, function() {
console.log('Listening on port %d', server.address().port);
});
а также базовый package.json, который выглядит так:
{
"name": "hello-world",
"description": "hello world test app",
"version": "0.0.1",
"private": true,
"dependencies": {
"express": "4.7.2"
}
}
Изображение строится просто отлично:
→ docker build -t jimjeffers/hello-world .
Sending build context to Docker daemon 1.126 MB
Sending build context to Docker daemon
Step 0 : FROM node
---> 6a8a9894567d
Step 1 : ADD ./src /src
---> 753466503fbf
Removing intermediate container 135dab70dfff
Step 2 : WORKDIR /src
---> Running in 12257ff3f990
---> 010ce4140cdc
Removing intermediate container 12257ff3f990
Step 3 : RUN npm install
---> Running in 1a9a0eb9d188
---> 5dc97c79281e
Removing intermediate container 1a9a0eb9d188
Step 4 : EXPOSE 8080
---> Running in abbaadf8709d
---> 9ed540098ed2
Removing intermediate container abbaadf8709d
Step 5 : CMD [ "node", "server.js" ]
---> Running in 63b14b5581cd
---> eababd51b50e
Removing intermediate container 63b14b5581cd
Successfully built eababd51b50e
И начинается просто отлично
→ docker run -P -d jimjeffers/hello-world
ee5024d16a679c10131d23c1c336c163e9a6f4c4ebed94ad4d2a5a66a64bde1d
→ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ee5024d16a67 jimjeffers/hello-world:latest node server.js About an hour ago Up 11 seconds 0.0.0.0:49158->8080/tcp jovial_engelbart
5d43b2dee28d mongo:2.6 /usr/src/mongo/docke 5 hours ago Up 3 hours 27017/tcp some-mongo
Я могу подтвердить, что сервер работает внутри контейнера:
→ docker logs ee5024d16a67
Listening on port 8080
Но если я попытаюсь сделать запрос, соединение будет отклонено.
→ curl -i 0.0.0.0:49158
curl: (7) Failed connect to 0.0.0.0:49158; Connection refused
Есть что-то, чего я здесь не хватает? Если я запускаю приложение без использования докера, оно работает как положено:
→ node src/server.js
Listening on port 8080
→ curl -i 0.0.0.0:8080
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 11
ETag: W/"b-1243066710"
Date: Mon, 04 Aug 2014 05:11:58 GMT
Connection: keep-alive
Hello World
2 ответа
Я узнал источник путаницы. Моя машина работает на Mac OSX, и поэтому я установил Docker с boot2docker.
Итак, снова повторим процесс:
→ docker run -P -d jimjeffers/hello-world
28431b32b93dbecaa2a8a5b129cbd36eebe8a90f4c20ab10735455d82fa9de37
→ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
28431b32b93d jimjeffers/hello-world:latest node server.js 2 hours ago Up 9 minutes 0.0.0.0:49159->8080/tcp stoic_franklin
5d43b2dee28d mongo:2.6 /usr/src/mongo/docke 6 hours ago Up 4 hours 27017/tcp some-mongo
Наконец, хитрость заключалась не в том, чтобы подключиться к моей машине, а в том, чтобы свернуться с IP-адреса виртуальной машины:
→ boot2docker ip
The VM's Host only interface IP address is: 192.168.59.103
Итак, я наконец-то добился успеха, свернув виртуальную машину:
→ curl -i 192.168.59.103:49159
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 11
ETag: W/"b-1243066710"
Date: Mon, 04 Aug 2014 04:32:37 GMT
Connection: keep-alive
Все это подробно объясняется в руководстве по установке Docker, но я пропустил его, так как оно было ближе к концу документа.
После того, как вы открыли порт в вашем файле Docker, вы также должны указать Docker, как сопоставить вашу хост-систему с вашим контейнером.
Попробуйте изменить команду запуска Docker на что-то вроде этого:
docker run -p 127.0.0.1:49158:8080 -d jimjeffers/hello-world
Тогда попробуй: curl'ing:
curl -i 127.0.0.1:49158