Использование хоста ip в docker-compose
Я хочу создать файл docker-compose, который может работать на разных серверах.
Для этого я должен иметь возможность указать host-ip или имя хоста сервера (где все контейнеры запущены) в нескольких местах в docker-compose.yml.
например. для контейнера consul, где я хочу определить, как сервер может быть найден другими контейнерами consul.
consul:
image: progrium/consul
command: -server -advertise 192.168.1.125 -bootstrap
Я не хочу явно указывать 192.168.1.125.
Я мог бы использовать env_file:, чтобы указать имя хоста или ip и принять его на каждом сервере, поэтому у меня есть эта информация в одном месте и используйте ее в файле docker-compose.yml. Но это можно использовать только для спецификаций среды, а не для параметра рекламы.
Есть ли лучшее решение?
Ответы
Ответ 1
Есть ли лучшее решение?
Абсолютно! Вам не нужен IP-адрес хоста для связи между контейнерами. Если вы link
контейнеры в вашем файле docker-compose.yaml
, у вас будет доступ к ряду переменных среды, которые вы можете использовать для обнаружения IP-адресов ваших служб.
Рассмотрим, например, конфигурацию с помощью докеры с двумя контейнерами: одну с помощью consul
, а одну - с некоторой службой, с которой нужно поговорить с консулом.
consul:
image: progrium/consul
command: -server -bootstrap
webserver:
image: larsks/mini-httpd
links:
- consul
Во-первых, начиная с consul
только с -server -bootstrap
, consul
определяет свой собственный рекламный адрес, например:
consul_1 | ==> Consul agent running!
consul_1 | Node name: 'f39ba7ef38ef'
consul_1 | Datacenter: 'dc1'
consul_1 | Server: true (bootstrap: true)
consul_1 | Client Addr: 0.0.0.0 (HTTP: 8500, HTTPS: -1, DNS: 53, RPC: 8400)
consul_1 | Cluster Addr: 172.17.0.4 (LAN: 8301, WAN: 8302)
consul_1 | Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false
consul_1 | Atlas: <disabled>
В контейнере webserver
мы находим следующие переменные среды, доступные для pid 1:
CONSUL_PORT=udp://172.17.0.4:53
CONSUL_PORT_8300_TCP_START=tcp://172.17.0.4:8300
CONSUL_PORT_8300_TCP_ADDR=172.17.0.4
CONSUL_PORT_8300_TCP_PROTO=tcp
CONSUL_PORT_8300_TCP_PORT_START=8300
CONSUL_PORT_8300_UDP_END=udp://172.17.0.4:8302
CONSUL_PORT_8300_UDP_PORT_END=8302
CONSUL_PORT_53_UDP=udp://172.17.0.4:53
CONSUL_PORT_53_UDP_ADDR=172.17.0.4
CONSUL_PORT_53_UDP_PORT=53
CONSUL_PORT_53_UDP_PROTO=udp
CONSUL_PORT_8300_TCP=tcp://172.17.0.4:8300
CONSUL_PORT_8300_TCP_PORT=8300
CONSUL_PORT_8301_TCP=tcp://172.17.0.4:8301
CONSUL_PORT_8301_TCP_ADDR=172.17.0.4
CONSUL_PORT_8301_TCP_PORT=8301
CONSUL_PORT_8301_TCP_PROTO=tcp
CONSUL_PORT_8301_UDP=udp://172.17.0.4:8301
CONSUL_PORT_8301_UDP_ADDR=172.17.0.4
CONSUL_PORT_8301_UDP_PORT=8301
CONSUL_PORT_8301_UDP_PROTO=udp
CONSUL_PORT_8302_TCP=tcp://172.17.0.4:8302
CONSUL_PORT_8302_TCP_ADDR=172.17.0.4
CONSUL_PORT_8302_TCP_PORT=8302
CONSUL_PORT_8302_TCP_PROTO=tcp
CONSUL_PORT_8302_UDP=udp://172.17.0.4:8302
CONSUL_PORT_8302_UDP_ADDR=172.17.0.4
CONSUL_PORT_8302_UDP_PORT=8302
CONSUL_PORT_8302_UDP_PROTO=udp
CONSUL_PORT_8400_TCP=tcp://172.17.0.4:8400
CONSUL_PORT_8400_TCP_ADDR=172.17.0.4
CONSUL_PORT_8400_TCP_PORT=8400
CONSUL_PORT_8400_TCP_PROTO=tcp
CONSUL_PORT_8500_TCP=tcp://172.17.0.4:8500
CONSUL_PORT_8500_TCP_ADDR=172.17.0.4
CONSUL_PORT_8500_TCP_PORT=8500
CONSUL_PORT_8500_TCP_PROTO=tcp
Существует набор переменных для каждого порта EXPOSE
d с помощью consul
образ. Например, во втором изображении мы могли бы взаимодействовать с API-интерфейсом консула, подключаясь к:
http://${CONSUL_PORT_8500_TCP_ADDR}:8500/
Ответ 2
С новой версией Docker Compose (1.4.0) вы сможете сделать что-то вроде этого:
Докер-compose.yml
consul:
image: progrium/consul
command: -server -advertise HOSTIP -bootstrap
bash
$ sed -e "s/HOSTIP/${HOSTIP}/g" docker-compose.yml | docker-compose --file - up
Это благодаря новой функции:
-
Compose теперь может читать конфигурацию YAML со стандартного ввода, а не из файла, указывая - как имя файла. Это упрощает динамическое создание конфигурации:
$ echo 'redis: {"image": "redis"}' | docker-compose --file - up
Ответ 3
docker-compose позволяет использовать переменные среды из среды, выполняющей команду compose.
См. документацию на https://docs.docker.com/compose/compose-file/#variable-substitution
Предполагая, что вы можете создать оболочку script, например, предложенную @balver, вы можете установить переменную среды с именем EXTERNAL_IP
, которая будет включать значение $(docker-machine ip)
.
Пример:
#!/bin/sh
export EXTERNAL_IP=$(docker-machine ip)
exec docker-compose [email protected]
и
# docker-compose.yml
version: "2"
services:
consul:
image: consul
environment:
- "EXTERNAL_IP=${EXTERNAL_IP}"
command: agent -server -advertise ${EXTERNAL_IP} -bootstrap
К сожалению, если вы используете произвольное назначение порта, нет возможности добавить EXTERNAL_PORT
, поэтому порты должны быть связаны статически.
PS: Что-то очень похожее включено по умолчанию в HashiCorp Nomad, также включает отображенные порты. Doc: https://www.nomadproject.io/docs/jobspec/interpreted.html#interpreted_env_vars
Ответ 4
Переменные среды, как это предложено в более раннем решении, создаются Docker, когда контейнеры связаны. Но env vars не обновляются автоматически, если контейнер перезагружен. Таким образом, не рекомендуется использовать переменные среды в процессе производства.
Docker, помимо создания переменных среды, также обновляет записи хоста в файле /etc/hosts. Фактически, документация Docker рекомендует использовать записи хоста из etc/hosts вместо переменных среды.
Ссылка: https://docs.docker.com/userguide/dockerlinks/
В отличие от записей хоста в файле /etc/hosts, IP-адреса, хранящиеся в переменных среды, не обновляются автоматически, если исходный контейнер перезагружен. Мы рекомендуем использовать записи хоста в /etc/hosts для разрешения IP-адреса связанных контейнеров.
Ответ 5
Я использовал внутренний IP-адрес докере, который кажется статическим: 172.17.0.1