Як говориться в назві. Мені потрібно мати можливість отримати 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% це змішане середовище Host OS. Я не розробляю контейнер під macOS і розгортаю його на сервері macOS. Я розгортаю його в Linux. Це те, що роблять усі. Тож у чому навіть вся суть docker.for.mac..
?
docker.for.mac.host.internal
не має значення, використовуєте ви Docker з чи без docker-compose
. Я хочу використовувати фіксований хост у файлах конфігурації. Наприклад, IDK, docker.host.internal
який завжди вказує на IP-адресу хоста. Незалежно від того, яку хост-систему я використовую. У цьому вся суть використання Докера взагалі: я хочу бути автономним. Я розумію, що в 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-адреса коли-небудь змінюється, але ви можете додати на свій Mac спеціальний IP-адрес із зворотним циклом, що контейнер не вважає собою, зробивши щось подібне на батьківській машині:
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-адреси, ви можете видалити псевдонім циклу таким чином:
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 у вбудований VM:
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 API докера ( наприклад, наприклад) і знаєте ім'я хоста або IP-адресу хост-машини, це можна зробити з великою сумою.-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 та економить дорогоцінні 7mb місця. Використовуйте вбудований 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
. Змінні середовища службової тканини
Ось як я це роблю. У цьому випадку він додає запис хостів у / etc / hosts в межах зображення докера, що вказує host-taurus до моєї 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-proxy
# 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
Спробуйте це
docker run --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/
a) $ docker-machine ip
b) Отримайте IP-адресу однієї або декількох машин.
$ docker-machine ip host_name
$ docker-machine ip host_name1 host_name2