Seperti judulnya. Saya harus dapat mengambil alamat IP host buruh pelabuhan dan portmap dari host ke wadah, dan melakukan itu di dalam wadah.
Seperti judulnya. Saya harus dapat mengambil alamat IP host buruh pelabuhan dan portmap dari host ke wadah, dan melakukan itu di dalam wadah.
Jawaban:
/sbin/ip route|awk '/default/ { print $3 }'
Seperti @MichaelNeale perhatikan, tidak ada gunanya menggunakan metode ini dalam Dockerfile
(kecuali ketika kita membutuhkan IP ini selama waktu pembangunan saja), karena IP ini akan di-hardcode selama waktu pembuatan.
Pada versi 18.03, Anda dapat menggunakan host.docker.internal
sebagai IP host.
Bekerja di Docker untuk Mac , Docker untuk Windows , dan mungkin platform lain juga.
Ini adalah pembaruan dari Mac-spesifik docker.for.mac.localhost
, tersedia sejak versi 17.06, dan docker.for.mac.host.internal
, tersedia sejak versi 17.12, yang mungkin juga masih bekerja pada platform itu.
Catatan, seperti dalam dokumentasi Mac dan Windows , ini hanya untuk tujuan pengembangan.
Misalnya, saya menetapkan variabel lingkungan di host saya:
MONGO_SERVER=host.docker.internal
Dalam docker-compose.yml
file saya , saya punya ini:
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..
tidak ada gunanya karena dalam kebanyakan kasus Anda tidak memiliki lingkungan Linux atau Mac-satunya di perusahaan Anda. Ini campuran, Anda memiliki pengembang menggunakan Linux dan Mac dan Windows. Domain ini tidak masuk akal karena di 99% itu adalah lingkungan OS Host campuran. Saya tidak mengembangkan wadah di bawah macOS dan menyebarkannya ke server macOS. Saya menyebarkannya ke Linux. Inilah yang dilakukan semua orang. Jadi, apa gunanya docker.for.mac..
?
docker.for.mac.host.internal
tidak masalah apakah Anda menggunakan Docker dengan atau tanpa docker-compose
. Saya ingin menggunakan host tetap dalam file konfigurasi. IDK, misalnya,, docker.host.internal
yang selalu menunjuk ke alamat IP host. Terlepas dari sistem host mana yang saya gunakan. Ini adalah inti dari menggunakan Docker sama sekali: Saya ingin mandiri. Saya mengerti bahwa ini lebih rumit pada macOS karena Anda memiliki lapisan lain antara sistem host dan wadah. Tapi bagaimanapun, menurut saya docker.for.mac.host.internal
tidak ada gunanya jika Anda hanya dapat menggunakannya untuk macOS.
host.docker.internal
tidak berfungsi pada Docker untuk Windows juga, setidaknya pada saat menulis komentar ini.
Pembaruan: Pada Docker untuk Mac , pada versi 18.03, Anda dapat menggunakan host.docker.internal sebagai IP host. Lihat jawaban allanberry . Untuk versi Docker untuk Mac sebelumnya, jawaban berikut mungkin masih berguna:
Di Docker untuk Mac, docker0
jembatan tidak ada, jadi jawaban lain di sini mungkin tidak berfungsi. Semua lalu lintas keluar, dialihkan melalui host induk Anda, jadi selama Anda mencoba menyambungkan ke IP yang dikenali sebagai dirinya sendiri (dan wadah buruh pelabuhan tidak menganggapnya sendiri) Anda harus dapat terhubung. Misalnya jika Anda menjalankan ini dari mesin induk jalankan:
ipconfig getifaddr en0
Ini akan menunjukkan IP Mac Anda pada jaringan saat ini dan buruh pelabuhan Anda harus dapat terhubung ke alamat ini juga. Ini tentu saja menyebalkan jika alamat IP ini pernah berubah, tetapi Anda dapat menambahkan IP loopback khusus ke Mac Anda yang tidak dianggap wadah dengan melakukan sesuatu seperti ini di mesin induk:
sudo ifconfig lo0 alias 192.168.46.49
Anda kemudian dapat menguji koneksi dari dalam wadah buruh pelabuhan dengan telnet. Dalam kasus saya, saya ingin terhubung ke server xdebug jarak jauh:
telnet 192.168.46.49 9000
Sekarang ketika lalu lintas masuk ke Mac Anda yang ditujukan untuk 192.168.46.49 (dan semua lalu lintas yang meninggalkan kontainer Anda melewati Mac Anda) Mac Anda akan menganggap bahwa IP itu sendiri. Ketika Anda selesai menggunakan IP ini, Anda dapat menghapus alias loopback seperti ini:
sudo ifconfig lo0 -alias 192.168.46.49
Satu hal yang perlu diperhatikan adalah wadah buruh pelabuhan tidak akan mengirimkan lalu lintas ke host induk jika menganggap tujuan lalu lintas itu sendiri. Jadi periksa antarmuka loopback di dalam wadah jika Anda memiliki masalah:
sudo ip addr show lo
Dalam kasus saya, ini menunjukkan inet 127.0.0.1/8
yang berarti saya tidak dapat menggunakan IP apa pun dalam 127.*
kisaran. Itu sebabnya saya menggunakan 192.168.*
contoh di atas. Pastikan IP yang Anda gunakan tidak bertentangan dengan sesuatu di jaringan Anda sendiri.
Bagi mereka yang menjalankan Docker di AWS, instance meta-data untuk host masih tersedia dari dalam wadah.
curl http://169.254.169.254/latest/meta-data/local-ipv4
Sebagai contoh:
$ 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+'
Satu-satunya cara menyampaikan informasi host sebagai lingkungan saat Anda membuat wadah
run --env <key>=<value>
-e "DOCKER_HOST=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')"
(menggunakan jawaban yang diterima dari unix.stackexchange.com/questions/87468/… )
The --add-host
bisa menjadi solusi yang bersih lebih (tapi tanpa bagian pelabuhan, hanya tuan rumah dapat ditangani dengan solusi ini). Jadi, dalam docker run
perintah Anda , lakukan sesuatu seperti:
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [my container]
Praktik terbaik standar untuk sebagian besar aplikasi yang ingin melakukan ini secara otomatis adalah: Anda tidak . Sebaliknya Anda meminta orang yang menjalankan wadah menyuntikkan nama host / alamat ip eksternal sebagai konfigurasi, misalnya sebagai variabel lingkungan atau file konfigurasi. Mengizinkan pengguna menyuntikkan ini memberi Anda desain yang paling portabel.
Mengapa ini begitu sulit? Karena wadah akan, dengan desain, mengisolasi aplikasi dari lingkungan host. Jaringan dinamai hanya untuk wadah itu secara default, dan rincian host dilindungi dari proses yang berjalan di dalam wadah yang mungkin tidak sepenuhnya dipercaya.
Ada beberapa opsi tergantung pada situasi spesifik Anda:
Jika kontainer Anda berjalan dengan jaringan host, maka Anda dapat melihat tabel routing pada host secara langsung untuk melihat rute default keluar. Dari pertanyaan ini, yang berikut berfungsi untuk saya, misalnya:
ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'
Contoh yang menunjukkan ini dengan jaringan host dalam wadah terlihat seperti:
docker run --rm --net host busybox /bin/sh -c \
"ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'"
Untuk beberapa versi Docker Desktop, mereka menyuntikkan entri DNS ke VM tertanam:
getent hosts host.docker.internal | awk '{print $1}'
Jika Anda berjalan di lingkungan cloud, Anda dapat memeriksa layanan metadata dari penyedia cloud, misalnya AWS:
curl http://169.254.169.254/latest/meta-data/local-ipv4
Jika Anda ingin alamat eksternal / internet, Anda dapat meminta layanan jarak jauh seperti:
curl ifconfig.co
Masing-masing memiliki keterbatasan dan hanya berfungsi dalam skenario tertentu. Opsi yang paling portabel adalah masih menjalankan wadah Anda dengan alamat IP yang disuntikkan sebagai konfigurasi, misalnya inilah opsi yang menjalankan ip
perintah sebelumnya pada host dan menyuntikkannya sebagai variabel lingkungan:
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
Perintah yang sangat membantu .. Terima kasih :)
Jika Anda ingin IP
alamat asli (bukan jembatan IP
) Windows
dan Anda memiliki buruh pelabuhan18.03
(atau yang lebih baru) lakukan hal berikut:
Jalankan bash on container dari host tempat nama gambar berada nginx
(berfungsi Alpine Linux distribution
):
docker run -it nginx /bin/ash
Kemudian jalankan di dalam wadah
/ # nslookup host.docker.internal
Name: host.docker.internal
Address 1: 192.168.65.2
192.168.65.2
adalah IP host - bukan IP jembatan seperti di spinus
jawaban yang diterima.
Saya menggunakan di sini host.docker.internal :
Tuan rumah memiliki alamat IP yang berubah (atau tidak ada jika Anda tidak memiliki akses jaringan). Dari 18,03 dan seterusnya, rekomendasi kami adalah untuk terhubung ke nama DNS khusus host.docker.internal, yang memutuskan ke alamat IP internal yang digunakan oleh tuan rumah. Ini untuk tujuan pengembangan dan tidak akan berfungsi di lingkungan produksi di luar Docker untuk Windows.
Alpine Linux
? Jika tidak maka periksa setara untuk spesifik Anda linux distribution
.
linux containers
dan saya tidak menggunakan windows containers
. Anda dapat melakukannya dengan mengklik kanan docker icon
dan memilih Switch to Linux containers
. Saya pikir itu bisa menjadi penting ketika Anda mengunduh gambar. Jika Anda telah windows container
memeriksa apakah menghapus nginx
gambar lama dan mengunduhnya lagi akan memberi Anda wadah lain. Jika masih tidak bekerja untuk Anda - daripada Anda dapat mencoba menginstal nslookup
di ash
.
host.docker.internal
) dari dalam wadah
docker run -it --rm alpine nslookup host.docker.internal
... mencetak alamat IP host ...
nslookup: can't resolve '(null)': Name does not resolve
Name: host.docker.internal
Address 1: 192.168.65.2
Di Mac dan Windows , Anda dapat menggunakan nama DNS khusus host.docker.internal
.
Tuan rumah memiliki alamat IP yang berubah (atau tidak ada jika Anda tidak memiliki akses jaringan). Dari 18,03 dan seterusnya, rekomendasi kami adalah untuk terhubung ke nama DNS khusus host.docker.internal, yang memutuskan ke alamat IP internal yang digunakan oleh tuan rumah. Ini untuk tujuan pengembangan dan tidak akan berfungsi di lingkungan produksi di luar Docker Desktop untuk Mac.
Docker untuk Mac Saya ingin terhubung dari sebuah wadah ke layanan di host
Tuan rumah memiliki alamat IP yang berubah (atau tidak ada jika Anda tidak memiliki akses jaringan). Dari 18,03 dan seterusnya, rekomendasi kami adalah untuk terhubung ke nama DNS khusus host.docker.internal, yang memutuskan ke alamat IP internal yang digunakan oleh tuan rumah.
Gateway juga dapat dijangkau sebagai gateway.docker.internal. https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds
Jika Anda mengaktifkan API jarak jauh buruh pelabuhan (via-H
tcp://0.0.0.0:4243
misalnya) dan mengetahui nama host atau alamat IP mesin host, ini dapat dilakukan dengan banyak bash.
Di dalam pengguna kontainer saya 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'
)
Baris kedua mengambil ID kontainer dari lokal Anda /proc/self/cgroup
file .
Baris ketiga meringkuk ke mesin host (dengan asumsi Anda menggunakan 4243 sebagai port docker) kemudian menggunakan node untuk mengurai JSON yang dikembalikan untuk DESIRED_PORT
.
HostPort
bisa menjadi informasi yang berguna di sini, sayangnya HostIp
mungkin0.0.0.0
Saya punya Ubuntu 16.03. Untuk saya
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [image]
tidak TIDAK bekerja (ip yang salah menghasilkan)
Solusi kerja saya adalah:
docker run --add-host dockerhost:`docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge` [image]
Berikut adalah opsi lain bagi mereka yang menjalankan Docker di AWS. Opsi ini menghindari penggunaan apk untuk menambahkan paket ikal dan menghemat ruang 7mb yang berharga. Gunakan wget bawaan (bagian dari biner BusyBox monolitik):
wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4
AFAIK, dalam hal Docker untuk Linux (distribusi standar), alamat ip host akan selalu 172.17.0.1
.
Cara termudah untuk mendapatkannya adalah melalui ifconfig
(interface docker0) dari tuan rumah:
ifconfig
Dari dalam buruh pelabuhan, perintah berikut dari buruh pelabuhan: ip -4 route show default | cut -d" " -f3
Anda dapat menjalankannya dengan cepat di buruh pelabuhan dengan baris perintah berikut:
# 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"
Saya harap ini membantu.
Di linux Anda bisa menjalankan
HOST_IP=`hostname -I | awk '{print $1}'`
Di macOS mesin host Anda bukan host Docker. Docker akan menginstal host OS-nya di VirtualBox.
HOST_IP=`docker run busybox ping -c 1 docker.for.mac.localhost | awk 'FNR==2 {print $4}' | sed s'/.$//'`
hostname -I
memperingatkan untuk tidak "membuat asumsi tentang urutan output."
Ini adalah implementasi minimalis di Node.js untuk siapa yang menjalankan host pada instance AWS EC2 , menggunakan instance Metadata EC2 yang disebutkan sebelumnya
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
dan digunakan sebagai
ec2(function(err, ip) {
if(err) console.log(err)
else console.log(ip);
})
Jika Anda menjalankan wadah Windows pada kluster Fabric Layanan, alamat IP host tersedia melalui variabel lingkungan Fabric_NodeIPOrFQDN
. Variabel lingkungan Fabric Layanan
Inilah cara saya melakukannya. Dalam hal ini, ia menambahkan entri host ke / etc / hosts di dalam gambar buruh pelabuhan yang menunjuk taurus-host ke IP mesin lokal saya::
TAURUS_HOST=`ipconfig getifaddr en0`
docker run -it --rm -e MY_ENVIRONMENT='local' --add-host "taurus-host:${TAURUS_HOST}" ...
Kemudian, dari dalam wadah Docker, skrip dapat menggunakan nama host taurus-host untuk keluar ke mesin lokal saya yang menampung kontainer buruh pelabuhan.
Mungkin wadah yang saya buat bermanfaat juga https://github.com/qoomon/docker-host
Anda cukup menggunakan wadah nama dns untuk mengakses sistem host misalnya curl http: // dockerhost: 9200 , jadi tidak perlu repot dengan alamat IP.
Solusi yang saya gunakan didasarkan pada "server" yang mengembalikan alamat eksternal host Docker ketika menerima permintaan http.
Di "server":
1) Mulai jwilder / nginx-proxy
# docker run -d -p <external server port>:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
2) Mulai wadah ipify
# docker run -e VIRTUAL_HOST=<external server name/address> --detach --name ipify osixia/ipify-api:0.1.0
Sekarang ketika sebuah kontainer mengirimkan permintaan http ke server, mis
# curl http://<external server name/address>:<external server port>
alamat IP host Docker dikembalikan oleh ipify melalui tajuk http "X-Forwarded-For"
Contoh (server ipify memiliki nama "ipify.example.com" dan berjalan pada port 80, host buruh pelabuhan memiliki 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
Di dalam wadah sekarang Anda dapat memanggil:
# curl http://ipify.example.com
10.20.30.40
Coba ini
run docker --rm -i --net = host alpine ifconfig
Di Ubuntu, hostname
perintah dapat digunakan dengan opsi berikut:
-i
, --ip-address
alamat untuk nama host-I
, --all-ip-addresses
semua alamat untuk tuan rumahSebagai contoh:
$ hostname -i
172.17.0.2
Untuk menetapkan variabel, one-liner berikut dapat digunakan:
IP=$(hostname -i)
Dengan https://docs.docker.com/machine/install-machine/
a) $ mesin docker ip
b) Dapatkan alamat IP dari satu atau lebih mesin.
$ docker-machine ip host_name
$ docker-machine ip host_name1 host_name2