Như tiêu đề nói. Tôi cần có khả năng truy xuất địa chỉ IP của máy chủ docker và các chân dung từ máy chủ đến container và thực hiện điều đó bên trong container.
Như tiêu đề nói. Tôi cần có khả năng truy xuất địa chỉ IP của máy chủ docker và các chân dung từ máy chủ đến container và thực hiện điều đó bên trong container.
Câu trả lời:
/sbin/ip route|awk '/default/ { print $3 }'
Như @MichaelNeale nhận thấy, không có ý nghĩa gì khi sử dụng phương thức này Dockerfile
(trừ khi chúng tôi chỉ cần IP này trong thời gian xây dựng), vì IP này sẽ bị mã hóa cứng trong thời gian xây dựng.
Kể từ phiên bản 18.03, bạn có thể sử dụng host.docker.internal
làm IP của máy chủ.
Hoạt động trong Docker cho Mac , Docker cho Windows và có lẽ các nền tảng khác.
Đây là bản cập nhật từ Mac cụ thể docker.for.mac.localhost
, có sẵn từ phiên bản 17.06 và docker.for.mac.host.internal
, có sẵn kể từ phiên bản 17.12, vẫn có thể hoạt động trên nền tảng đó.
Lưu ý, như trong tài liệu Mac và Windows , mục đích này chỉ dành cho mục đích phát triển.
Ví dụ: tôi có các biến môi trường được đặt trên máy chủ của mình:
MONGO_SERVER=host.docker.internal
Trong docker-compose.yml
tập tin của tôi , tôi có điều này:
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..
vô dụng vì trong hầu hết các trường hợp, bạn không có môi trường chỉ dành cho Linux hoặc Mac trong công ty của mình. Thật hỗn tạp, bạn có các nhà phát triển sử dụng Linux và Mac và Windows. Tên miền này không có ý nghĩa gì vì trong 99% đó là môi trường Hệ điều hành máy chủ hỗn hợp. Tôi không phát triển một container theo macOS và triển khai nó đến máy chủ macOS. Tôi triển khai nó lên Linux. Đây là những gì mọi người làm. Vì vậy, những gì thậm chí toàn bộ quan điểm docker.for.mac..
?
docker.for.mac.host.internal
không quan trọng bạn có sử dụng Docker hay không docker-compose
. Tôi muốn sử dụng một máy chủ cố định trong các tập tin cấu hình. IDK, ví dụ, docker.host.internal
mà luôn luôn trỏ tới địa chỉ IP máy chủ. Bất kể hệ thống máy chủ nào tôi đang sử dụng. Đây là toàn bộ quan điểm của việc sử dụng Docker: Tôi muốn tự chủ. Tôi hiểu rằng nó thậm chí còn phức tạp hơn trên macOS vì bạn có một lớp khác giữa hệ thống máy chủ và bộ chứa. Nhưng dù sao, theo tôi docker.for.mac.host.internal
là vô ích nếu bạn chỉ có thể sử dụng nó cho macOS.
host.docker.internal
cũng hoạt động trên Docker cho Windows , ít nhất là tại thời điểm viết bình luận này.
Cập nhật: Trên Docker cho Mac , kể từ phiên bản 18.03, bạn có thể sử dụng host.docker.iternal làm IP của máy chủ. Xem câu trả lời của allanberry . Đối với các phiên bản trước của Docker cho Mac, câu trả lời sau có thể vẫn hữu ích:
Trên Docker cho Mac, docker0
cây cầu không tồn tại, vì vậy các câu trả lời khác ở đây có thể không hoạt động. Tuy nhiên, tất cả lưu lượng truy cập đi được chuyển qua máy chủ mẹ của bạn, do đó, miễn là bạn cố gắng kết nối với IP, nó sẽ tự nhận ra (và bộ chứa docker không nghĩ là chính nó), bạn sẽ có thể kết nối. Ví dụ: nếu bạn chạy cái này từ máy mẹ chạy:
ipconfig getifaddr en0
Điều này sẽ cho bạn thấy IP của máy Mac của bạn trên mạng hiện tại và thùng chứa docker của bạn cũng có thể kết nối với địa chỉ này. Điều này tất nhiên là khó khăn nếu địa chỉ IP này thay đổi, nhưng bạn có thể thêm IP loopback tùy chỉnh vào máy Mac mà container không nghĩ là chính nó bằng cách thực hiện một cái gì đó như thế này trên máy mẹ:
sudo ifconfig lo0 alias 192.168.46.49
Sau đó, bạn có thể kiểm tra kết nối từ trong thùng chứa docker bằng telnet. Trong trường hợp của tôi, tôi muốn kết nối với máy chủ xdebug từ xa:
telnet 192.168.46.49 9000
Bây giờ khi lưu lượng truy cập vào máy Mac của bạn được gửi đến 192.168.46.49 (và tất cả lưu lượng truy cập rời khỏi vùng chứa của bạn đi qua máy Mac của bạn), máy Mac của bạn sẽ cho rằng IP là chính nó. Khi bạn kết thúc sử dụng IP này, bạn có thể xóa bí danh loopback như thế này:
sudo ifconfig lo0 -alias 192.168.46.49
Một điều cần cẩn thận là container docker sẽ không gửi lưu lượng đến máy chủ mẹ nếu nó nghĩ đích đến của lưu lượng là chính nó. Vì vậy, hãy kiểm tra giao diện loopback bên trong container nếu bạn gặp sự cố:
sudo ip addr show lo
Trong trường hợp của tôi, điều này cho thấy inet 127.0.0.1/8
điều đó có nghĩa là tôi không thể sử dụng bất kỳ IP nào trong 127.*
phạm vi. Đó là lý do tại sao tôi sử dụng 192.168.*
trong ví dụ trên. Đảm bảo IP bạn sử dụng không xung đột với thứ gì đó trên mạng của bạn.
Đối với những người đang chạy Docker trong AWS, siêu dữ liệu thể hiện cho máy chủ vẫn có sẵn từ bên trong container.
curl http://169.254.169.254/latest/meta-data/local-ipv4
Ví dụ:
$ 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+'
Cách duy nhất là truyền thông tin máy chủ dưới dạng môi trường khi bạn tạo một thùng chứa
run --env <key>=<value>
-e "DOCKER_HOST=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')"
(sử dụng câu trả lời được chấp nhận từ unix.stackexchange.com/questions/87468/ù )
Đây --add-host
có thể là một giải pháp sạch hơn (nhưng không có phần cổng, chỉ có thể xử lý máy chủ với giải pháp này). Vì vậy, trong docker run
lệnh của bạn , hãy làm một cái gì đó như:
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [my container]
Cách thực hành tốt nhất cho hầu hết các ứng dụng muốn thực hiện điều này một cách tự động là: bạn không . Thay vào đó, bạn có người đang chạy container chứa một địa chỉ tên máy chủ / ip bên ngoài làm cấu hình, ví dụ như một biến môi trường hoặc tệp cấu hình. Cho phép người dùng tiêm này cung cấp cho bạn thiết kế di động nhất.
Tại sao điều này sẽ rất khó khăn? Bởi vì các container sẽ, theo thiết kế, sẽ cách ly ứng dụng khỏi môi trường máy chủ. Mạng được đặt tên theo vùng chứa theo mặc định và các chi tiết của máy chủ được bảo vệ khỏi quá trình chạy bên trong vùng chứa có thể không được tin cậy hoàn toàn.
Có các tùy chọn khác nhau tùy thuộc vào tình huống cụ thể của bạn:
Nếu container của bạn đang chạy với mạng máy chủ, thì bạn có thể nhìn vào bảng định tuyến trên máy chủ để xem tuyến đường mặc định. Từ câu hỏi này , các công việc sau đây đối với tôi, vd:
ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'
Một ví dụ cho thấy điều này với mạng máy chủ trong một container trông như sau:
docker run --rm --net host busybox /bin/sh -c \
"ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'"
Đối với một số phiên bản của Docker Desktop, họ đã chèn một mục DNS vào VM nhúng:
getent hosts host.docker.internal | awk '{print $1}'
Nếu bạn đang chạy trong môi trường đám mây, bạn có thể kiểm tra dịch vụ siêu dữ liệu từ nhà cung cấp đám mây, ví dụ: AWS:
curl http://169.254.169.254/latest/meta-data/local-ipv4
Nếu bạn muốn địa chỉ bên ngoài / internet của mình, bạn có thể truy vấn một dịch vụ từ xa như:
curl ifconfig.co
Mỗi trong số đó có những hạn chế và chỉ hoạt động trong các kịch bản cụ thể. Tùy chọn di động nhất vẫn là chạy container của bạn với địa chỉ IP được chèn dưới dạng cấu hình, ví dụ: đây là một tùy chọn chạy ip
lệnh trước đó trên máy chủ và tiêm nó dưới dạng biến môi trường:
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
Lệnh .. Cảm ơn :)
Nếu bạn muốn IP
địa chỉ thực (không phải là cầu nối IP
) Windows
và bạn có docker 18.03
(hoặc gần đây hơn), hãy làm như sau:
Chạy bash trên container từ máy chủ lưu trữ tên hình ảnh nginx
(hoạt động trên Alpine Linux distribution
):
docker run -it nginx /bin/ash
Sau đó chạy bên trong container
/ # nslookup host.docker.internal
Name: host.docker.internal
Address 1: 192.168.65.2
192.168.65.2
là IP của máy chủ - không phải IP cầu nối như trong spinus
câu trả lời được chấp nhận.
Tôi đang sử dụng ở đây host.docker.iternal :
Máy chủ có địa chỉ IP thay đổi (hoặc không có nếu bạn không có quyền truy cập mạng). Từ 18.03 trở đi, khuyến nghị của chúng tôi là kết nối với tên DNS đặc biệt host.docker.iternal, phân giải thành địa chỉ IP nội bộ được sử dụng bởi máy chủ lưu trữ. Mục đích này là dành cho mục đích phát triển và sẽ không hoạt động trong môi trường sản xuất bên ngoài Docker cho Windows.
Alpine Linux
? Nếu không thì kiểm tra tương đương cho cụ thể của bạn linux distribution
.
linux containers
và tôi không sử dụng windows containers
. Bạn có thể làm điều đó bằng cách nhấp chuột phải vào docker icon
và chọn Switch to Linux containers
. Tôi nghĩ rằng điều đó có thể quan trọng khi bạn đang tải xuống hình ảnh. Nếu bạn đã windows container
kiểm tra nếu xóa nginx
hình ảnh cũ và tải lại nó sẽ giúp bạn có một container khác. Nếu nó vẫn không hoạt động cho bạn - hơn bạn có thể thử cài đặt nslookup
trong ash
.
host.docker.internal
) này từ bên trong container
docker run -it --rm alpine nslookup host.docker.internal
... In địa chỉ IP của máy chủ ...
nslookup: can't resolve '(null)': Name does not resolve
Name: host.docker.internal
Address 1: 192.168.65.2
Trên Mac và Windows , bạn có thể sử dụng tên DNS đặc biệt host.docker.internal
.
Máy chủ có địa chỉ IP thay đổi (hoặc không có nếu bạn không có quyền truy cập mạng). Từ 18.03 trở đi, khuyến nghị của chúng tôi là kết nối với tên DNS đặc biệt host.docker.iternal, phân giải thành địa chỉ IP nội bộ được sử dụng bởi máy chủ lưu trữ. Mục đích này là dành cho mục đích phát triển và sẽ không hoạt động trong môi trường sản xuất bên ngoài Docker Desktop cho Mac.
Docker cho Mac Tôi muốn kết nối từ một container đến một dịch vụ trên máy chủ
Máy chủ có địa chỉ IP thay đổi (hoặc không có nếu bạn không có quyền truy cập mạng). Từ 18.03 trở đi, khuyến nghị của chúng tôi là kết nối với tên DNS đặc biệt host.docker.iternal, phân giải thành địa chỉ IP nội bộ được sử dụng bởi máy chủ lưu trữ.
Cổng cũng có thể truy cập được như gateway.docker.iternal. https://docs.docker.com/docker-for-mac/networking/#use-case-and-workaround
Nếu bạn đã bật API từ xa docker ( ví dụ thông qua ) và biết tên máy chủ hoặc địa chỉ IP của máy chủ thì điều này có thể được thực hiện với rất nhiều bash.-H
tcp://0.0.0.0:4243
Trong phạm vi người dùng của tôi 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'
)
Dòng thứ hai lấy ID container từ địa phương của bạn /proc/self/cgroup
tệp .
Dòng thứ ba cuộn tròn với máy chủ (giả sử bạn đang sử dụng 4243 làm cổng của docker) sau đó sử dụng nút để phân tích JSON được trả về cho DESIRED_PORT
.
HostPort
có thể là thông tin hữu ích ở đây, tiếc là HostIp
có thể0.0.0.0
Tôi có Ubuntu 16.03. Cho tôi
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [image]
không KHÔNG làm việc (sai ip được tạo ra)
Giải pháp làm việc của tôi là:
docker run --add-host dockerhost:`docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge` [image]
Đây là một tùy chọn khác cho những người đang chạy Docker trong AWS. Tùy chọn này tránh việc sử dụng apk để thêm gói curl và tiết kiệm 7mb không gian quý giá. Sử dụng wget tích hợp (một phần của nhị phân BusyBox nguyên khối):
wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4
AFAIK, trong trường hợp Docker cho Linux (phân phối chuẩn), địa chỉ IP của máy chủ sẽ luôn là 172.17.0.1
.
Cách dễ nhất để có được nó là thông qua ifconfig
(giao diện docker0) từ máy chủ:
ifconfig
Từ bên trong docker, lệnh sau từ docker: ip -4 route show default | cut -d" " -f3
Bạn có thể chạy nó nhanh chóng trong một docker với dòng lệnh sau:
# 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"
Tôi hy vọng nó sẽ giúp.
Trong linux bạn có thể chạy
HOST_IP=`hostname -I | awk '{print $1}'`
Trong macOS, máy chủ của bạn không phải là máy chủ Docker. Docker sẽ cài đặt hệ điều hành máy chủ lưu trữ trong VirtualBox.
HOST_IP=`docker run busybox ping -c 1 docker.for.mac.localhost | awk 'FNR==2 {print $4}' | sed s'/.$//'`
hostname -I
cảnh báo không "đưa ra bất kỳ giả định nào về thứ tự của đầu ra."
Đây là một triển khai tối giản trong Node.js cho những người đang chạy máy chủ trên các phiên bản AWS EC2 , sử dụng ví dụ Siêu dữ liệu EC2 đã đề cập ở trên
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
và được sử dụng như
ec2(function(err, ip) {
if(err) console.log(err)
else console.log(ip);
})
Nếu bạn đang chạy bộ chứa Windows trên cụm Service Service, địa chỉ IP của máy chủ có sẵn thông qua biến môi trường Fabric_NodeIPOrFQDN
. Dịch vụ biến môi trường vải
Đây là cách tôi làm điều đó. Trong trường hợp này, nó thêm một mục nhập máy chủ vào / etc / hosts trong hình ảnh docker trỏ taurus-host vào máy IP cục bộ của tôi ::
TAURUS_HOST=`ipconfig getifaddr en0`
docker run -it --rm -e MY_ENVIRONMENT='local' --add-host "taurus-host:${TAURUS_HOST}" ...
Sau đó, từ trong Docker container, script có thể sử dụng tên máy chủ taurus-host để thoát ra khỏi máy cục bộ của tôi, nơi chứa container docker.
Có lẽ bộ chứa tôi đã tạo cũng hữu ích https://github.com/qoomon/docker-host
Bạn chỉ có thể sử dụng dns tên container để truy cập hệ thống máy chủ, ví dụ: curl http: // dockerhost: 9200 , do đó không cần phải gặp rắc rối với bất kỳ địa chỉ IP nào.
Giải pháp tôi sử dụng dựa trên "máy chủ" trả về địa chỉ bên ngoài của máy chủ Docker khi nhận được yêu cầu http.
Trên "máy chủ":
1) Bắt đầu jwilder / nginx-proxy
# docker run -d -p <external server port>:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
2) Bắt đầu chứa ipify
# docker run -e VIRTUAL_HOST=<external server name/address> --detach --name ipify osixia/ipify-api:0.1.0
Bây giờ khi một container gửi yêu cầu http đến máy chủ, vd
# curl http://<external server name/address>:<external server port>
địa chỉ IP của máy chủ Docker được ipify trả về qua tiêu đề http "X-Forwarded-For"
Ví dụ (máy chủ ipify có tên "ipify.example.com" và chạy trên cổng 80, máy chủ docker có 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
Bên trong container, bây giờ bạn có thể gọi:
# curl http://ipify.example.com
10.20.30.40
Thử cái này
docker chạy --rm -i --net = máy chủ alpine ifconfig
Trên Ubuntu, hostname
lệnh có thể được sử dụng với các tùy chọn sau:
-i
, --ip-address
địa chỉ cho tên máy chủ-I
, --all-ip-addresses
tất cả địa chỉ cho máy chủVí dụ:
$ hostname -i
172.17.0.2
Để gán cho biến, có thể sử dụng một lớp lót sau:
IP=$(hostname -i)
Với https://docs.docker.com/machine/install-machine/
a) $ docker-máy ip
b) Lấy địa chỉ IP của một hoặc nhiều máy.
$ docker-machine ip host_name
$ docker-machine ip host_name1 host_name2