У меня возникли проблемы с взаимодействием двух контейнеров Docker друг с другом с помощью Docker Compose. В попытке свести проблему к наименьшему воспроизводимому примеру я создал следующие три файла:
docker-compose.yml
services:
db:
build: webSQL
ports:
- "3000:3000"
client-test:
build: clientTest
веб-SQL/Dockerfile
FROM ubuntu
RUN apt update
RUN apt install netcat-traditional
RUN nc -l 3000
клиентТест/Докерфайл
FROM ubuntu
RUN apt update
RUN apt install curl -y
RUN curl -X "hello" http://db:3000
Когда я запускаю docker-compose up в каталоге, содержащем файл docker-compose.yml, я получаю следующий результат:
[+] Building 4.1s (11/11) FINISHED docker:default
=> [client-test internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 131B 0.0s
=> [db internal] load metadata for docker.io/library/ubuntu:latest 0.0s
=> [client-test internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [db internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 122B 0.0s
=> [db 1/4] FROM docker.io/library/ubuntu:latest 0.0s
=> CACHED [db 2/4] RUN apt update 0.0s
=> CACHED [client-test 3/4] RUN apt install curl -y 0.0s
=> ERROR [client-test 4/4] RUN curl -X "hello" http://db:3000 4.0s
=> [db internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> CACHED [db 3/4] RUN apt install netcat-traditional 0.0s
=> CANCELED [db 4/4] RUN nc -l 3000 4.0s
------
> [client-test 4/4] RUN curl -X "hello" http://db:3000:
0.641 % Total % Received % Xferd Average Speed Time Time Time Current
0.641 Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- 0:00:02 --:--:-- 0curl: (6) Could not resolve host: db
------
failed to solve: process "/bin/sh -c curl -X \"hello\" http://db:3000" did not complete successfully: exit code: 6
Насколько я понимаю Docker Compose, каждый контейнер может автоматически отправлять запросы ко всем остальным контейнерам в одном и том же файле Docker Compose. (Предполагая, что вы не указываете разные сети для запуска контейнеров) Что я делаю неправильно?


Вы пытаетесь RUN выполнить две команды, которые задействуют сеть как часть построения образа. Во время сборки вы вообще не можете подключаться к другим контейнерам.
Если вы измените их на CMD
CMD nc -l 3000
CMD curl -X "hello" http://db:3000
тогда они будут выполняться как основные команды контейнера, когда Compose запускает контейнеры. В этот момент они будут подключены к общей сети, и эта настройка должна работать (до того момента, пока вы не сможете ввести HTTP-ответ в nc).
В примере вы назвали серверный контейнер db. Наиболее распространенным следствием такой настройки является то, что вы не можете выполнять миграцию базы данных или начальные данные во время сборки образа. В типичных установках используется сценарий-оболочка точки входа для запуска миграции при каждом запуске или вручную docker-compose run миграции. Как вы выполняете миграцию базы данных Django при использовании Docker-Compose? есть примеры обеих техник.
RUN операторы выполняются во время сборки. Во время сборки сеть Docker недоступна, и вы не можете подключиться к другим контейнерам.
Сеть Docker настраивается во время выполнения, и именно в этот момент контейнеры могут подключаться друг к другу.
Чтобы указать команду, которая выполняется во время выполнения, вы используете оператор ENTRYPOINT вместе с оператором CMD.
Если у вас есть контейнеры, которые зависят от других контейнеров, вы можете указать эту связь в операторах depends_on в файле Docker Compose. Обратите внимание, что depends_on ждет только запуска контейнеров. Не для того, чтобы контейнеры были готовы к подключениям. Часто контейнеры, такие как базы данных, выполняют некоторую работу при запуске и не сразу доступны для подключений.
Чтобы исправить ваши настройки, мы можем добавить depends_on в ваш файл компоновки.
services:
db:
build: webSQL
ports:
- "3000:3000"
client-test:
build: clientTest
depends_on:
- db
И ваш Dockerfile базы данных
FROM ubuntu
RUN apt update
RUN apt install netcat-traditional
CMD nc -l 3000
И ваш клиентTest Dockerfile
FROM ubuntu
RUN apt update
RUN apt install curl -y
CMD curl -X "hello" http://db:3000
Для меня это имеет большой смысл. Однако попробовали ли вы предложенное исправление? Я попробовал, и он все еще не работает, хотя, по крайней мере, он выходит из строя с другой ошибкой. Теперь я получаю «client-test-1 | curl: (7) Не удалось подключиться к порту базы данных 3000 через 1 мс: не удалось подключиться к серверу. Client-test-1 завершился с кодом 7»
Да, я попробовал это, чтобы убедиться, что он может разрешить хост, о котором был ваш вопрос. Если у вас возникла новая, другая проблема, вам следует создать новый вопрос.
Но как бы то ни было, ваша команда nc кажется неправильной. Я получил это для работы nc -l -p 3000. Без -p он жалуется, что не понимает 3000 и вместо этого слушает случайный порт. Я также изменил -X на -d в команде завитка.
Возможно, при запуске хост базы данных еще не запущен, поэтому его также невозможно разрешить. Я думаю, если вы запустите их отдельно с достаточным временем между ними, сначала db, а затем клиентский тест, это сработает. Объявите зависимости и надлежащую проверку работоспособности, чтобы сделать это более надежным.