Контейнеры Docker в одной сети не могут получить доступ к открытым портам друг друга (Linux)
Вот довольно простой докерский стек, который я развернул:
version: "3"
services:
mysql:
environment:
- MYSQL_ROOT_PASSWORD=welcome
- MYSQL_DATABASE=db1
- MYSQL_USER=dbuser
- MYSQL_PASSWORD=welcome
- MYSQL_ROOT_HOST=*
- MYSQL_LOG_CONSOLE=true
image: mysql/mysql-server:latest
deploy:
replicas: 1
restart_policy:
condition: on-failure
ports:
- "3306:3306"
networks:
- test_net
repository:
environment:
- DB_USER=dbuser
- DB_PASSWORD=welcome
- DB_HOST=mysql
- DB_PORT=3306
image: private_repo/repository-service:0.1.3
deploy:
replicas: 1
restart_policy:
condition: on-failure
ports:
- "9091:80"
networks:
- test_net
deployment:
environment:
- DB_USER=dbuser
- DB_PASSWORD=welcome
- DB_HOST=mysql
- DB_PORT=3306
image: private_repo/deployment-service:0.1.3
deploy:
replicas: 1
restart_policy:
condition: on-failure
ports:
- "9092:80"
networks:
- test_net
networks:
test_net:
После развертывания стека докеров я вижу работающие сервисы. Однако, когда я пытаюсь получить доступ к API REST хранилища или службы развертывания из программы на хост- системе, такой как Postman, это не работает (соединение просто зависает). Итак, я сделал некоторую отладку:
1) Контейнеры могут пинговать друг друга в оверлейной сети, используя имена сервисов. Например
docker exec -i edb7432cdb64 ping mysql
PING mysql (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2 (10.0.0.2): icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from 10.0.0.2 (10.0.0.2): icmp_seq=2 ttl=64 time=0.065 ms
64 bytes from 10.0.0.2 (10.0.0.2): icmp_seq=3 ttl=64 time=0.058 ms
64 bytes from 10.0.0.2 (10.0.0.2): icmp_seq=4 ttl=64 time=0.083 ms
64 bytes from 10.0.0.2 (10.0.0.2): icmp_seq=5 ttl=64 time=0.062 ms
2) Из одного контейнера я могу использовать curl для доступа к другому контейнеру, но только через внутренний порт.
Например это работает:
docker exec -i edb7432cdb64 curl http://models:80/services/v1/models
Но это возвращает ошибку:
docker exec -i edb7432cdb64 curl http://models:9091/services/v1/models
curl: (7) Failed connect to models:9091; Connection refused
3) Похоже, что в сети наложения отсутствует информация:
docker inspect tf0z2ht7tfhe
[
{
"Name": "repository2_test_net",
"Id": "tf0z2ht7tfhefrcqvh4g0a2zq",
"Created": "0001-01-01T00:00:00Z",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "",
"Options": null,
"Config": null
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": null,
"Options": {
"com.docker.network.driver.overlay.vxlanid_list": "4097"
},
"Labels": {
"com.docker.stack.namespace": "repository2"
}
}
]
Когда я пытаюсь развернуть этот точный стек на моем Mac, это работает! И тот же осмотр оверлейной сети гораздо более информативен. С одной стороны, он показывает список контейнеров, а также дает мне подсеть и шлюз.
Каким-то образом на моей машине с Linux сеть для оверлеев настроена не совсем правильно. Я не уверен, какую конфигурацию я мог пропустить, хотя. Похоже, нет большой разницы между стеком док-станции / роем для Mac и стеком док-станции / роем для Linux. Любые указатели относительно того, что посмотреть или попробовать дальше будут очень цениться.
docker -v
Docker version 17.06.2-ol, build d02b7ab
2 ответа
Таким образом, кажется, что, хотя я не могу получить доступ к сервисам, например, с помощью localhost: 9091, я могу получить к ним доступ, используя адрес менеджера роя
swarm init
Swarm initialized: current node (a5aiio3xh1qfpnw6gf8keam4y) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-2e1yxt76ui6syrk2p4970hns25n57tquvprxn1l160vnrk0bog-bi10m0b0jcz54cv17pd469a26 10.*.*.*:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Я могу получить доступ к своему сервису в 10.. *:9091. Не уверен, почему это происходит только в Linux или есть ли способ использовать localhost в этой конфигурации. Но пока это работает.
Сопоставление портов влияет только на хост (или в вашем случае, я полагаю, менеджер роя). В определенной пользователем сети контейнеры видят только фактические порты друг друга. Если вы хотите получить доступ к некоторому контейнеру через порт, который вы указали на вашем хосте, вам нужно использовать IP-адрес хоста: docker exec -i edb7432cdb64 curl http://<Swarm manager IP>:9091/services/v1/models
, Но это было бы довольно неловко и довольно бесполезно.