Как получить IP-адрес хоста докера из контейнера докеров

Как говорится в названии. Мне нужно иметь возможность получить IP-адрес хостов докеров и портлетов от хоста к контейнеру и сделать это внутри контейнера.

Ответ 1

/sbin/ip route|awk '/default/ { print $3 }'

Как заметил @MichaelNeale, нет смысла использовать этот метод в Dockerfile (за исключением случаев, когда нам нужен этот IP только во время сборки), поскольку этот IP-адрес будет жестко запрограммирован во время сборки.

Ответ 2

Начиная с версии 18.03, вы можете использовать host.docker.internal в качестве IP- host.docker.internal хоста.

Работает в Docker для Mac, Docker для Windows и, возможно, на других платформах. (шляпный наконечник joanlofe)

Это обновление для docker.for.mac.localhost Mac, доступное с версии 17.06, и docker.for.mac.host.internal, доступное с версии 17.12, которое также может работать на этой платформе.

Обратите внимание, как и в документации для Mac и Windows, это только для целей разработки.

Например, на моем хосте установлены переменные окружения:

MONGO_SERVER=host.docker.internal

В моем файле docker-compose.yml меня есть это:

version: '3'

services:
  api:
    build: ./api
    volumes:
      - ./api:/usr/src/app:ro
    ports:
      - "8000"
    environment:
      - MONGO_SERVER
    command: /usr/local/bin/gunicorn -c /usr/src/app/gunicorn_config.py -w 1 -b :8000 wsgi

Ответ 3

Обновление: в Docker для Mac, начиная с версии 18.03, вы можете использовать host.docker.internal как IP-адрес хоста. См. Ответ allanberry. Для предыдущих версий Docker для Mac может быть полезен следующий ответ:

В Docker for Mac docker0 не существует, поэтому другие ответы здесь могут не работать. Однако весь исходящий трафик маршрутизируется через ваш родительский хост, поэтому пока вы пытаетесь подключиться к IP-адресу, который он распознает как сам (и контейнер-докер не думает сам), вы должны иметь возможность подключиться. Например, если вы запустили это из запуска родительской машины:

ipconfig getifaddr en0

Это должно показать вам IP вашего Mac в его текущей сети, и ваш контейнер докеров должен также иметь возможность подключиться к этому адресу. Это, конечно, боль, если этот IP-адрес когда-либо изменился, но вы можете добавить настраиваемый IP-адрес циклы на ваш Mac, чтобы контейнер не думал сам, выполнив что-то вроде этого на родительской машине:

sudo ifconfig lo0 alias 192.168.46.49

Затем вы можете проверить соединение из контейнера докера с помощью telnet. В моем случае я хотел подключиться к удаленному серверу xdebug:

telnet 192.168.46.49 9000

Теперь, когда на ваш Mac поступает трафик на 192.168.46.49 (и весь трафик, покидающий ваш контейнер, проходит через ваш Mac), ваш Mac будет считать, что сам IP. Когда вы закончите использовать этот IP-адрес, вы можете удалить псевдоним loopback следующим образом:

sudo ifconfig lo0 -alias 192.168.46.49

Одна вещь, о которой нужно быть осторожным, заключается в том, что контейнер докеров не будет отправлять трафик на родительский хост, если он считает, что назначение трафика само по себе. Поэтому проверьте интерфейс loopback внутри контейнера, если у вас есть проблемы:

sudo ip addr show lo

В моем случае это показало inet 127.0.0.1/8 что означает, что я не мог использовать IP-адреса в диапазоне 127.*. Вот почему я использовал 192.168.* В приведенном выше примере. Убедитесь, что используемый вами IP-адрес не конфликтует с чем-то в вашей собственной сети.

Ответ 4

Для тех, кто запускает Docker в AWS, метаданные экземпляра для хоста все еще доступны изнутри контейнера.

curl http://169.254.169.254/latest/meta-data/local-ipv4

Например:

$ docker run alpine /bin/sh -c "apk update ; apk add curl ; curl -s http://169.254.169.254/latest/meta-data/local-ipv4 ; echo"
fetch http://dl-cdn.alpinelinux.org/alpine/v3.3/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.3/community/x86_64/APKINDEX.tar.gz
v3.3.1-119-gb247c0a [http://dl-cdn.alpinelinux.org/alpine/v3.3/main]
v3.3.1-59-g48b0368 [http://dl-cdn.alpinelinux.org/alpine/v3.3/community]
OK: 5855 distinct packages available
(1/4) Installing openssl (1.0.2g-r0)
(2/4) Installing ca-certificates (20160104-r2)
(3/4) Installing libssh2 (1.6.0-r1)
(4/4) Installing curl (7.47.0-r0)
Executing busybox-1.24.1-r7.trigger
Executing ca-certificates-20160104-r2.trigger
OK: 7 MiB in 15 packages
172.31.27.238

$ ifconfig eth0 | grep -oP 'inet addr:\K\S+'
172.31.27.238

Ответ 5

Единственный способ передачи информации о хосте в качестве среды при создании контейнера

run --env <key>=<value>

Ответ 6

--add-host может быть более чистым решением (но без части порта с этим решением может обрабатываться только хост). Итак, в вашей команде docker run сделайте что-то вроде:

docker run --add-host dockerhost:'/sbin/ip route|awk '/default/ { print  $3}'' [my container]

fooobar.com/questions/33350/...)

Ответ 7

Если вы хотите реальный IP адрес ( а не мост IP) на Windows, и у вас есть докер 18.03 (или более поздние) сделайте следующее:

Запустите bash для контейнера с хоста, где имя образа - nginx (работает в Alpine Linux distribution):

 docker run -it nginx /bin/ash

Затем запустите внутри контейнера

/ # nslookup host.docker.internal

Name:      host.docker.internal
Address 1: 192.168.65.2

192.168.65.2 - это IP-адрес хоста, а не IP-адрес моста, как в ответе spinus.

Я использую здесь host.docker.internal:

Хост имеет изменяющийся IP-адрес (или не имеет, если у вас нет доступа к сети). Начиная с 18.03, мы рекомендуем подключаться к специальному DNS-имени host.docker.internal, который разрешает внутренний IP-адрес, используемый хостом. Это для целей разработки и не будет работать в производственной среде за пределами Docker для Windows.

Ответ 8

Докер для Mac Я хочу подключиться из контейнера к службе на хосте

Хост имеет изменяющийся IP-адрес (или нет, если у вас нет доступа к сети). Начиная с 18.03, наша рекомендация - подключиться к специальному DNS-имени host.docker.internal, которое разрешает внутренний IP-адрес, используемый хостом.

Шлюз также доступен как gateway.docker.internal. https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds

Ответ 9

Если вы включили удаленный API докеры (через -H tcp://0.0.0.0:4243) и узнать имя хоста хоста или IP-адрес, это можно сделать с помощью большого количества bash.

Внутри пользователя контейнера bashrc:

export hostIP=$(ip r | awk '/default/{print $3}')
export containerID=$(awk -F/ '/docker/{print $NF;exit;}' /proc/self/cgroup)
export proxyPort=$(
  curl -s http://$hostIP:4243/containers/$containerID/json |
  node -pe 'JSON.parse(require("fs").readFileSync("/dev/stdin").toString()).NetworkSettings.Ports["DESIRED_PORT/tcp"][0].HostPort'
)

Вторая строка захватывает идентификатор контейнера из локального файла /proc/self/cgroup.

Третья строка зависает на главном компьютере (при условии, что вы используете 4243 в качестве порта докера), затем использует node для синтаксического анализа возвращенного JSON для DESIRED_PORT.

Ответ 10

Вот еще один вариант для тех, кто работает Docker в AWS. Этот вариант позволяет избежать использования apk для добавления пакета curl и сохранения драгоценного 7mb пространства. Используйте встроенный wget (часть монолитного двоичного файла BusyBox):

wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4

Ответ 11

В linux вы можете запускать

HOST_IP='hostname -I | awk '{print $1}''

В macOS ваша хост-машина не является хостом Docker. Docker установит его хост-систему в VirtualBox.

HOST_IP='docker run busybox ping -c 1 docker.for.mac.localhost | awk 'FNR==2 {print $4}' | sed s'/.$//''

Ответ 12

Стандартные рекомендации для большинства приложений, которые хотят сделать это автоматически: нет. Вместо этого человек, выполняющий контейнер, вводит внешнее имя хоста /IP-адрес в качестве конфигурации, например, в качестве переменной среды или файла конфигурации. Позволяя пользователю вводить это дает вам наиболее портативный дизайн.

Почему это так сложно? Поскольку контейнеры по своей природе изолируют приложение от среды хоста. По умолчанию пространство сети относится именно к этому контейнеру, а сведения о хосте защищены от процесса, выполняющегося внутри контейнера, которому нельзя доверять полностью.


Существуют различные варианты в зависимости от вашей конкретной ситуации:

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

ip r s 0/0 | awk '{print $3}

Пример, показывающий это с хост-сетью в контейнере, выглядит следующим образом:

docker run --rm --net host busybox /bin/sh -c "ip r s 0/0 | awk '{print \$3}'"

В некоторых версиях Docker Desktop они вводили запись DNS:

getent hosts host.docker.internal | awk '{print $1}'

Если вы работаете в облачной среде, вы можете проверить сервис метаданных у облачного провайдера, например AWS:

curl http://169.254.169.254/latest/meta-data/local-ipv4

Если вы хотите, чтобы ваш внешний/интернет-адрес, вы можете запросить удаленный сервис, как:

curl ifconfig.co

Каждый из них имеет ограничения и работает только в определенных сценариях. Наиболее переносимым вариантом по-прежнему является запуск вашего контейнера с IP-адресом, введенным в качестве конфигурации, например, здесь можно запустить более раннюю команду ip на хосте и внедрить ее в качестве переменной среды:

docker run --rm -e HOST_IP=$(ip r s 0/0 | awk '{print $3}') busybox printenv HOST_IP

Ответ 13

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

Ответ 14

Вот как я это делаю. В этом случае он добавляет запись хостов в /etc/hosts в образ докеры, указывающий на taurus-host, на мой локальный компьютер IP::

TAURUS_HOST='ipconfig getifaddr en0'
docker run -it --rm -e MY_ENVIRONMENT='local' --add-host "taurus-host:${TAURUS_HOST}" ...

Затем изнутри контейнера Docker скрипт может использовать имя узла taurus-host, чтобы выйти на мою локальную машину, на которой размещается контейнер докеров.

Ответ 15

Может быть, созданный мною контейнер тоже полезен https://github.com/qoomon/docker-host

Вы можете просто использовать имя контейнера dns для доступа к хост-системе, например, curl http://dockerhost: 9200, поэтому вам не нужно беспокоиться о каком-либо IP-адресе.

Ответ 16

Решение, которое я использую, основано на "сервере", который возвращает внешний адрес хоста Docker, когда он получает запрос http.

На "сервере":

1) Запустите jwilder/nginx-прокси

# docker run -d -p <external server port>:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy

2) Запустить ipify контейнер

# docker run -e VIRTUAL_HOST=<external server name/address> --detach --name ipify osixia/ipify-api:0.1.0

Теперь, когда контейнер отправляет запрос http на сервер, например

# curl http://<external server name/address>:<external server port>

IP-адрес хоста Docker возвращается через ipify через заголовок http "X-Forwarded-For"

Пример (сервер ipify имеет имя "ipify.example.com" и работает на порту 80, хост докера имеет IP 10.20.30.40):

# docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
# docker run -e VIRTUAL_HOST=ipify.example.com --detach --name ipify osixia/ipify-api:0.1.0

Внутри контейнера теперь можно звонить:

# curl http://ipify.example.com
10.20.30.40

Ответ 17

В Ubuntu команду hostname можно использовать со следующими параметрами:

  • -i, --ip-address адресов для имени хоста
  • -i, --all-ip-addresses всех адресов для хоста

Например:

$ hostname -i
172.17.0.2

Для присвоения переменной можно использовать следующую однострочную строку:

IP=$(hostname -i)

Ответ 18

Это минималистичная реализация в Node.js для того, кто запускает хост на экземплярах AWS EC2, используя вышеупомянутый экземпляр метаданных EC2.

const cp = require('child_process');
const ec2 = function (callback) {
    const URL = 'http://169.254.169.254/latest/meta-data/local-ipv4';
    // we make it silent and timeout to 1 sec
    const args = [URL, '-s', '--max-time', '1'];
    const opts = {};
    cp.execFile('curl', args, opts, (error, stdout) => {
        if (error) return callback(new Error('ec2 ip error'));
        else return callback(null, stdout);
    })
        .on('error', (error) => callback(new Error('ec2 ip error')));
}//ec2

и используется как

ec2(function(err, ip) {
        if(err) console.log(err)
        else console.log(ip);
    })

Ответ 19

У меня Ubuntu 16.03. Для меня

docker run --add-host dockerhost:'/sbin/ip route|awk '/default/ { print  $3}'' [image]

НЕ работает (генерировался неправильный ip)

Мое рабочее решение было таким:

docker run --add-host dockerhost:'docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge' [image]

Ответ 20

С https://docs.docker.com/machine/install-machine/

a) $docker-machine ip

b) Получите IP-адрес одной или нескольких машин.

  $ docker-machine ip host_name

  $ docker-machine ip host_name1 host_name2