Связь между двумя API, которые находятся внутри двух разных контейнеров - PullRequest
0 голосов
/ 01 мая 2020

У меня есть 2 REST API, написанных на Python (3.6). Они оба используют Flask и Swagger. Я строю 2 docker изображений для каждого из них. Затем запустите 2 docker образы, подобные этим:

$ docker run -d -p $HOST_PORT1:$APPLICATION_PORT1 --name $SERVICE_NAME1 $IMAGE1
$ docker run -d -p $HOST_PORT2:$APPLICATION_PORT2 --name $SERVICE_NAME2 $IMAGE2

Они оба работают на одном компьютере. Допустим, IP-адрес машины - PUBLIC_IP.

Когда я пытаюсь получить доступ к API по отдельности из браузера. Работает просто отлично. Использование PUBLIC_IP компьютера, на котором развернуты контейнеры, и обоих опубликованных портов. Я могу отправлять запросы и получать правильные ответы.

Однако одна конечная точка первого API должна вызывать конечную точку другого. Вот как первый API вызывает второй:

response = requests.post(url  = "http://PUBLIC_IP:APPLICATION_PORT2/v1/api/endpoint", 
                         json = {"data":s}).text

Я нацелен на PUBLIC_IP машины (оба контейнера работают на этой машине). Звонок не возвращается. Вот след звонящего:

2020-05-01T18:08:39.670173821Z <_MultiThreadedRendezvous of RPC that terminated with:
2020-05-01T18:08:39.670190663Z  status = StatusCode.UNAVAILABLE
2020-05-01T18:08:39.670202690Z  details = "failed to connect to all addresses"
2020-05-01T18:08:39.670217148Z  debug_error_string = "{"created":"@1588356519.668295801","description":"Failed to pick subchannel","file":"src/core/ext/filters/client_channel/client_channel.cc","file_line":3981,"referenced_errors":[{"created":"@1588356519.668285228","description":"failed to connect to all addresses","file":"src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc","file_line":394,"grpc_status":14}]}"

Ответы [ 2 ]

0 голосов
/ 01 мая 2020

Здесь может происходить несколько вещей. Во-первых, похоже, что вы пытаетесь получить доступ к REST API в другом контейнере, опубликовав порт на хосте, а затем подключившись к опубликованному порту. Это должно работать, но это не обязательно; если вы действительно не хотите предоставлять внешний доступ к этому API, лучше подключить один контейнер напрямую к другому. В этом случае нет необходимости публиковать sh порты.

Самый простой способ сделать это - воспользоваться преимуществами автоматического c DNS, который docker предоставляет в любой сети, отличной от используемой по умолчанию. мостовая сеть. Итак, если мы сначала создадим сеть с именем, скажем, appnet:

$ docker network create appnet

Затем присоедините наши контейнеры к этой сети:

$ docker run -d --name container0 --network appnet alpinelinux/darkhttpd
$ docker run -d --name container1 --network appnet alpinelinux/darkhttpd

Тогда контейнеры могут ссылаться на друг друга по имени , Например, если я подключаюсь к container0, я могу получить доступ к веб-службе, работающей на container1:

<code>$ docker exec -it container0 sh
/ $ wget -O- http://container1:8080
Connecting to container1:8080 (172.22.0.3:8080)
writing to stdout
<html>
<head>
 <title>/</title>
</head>
<body>
<h1>/</h1>
<tt><pre>
<a href="..">..</a>/

Или , используя requests:

<code>$ docker exec -it -u root container0 sh
/ # apk add --update python3 py3-requests
/ # python3
>>> import requests
>>> res = requests.get('http://container1:8080')
>>> res.text
'<html>\n<head>\n <title>/</title>\n</head>\n<body>\n<h1>/</h1>\n<tt><pre>\n<a href="..">..</a>/\n
\ n
\ n \ n \ n '

Тем не менее, порты публикации на вашем хосте должно работать просто отлично. Например, мой хост имеет адрес 192.168.1.200. Если вместо этого я запускаю контейнеры следующим образом:

$ docker run -d --name container0 -p 1234:8080 alpinelinux/darkhttpd
$ docker run -d --name container1 -p 4321:8080 alpinelinux/darkhttpd

Тогда я могу получить доступ к этим службам на опубликованных портах хоста, как и ожидалось:

<code>$ docker exec -it container0 sh
/ $ wget -O- http://192.168.1.200:1234
Connecting to 192.168.1.200:1234 (192.168.1.200:1234)
writing to stdout
<html>
<head>
 <title>/</title>
</head>
<body>
<h1>/</h1>
<tt><pre>
<a href="..">..</a>/

/ $ wget -O- http://192.168.1.200: 4321 Подключение к 192.168.1.200:4321 (192.168.1.200:4321) с записью в стандартный вывод /

/

<a href="..">..</a>/
0 голосов
/ 01 мая 2020

По умолчанию все контейнеры должны быть доступны по их именам. Если нет, вам нужно связать их в сети или связать их вместе. Посмотрите на параметр docker --link

Пример: docker network connect --link container1:c1 multi-host-network container2

Более подробную информацию см. В официальной docker документации здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...