Как видно из названия. Мне нужно иметь возможность получить IP-адрес хоста докера и сопоставления портов от хоста к контейнеру, и делать это внутри контейнера.
Как видно из названия. Мне нужно иметь возможность получить IP-адрес хоста докера и сопоставления портов от хоста к контейнеру, и делать это внутри контейнера.
Ответы:
/sbin/ip route|awk '/default/ { print $3 }'
Как заметил @MichaelNeale, нет смысла использовать этот метод Dockerfile
(кроме случаев, когда нам нужен этот IP только во время сборки), потому что этот IP будет жестко задан во время сборки.
Начиная с версии 18.03, вы можете использовать host.docker.internal
в качестве IP- адреса хоста.
Работает в Docker для Mac , Docker для Windows и, возможно, на других платформах.
Это обновление для Mac docker.for.mac.localhost
, доступное с версии 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
docker.for.mac..
это бесполезно , так как в большинстве случаев не имеют среды linux- или Mac-только в вашей компании. Это смешанно, у вас есть разработчики, использующие Linux, Mac и Windows. Этот домен не имеет смысла, так как на 99% это смешанная среда хост-ОС. Я не разрабатываю контейнер под macOS и не развертываю его на сервере macOS. Я развернул его в Linux. Это то, что все делают. Так в чем же смысл docker.for.mac..
?
docker.for.mac.host.internal
не имеет значения, используете ли вы Docker с или без docker-compose
. Я хочу использовать фиксированный хост в файлах конфигурации. IDK, например, docker.host.internal
который всегда указывает на IP-адрес хоста. Независимо от того, какую хост-систему я использую. В этом весь смысл использования Docker: я хочу быть автономным. Я понимаю, что это еще сложнее в macOS, потому что у вас есть другой слой между хост-системой и контейнером. Но в любом случае, на мой взгляд docker.for.mac.host.internal
, бесполезно, если вы можете использовать его только для macOS.
host.docker.internal
действительно работает на Docker для Windows , по крайней мере, во время написания этого комментария.
Обновление: в Docker для Mac , начиная с версии 18.03, вы можете использовать host.docker.internal в качестве IP- адреса хоста. Смотрите ответ Алланберри . Для предыдущих версий Docker для Mac все еще может быть полезен следующий ответ:
В Docker для Mac docker0
мост не существует, поэтому другие ответы здесь могут не работать. Однако весь исходящий трафик направляется через ваш родительский хост, поэтому до тех пор, пока вы пытаетесь подключиться к IP-адресу, который он распознает как сам по себе (а док-контейнер не считает себя таким), вы должны иметь возможность подключиться. Например, если вы запускаете это с родительского компьютера, запустите:
ipconfig getifaddr en0
Это должно показать вам IP вашего Mac в его текущей сети, и ваш док-контейнер должен также иметь возможность подключиться к этому адресу. Это, конечно, неприятно, если этот IP-адрес когда-либо изменится, но вы можете добавить свой петлевой IP-адрес к вашему Mac, который контейнер не считает самим, выполнив что-то вроде этого на родительской машине:
sudo ifconfig lo0 alias 192.168.46.49
Затем вы можете проверить соединение из контейнера Docker с помощью telnet. В моем случае я хотел подключиться к удаленному серверу xdebug:
telnet 192.168.46.49 9000
Теперь, когда трафик поступает на ваш Mac с адресом 192.168.46.49 (и весь трафик, выходящий из вашего контейнера, проходит через ваш Mac), ваш Mac будет считать, что IP сам по себе. Когда вы закончите использовать этот IP-адрес, вы можете удалить псевдоним петли следующим образом:
sudo ifconfig lo0 -alias 192.168.46.49
Одна вещь, о которой следует быть осторожным, заключается в том, что док-контейнер не будет отправлять трафик на родительский хост, если он думает, что адресат трафика сам по себе. Поэтому проверьте интерфейс обратной связи внутри контейнера, если у вас возникли проблемы:
sudo ip addr show lo
В моем случае это показало, inet 127.0.0.1/8
что означает, что я не мог использовать любые IP-адреса в 127.*
диапазоне. Вот почему я использовал 192.168.*
в приведенном выше примере. Убедитесь, что используемый вами IP-адрес не конфликтует с чем-то в вашей сети.
Для тех, кто использует 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
ifconfig eth0 | grep -oP 'inet \K\S+'
Единственный способ - передать информацию о хосте в качестве среды при создании контейнера.
run --env <key>=<value>
-e "DOCKER_HOST=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')"
(используя принятый ответ от unix.stackexchange.com/questions/87468/… )
Это --add-host
может быть более чистое решение (но без части порта, только хост может быть обработан с этим решением). Итак, в вашей docker run
команде сделайте что-то вроде:
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [my container]
Стандартные рекомендации для большинства приложений, которые хотят сделать это автоматически: нет . Вместо этого человек, выполняющий контейнер, вводит внешнее имя хоста / IP-адрес в качестве конфигурации, например, в качестве переменной среды или файла конфигурации. Позволяя пользователю вводить это дает вам наиболее портативный дизайн.
Почему это так сложно? Поскольку контейнеры по своей природе изолируют приложение от среды хоста. По умолчанию пространство сети относится именно к этому контейнеру, а сведения о хосте защищены от процесса, выполняющегося внутри контейнера, которому нельзя доверять полностью.
Существуют различные варианты в зависимости от вашей конкретной ситуации:
Если ваш контейнер работает с сетью хоста, то вы можете посмотреть таблицу маршрутизации на хосте напрямую, чтобы увидеть маршрут по умолчанию. Из этого вопроса у меня работает следующее, например:
ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'
Пример, показывающий это с хост-сетью в контейнере, выглядит следующим образом:
docker run --rm --net host busybox /bin/sh -c \
"ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'"
В некоторых версиях 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
команду на хосте и вставлял ее как переменную среды:
export HOST_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p')
docker run --rm -e HOST_IP busybox printenv HOST_IP
curl ifconfig.co
команда .. Спасибо :)
Если вы хотите, чтобы действительный 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.
Alpine Linux
? Если нет, то проверьте эквивалент для вашего конкретного linux distribution
.
linux containers
и я не использую. windows containers
Вы можете сделать это, щелкнув правой кнопкой мыши docker icon
и выбрав Switch to Linux containers
. Я думаю, что это может быть важно, когда вы загружаете изображение. Если вы windows container
проверили, удалив ли старое nginx
изображение и загрузите его снова, вы получите другой контейнер. Если это все еще не работает для вас - чем вы можете попробовать установить nslookup
в ash
.
host.docker.internal
) из контейнера
docker run -it --rm alpine nslookup host.docker.internal
... печатает IP-адрес хоста ...
nslookup: can't resolve '(null)': Name does not resolve
Name: host.docker.internal
Address 1: 192.168.65.2
На Mac и Windows вы можете использовать специальное DNS-имя host.docker.internal
.
Хост имеет изменяющийся IP-адрес (или не имеет, если у вас нет доступа к сети). Начиная с 18.03, мы рекомендуем подключаться к специальному DNS-имени host.docker.internal, который разрешает внутренний IP-адрес, используемый хостом. Это для целей разработки и не будет работать в производственной среде за пределами Docker Desktop для Mac.
Docker для Mac Я хочу подключиться из контейнера к службе на хосте
Хост имеет изменяющийся IP-адрес (или не имеет, если у вас нет доступа к сети). Начиная с 18.03, мы рекомендуем подключаться к специальному DNS-имени host.docker.internal, который разрешает внутренний IP-адрес, используемый хостом.
Шлюз также доступен как gateway.docker.internal. https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds
Если вы включили удаленный API докера ( например, через ) и знаете имя хоста или IP-адрес хост-машины, это можно сделать с помощью большого количества команд bash.-H
tcp://0.0.0.0:4243
Внутри пользователя моего контейнера 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 в качестве порта докера), а затем использует узел для анализа возвращенного JSON для DESIRED_PORT
.
HostPort
может быть полезной информацией здесь, к сожалению, HostIp
может быть0.0.0.0
У меня Ubuntu 16.03. Для меня
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [image]
это НЕ работает (неправильно внутрибрюшинно генерировала)
Мое рабочее решение было таким:
docker run --add-host dockerhost:`docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge` [image]
Вот еще один вариант для тех, кто работает в Docker в AWS. Эта опция позволяет избежать использования apk для добавления пакета curl и экономит драгоценные 7 МБ пространства. Используйте встроенный wget (часть монолитного двоичного файла BusyBox):
wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4
AFAIK, в случае Docker для Linux (стандартный дистрибутив), IP-адрес хоста всегда будет 172.17.0.1
.
Самый простой способ получить его - через ifconfig
(интерфейс docker0) с хоста:
ifconfig
Из докера, следующая команда из докера: ip -4 route show default | cut -d" " -f3
Вы можете быстро запустить его в докере с помощью следующей командной строки:
# 1. Run an ubuntu docker
# 2. Updates dependencies (quietly)
# 3. Install ip package (quietly)
# 4. Shows (nicely) the ip of the host
# 5. Removes the docker (thanks to `--rm` arg)
docker run -it --rm ubuntu:19.10 bash -c "apt-get update && apt-get install iproute2 -y && ip -4 route show default | cut -d' ' -f3"
Я надеюсь, что это помогает.
В 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'/.$//'`
hostname -I
предупреждает, чтобы «не делать никаких предположений о порядке вывода».
Это минималистичная реализация в 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);
})
Если вы запускаете контейнер Windows в кластере Service Fabric, IP-адрес хоста доступен через переменную среды Fabric_NodeIPOrFQDN
. Переменные среды Service Fabric
Вот как я это делаю. В этом случае он добавляет запись hosts в / 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, чтобы выйти на мою локальную машину, на которой размещен контейнер Docker.
Может быть, созданный мною контейнер также полезен https://github.com/qoomon/docker-host
Вы можете просто использовать имя контейнера dns для доступа к хост-системе, например, curl http: // dockerhost: 9200 , поэтому вам не нужно беспокоиться о каком-либо IP-адресе.
Решение, которое я использую, основано на «сервере», который возвращает внешний адрес хоста 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
Попробуй это
запуск докера --rm -i --net = хост альпийский ifconfig
В Ubuntu hostname
команду можно использовать со следующими параметрами:
-i
, --ip-address
адреса для имени хоста-I
, --all-ip-addresses
все адреса для хостаНапример:
$ hostname -i
172.17.0.2
Для присвоения переменной можно использовать следующую однострочную строку:
IP=$(hostname -i)
С помощью https://docs.docker.com/machine/install-machine/
а) $ docker-machine ip
б) Получить IP-адрес одной или нескольких машин.
$ docker-machine ip host_name
$ docker-machine ip host_name1 host_name2