กำหนด IP แบบคงที่ให้กับคอนเทนเนอร์ Docker


205

ตอนนี้ฉันกำลังพยายามกำหนด IP แบบคงที่ 172.17.0.1 เมื่อเริ่มต้นคอนเทนเนอร์นักเทียบท่า

ฉันใช้พอร์ต 2122 เป็นพอร์ต ssh ของคอนเทนเนอร์นี้เพื่อที่ฉันจะให้คอนเทนเนอร์นี้ฟังพอร์ต 2122

sudo docker run -i -t -p 2122:2122 ubuntu

คำสั่งนี้จะเรียกใช้ Docker container ที่มี IP แบบสุ่มเช่น 172.17.0.5 แต่ฉันต้องกำหนด IP เฉพาะให้กับคอนเทนเนอร์

เชลล์สคริปต์ต่อไปนี้คือสิ่งที่ฉันอ้างอิงเอกสารนักเทียบท่าในการตั้งค่าเครือข่ายขั้นสูง

pid=$(sudo docker inspect -f '{{.State.Pid}}' <container_name> 2>/dev/null)
sudo rm -rf /var/run/netns/*
sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid
sudo ip link add A type veth peer name B
sudo brctl addif docker0 A
sudo ip link set A up
sudo ip link set B netns $pid
sudo ip netns exec $pid ip link set eth0 down
sudo ip netns exec $pid ip link delete eth0
sudo ip netns exec $pid ip link set dev B name eth0
sudo ip netns exec $pid ip link set eth0 address 12:34:56:78:9a:bc
sudo ip netns exec $pid ip link set eth0 down
sudo ip netns exec $pid ip link set eth0 up
sudo ip netns exec $pid ip addr add 172.17.0.1/16 dev eth0
sudo ip netns exec $pid ip route add default via 172.17.42.1

เชลล์สคริปต์นี้จะกำหนด IP คงที่ 172.17.0.1 และเชื่อมโยงไปยังโลกที่ดี แต่เมื่อใดก็ตามที่ฉันพยายามที่จะ ssh ภาชนะจากท้องถิ่นของฉันมันไม่ทำงาน ฉันอาจพบปัญหาอะไร


ฉันเกรงว่าจะไม่มีคำตอบง่ายๆสำหรับคำถามนั้นโปรดดูgithub.com/docker/docker/issues/6743และgithub.com/docker/docker/issues/1179และอ่านgithub.com/jpetazzo/pipework
2915097

@larrylo คุณสามารถยืนยันได้ว่าคุณเริ่ม sshd ภายในคอนเทนเนอร์หรือไม่
ไบรอัน

5
คุณกำลังเลิกทำการกำหนดเส้นทางทั้งหมดที่ docker daemon ทำเพื่อคุณ ภาชนะบรรจุไม่ใช่ VMs
user2105103

ใช่ฉันยืนยันว่าฉันสามารถเริ่ม sshd ภายในคอนเทนเนอร์ได้
LarryLo

คำตอบ:


291

ง่ายด้วย Docker รุ่น 1.10.1, สร้าง 9e83765

ก่อนอื่นคุณต้องสร้างเครือข่ายนักเทียบท่าของคุณเอง (mynet123)

docker network create --subnet=172.18.0.0/16 mynet123

เพียงแค่เรียกใช้ภาพ (ฉันจะใช้ Ubuntu เป็นตัวอย่าง)

docker run --net mynet123 --ip 172.18.0.22 -it ubuntu bash

จากนั้นใน ubuntu shell

ip addr

นอกจากนี้คุณสามารถใช้

  • --hostname เพื่อระบุชื่อโฮสต์
  • --add-host เพื่อเพิ่มรายการเพิ่มเติมไปยัง / etc / hosts

เอกสาร (และสาเหตุที่คุณต้องสร้างเครือข่าย) ที่https://docs.docker.com/engine/reference/commandline/network_create/


1
คำตอบที่ดี - เพียงแค่เพิ่มข้อมูลเพิ่มเติม: blog.jessfraz.com/post/ips-for-all-the-things
Ole

@cantSleepNow ด้วยเหตุผลบางอย่างที่ฉันต้องการเพียงแค่ใช้บริดจ์ที่สร้างขึ้นเป็นค่าเริ่มต้นของตัวเองซึ่งถูกสร้างขึ้นในไฟล์อินเตอร์เฟสระหว่างการบูตระบบ (ดังนั้นจึงไม่ได้ถูกสร้างขึ้นโดยใช้เครือข่ายนักสร้าง Docker) คุณช่วยแนะนำฉันได้อย่างไร -ip พารามิเตอร์ (รับที่อยู่ IP ถาวรสำหรับคอนเทนเนอร์) โดยไม่ต้องสร้างบริดจ์ของฉันโดยใช้นักเทียบท่า?
Mohammed Noureldin

@ MohammedNoureldin ฉันไม่เข้าใจอย่างสมบูรณ์ - ดูเหมือนคำถามใหม่ฉันคิดว่าคุณควรถามเช่นนี้
cantSleepNow

@cantSleepNow ฉันหมายความว่าฉันต้องแก้ไขที่อยู่ IP ของคอนเทนเนอร์แม้ว่าฉันจะไม่ได้ใช้บริดจ์แบบกำหนดเอง (ดังนั้น - ไม่สามารถใช้พารามิเตอร์ ip ได้) คุณแนะนำวิธีใดในการรับสิ่งนั้น
Mohammed Noureldin

@ MohammedNoureldin ฉันไม่แน่ใจ ดังที่ฉันพูดไว้โพสต์คำถามของคุณเป็นคำถามไม่ใช่ความคิดเห็น - อาจมีบางคนที่รู้คำตอบ
cantSleepNow

89

สำหรับdocker-composeคุณสามารถใช้ต่อไปนี้docker-compose.yml

version: '2'
services:
  nginx:
    image: nginx
    container_name: nginx-container
    networks:
      static-network:
        ipv4_address: 172.20.128.2
networks:
  static-network:
    ipam:
      config:
        - subnet: 172.20.0.0/16
          #docker-compose v3+ do not use ip_range
          ip_range: 172.28.5.0/24

จากโฮสต์คุณสามารถทดสอบโดยใช้:

docker-compose up -d
curl 172.20.128.2

โมเดิร์นdocker-composeไม่เปลี่ยนที่อยู่ IP ที่บ่อย

วิธีค้นหา ips ของคอนเทนเนอร์ทั้งหมดdocker-composeในการใช้งานบรรทัดเดียว:

for s in `docker-compose ps -q`; do echo ip of `docker inspect -f "{{.Name}}" $s` is `docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $s`; done

หากคุณต้องการทำให้เป็นอัตโนมัติคุณสามารถใช้บางอย่างเช่นส่วนสำคัญตัวอย่างนี้


2
ดูเหมือนว่าจะใช้งานได้เฉพาะใน v2 docker-compose, v3 เข้ากันได้
Andrzej Rehmann

4
เมื่อใช้นักเทียบท่าเขียน v3 + ลบip_range
Andrzej Rehmann

ฉันไม่ได้รับ ip_range ไม่ครอบคลุม subnet หรือไม่ ยังไงก็ตามขอบคุณ! ที่แก้ไขของฉัน "ฉันต้องค้นหา ip ของคอนเทนเนอร์ mongo ของฉันอีกครั้ง" - ปัญหา
เบน

1
มีวิธีในการระบุที่อยู่ IP ในการเขียนรุ่น 3 หรือไม่?
ealeon

2
ip_rangeการแก้ปัญหาการทำงานที่ดีสำหรับฉันโดยไม่ต้อง ฉันใช้เวอร์ชั่น: '3.4'
Mikhail Morfikov

24

ไม่ใช่คำตอบโดยตรง แต่สามารถช่วยได้

ฉันใช้บริการเชื่อมต่อส่วนใหญ่ที่เชื่อมโยงกับ IPS แบบคงที่ของตัวเองโดยใช้วิธีการต่อไปนี้:

  1. ฉันสร้างชื่อแทน ip สำหรับบริการทั้งหมดในโฮสต์นักเทียบท่า
  2. จากนั้นฉันเรียกใช้แต่ละบริการที่เปลี่ยนเส้นทางพอร์ตจาก ip นี้ไปยังคอนเทนเนอร์เพื่อให้บริการแต่ละรายการมี IP แบบคงที่ซึ่งผู้ใช้ภายนอกและคอนเทนเนอร์อื่นสามารถใช้งานได้

ตัวอย่าง:

docker run --name dns --restart=always -d -p 172.16.177.20:53:53/udp dns
docker run --name registry --restart=always -d -p 172.16.177.12:80:5000 registry
docker run --name cache --restart=always -d -p 172.16.177.13:80:3142 -v /data/cache:/var/cache/apt-cacher-ng cache
docker run --name mirror --restart=always -d -p 172.16.177.19:80:80 -v /data/mirror:/usr/share/nginx/html:ro mirror
...

ขอบคุณ ~ ฉันรู้สิ่งนี้ เช่นเดียวกับgithub.com/brandon-rhodes/fopnp/tree/m/playgroundทำ ฉันจะลองดู
LarryLo

1
นี้เป็นทางออกที่ดีมากผมก็จะแนบลิงค์นี้สำหรับผู้ใช้ใหม่ในการเรียนรู้เกี่ยวกับ aliasing cyberciti.biz/faq/...
โมฮัมเหม็ Noureldin

ขอบคุณสำหรับการแก้ปัญหาที่ดี
RavinderSingh13

4

มันใช้งานได้สำหรับฉัน

สร้างเครือข่ายด้วย docker network create --subnet=172.17.0.0/16 selnet

เรียกใช้อิมเมจนักเทียบท่า docker run --net selnet --ip 172.18.0.2 hub

ตอนแรกฉันได้

docker: Error response from daemon: Invalid address 172.17.0.2: It does not belong to any of this network's subnets.
ERRO[0000] error waiting for container: context canceled

วิธีแก้ปัญหา: เพิ่มสี่ส่วนที่สองของ IP [.18 แทน. 17.]


3
มีคำตอบที่คล้ายกัน / เหมือนกันที่อายุมากกว่า 2 ปีที่อื่นในหน้านี้: stackoverflow.com/a/35359185/694469
KajMagnus

2

ฉันสะดุดปัญหานี้ระหว่างพยายามเชื่อมต่อAvahiซึ่งจำเป็นต้องทราบว่า IP สาธารณะทำงานได้อย่างถูกต้อง การกำหนด IP แบบคงที่ให้กับคอนเทนเนอร์นั้นยุ่งยากเนื่องจากขาดการสนับสนุนการกำหนด IP แบบคงที่ใน Docker

บทความนี้อธิบายเทคนิคการกำหนด IP แบบคงที่ให้กับคอนเทนเนอร์บนDebian :

  1. DOCKER_OPTS="--bridge=br0 --ip-masq=false --iptables=false"บริการเทียบท่าควรจะเริ่มต้นด้วย ฉันคิดว่าbr0บริดจ์นั้นได้รับการกำหนดค่าแล้ว

  2. ควรเริ่มคอนเทนเนอร์ด้วย --cap-add=NET_ADMIN --net=bridge

  3. ภาชนะภายในpre-up ip addr flush dev eth0ใน/etc/network/interfacesสามารถใช้ในการยกเลิกที่อยู่ IP ได้รับมอบหมายจากหางดังตัวอย่างต่อไปนี้:


auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
    pre-up ip addr flush dev eth0
    address 192.168.0.249
    netmask 255.255.255.0
    gateway 192.168.0.1
  1. /etc/init.d/networking startสคริปต์รายการของคอนเทนเนอร์ที่ควรเริ่มต้นด้วย สคริปต์รายการต้องแก้ไขหรือเติม/etc/hostsไฟล์เพื่อลบการอ้างอิงไปยัง IP ที่นักเทียบท่ากำหนด

2

คุณสามารถตั้งค่า IP ในขณะที่ทำงาน

docker run --cap-add=NET_ADMIN -dit imagename /bin/sh -c "/sbin/ip addr add 172.17.0.12 dev eth0; bash"

ดูตัวอย่างของฉันได้ที่https://github.com/RvdGijp/mariadb-10.1-galera


น่าเสียดายที่นี่เพิ่มที่อยู่ IP อีกหนึ่งรายการหากมีการกำหนดที่อยู่ IP ในกระบวนการก่อนหน้านี้จะส่งผลให้มีที่อยู่ IP สองแห่ง
เดฟ

1

คุณสามารถเข้าถึงบริการตู้คอนเทนเนอร์อื่น ๆ โดยใช้ชื่อของพวกเขา ( ping apacheจะได้รับ ip หรือcurl http://apacheจะเข้าถึงบริการ http) และนี่อาจเป็นทางเลือกของ ip แบบคงที่


3
ในรุ่นนักเทียบท่า 1.8 ใช้งานได้โดยตรง ในเวอร์ชันที่ใหม่กว่าคุณต้องเชื่อมโยงคอนเทนเนอร์เหล่านี้อย่างเด็ดขาด
Guisong He

0

ถ้าคุณต้องการให้คอนเทนเนอร์ของคุณมีซ็อกเก็ตอีเธอร์เน็ตเสมือน (มีที่อยู่ MAC ของตัวเอง), iptables จากนั้นใช้ไดรเวอร์ Macvlan อาจจำเป็นต้องกำหนดเส้นทางการรับส่งข้อมูลไปยัง / เราเตอร์ของคุณ

https://docs.docker.com/engine/userguide/networking/get-started-macvlan

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.