วิธีเชื่อมต่อกับ Docker container จากภายนอกโฮสต์ (เครือข่ายเดียวกัน) [Windows]


89

ฉันได้สร้างคอนเทนเนอร์นักเทียบท่าแรกของฉันมันใช้งานเซิร์ฟเวอร์โดยใช้ Go แต่ฉันไม่สามารถเข้าถึงจากภายนอกคอมพิวเตอร์โฮสต์ ฉันเพิ่งเริ่มต้นด้วยนักเทียบท่าดังนั้นฉันจึงหลงทางที่นี่เล็กน้อย

ดังนั้นฉันจึงมีโค้ด Go ที่ง่ายมากที่เริ่มต้นเซิร์ฟเวอร์ฉันได้สร้างอิมเมจนักเทียบท่าที่ติดตั้ง Go และสร้างโค้ดในอิมเมจพื้นฐานของ Linux ฉันใช้งานเซิร์ฟเวอร์บนพอร์ต 8080 ดังนั้นฉันจึงเปิดเผยพอร์ตนั้นกับโฮสต์ที่เรียกใช้คอนเทนเนอร์ดังนี้:

docker run -p 8080:8080 dockertest

ใช้งานได้และฉันสามารถเข้าถึงเซิร์ฟเวอร์ผ่าน IP เครื่องของนักเทียบท่า (อันที่ปรากฏบนDocker Quickstart Terminalเมื่อเริ่มต้น) ปัญหาคือฉันไม่สามารถเข้าถึงเว็บไซต์ที่ฉันโฮสต์จากภายนอกโฮสต์ได้ดังนั้นถ้าฉันลอง เพื่อเปิดที่อยู่ IP เดียวกันบนโทรศัพท์ของฉันมันทำให้ฉันมีข้อผิดพลาด: หน้าเว็บนี้ไม่พร้อมใช้งาน (ERR_CONNECTION_TIMED_OUT)

ฉันได้ลองระบุ IP เช่นนี้ด้วย:

docker run -p 192.168.0.157:8080:8080 dockertest

แต่เมื่อฉันทำเช่นนั้นฉันสามารถเข้าถึงเว็บไซต์ผ่าน IP ของเครื่องเทียบท่าหรือ IP ที่ระบุในบรรทัดคำสั่งด้านบน ฉันไม่แน่ใจว่าควรจะเขียน IP ใดในคำสั่งนั้นฉันใช้ IP ของคอมพิวเตอร์ฉันได้ลอง 127.0.0.1 (localhost) ด้วย แต่นั่นก็ให้ผลลัพธ์เดียวกัน: ไม่สามารถเข้าถึงเว็บไซต์ผ่านทางใด ๆ IP แต่อย่างใด

ฉัน googled ปัญหานี้และพบคำถาม StackOverflow มากมาย แต่ก็ไม่ได้ช่วยฉันแก้ปัญหาของฉันส่วนใหญ่มุ่งเน้นไปที่ Linux หรือ Mac ดังนั้นวิธีแก้ปัญหาจึงไม่สามารถใช้ได้กับสถานการณ์ของฉัน

นอกจากนี้ฉันสามารถเรียกใช้รหัส Go บนคอมพิวเตอร์และเข้าถึงเว็บไซต์จากอุปกรณ์อื่นในเครือข่ายเดียวกันผ่าน IP ของคอมพิวเตอร์ ฉันไม่เข้าใจว่าทำไมฉันถึงไม่สามารถเข้าถึงได้เมื่อฉันใช้งานในเครื่องเทียบท่ามันเกิดขึ้นกับฉันว่ามันอาจเกี่ยวข้องกับการส่งต่อ IP หรืออะไรบางอย่าง แต่ฉันเป็น noob ที่สมบูรณ์ในระบบเครือข่ายฉัน ส่วนใหญ่เป็นนักพัฒนาเว็บและแทบไม่มีประสบการณ์ในการใช้งานเจ้าของภาษาเลย


คุณใช้ EXPOSE 8080 ใน Dockerfile ร่วมกับตัวเลือก -p หรือไม่? นอกจากนี้ตรวจสอบเพื่อดูว่าพอร์ต 8080 ในกล่องที่คอนเทนเนอร์ของคุณกำลังทำงานอยู่นั้นไม่ได้ถูกบล็อกโดยกฎความปลอดภัยของคุณ
keda

@keda ใช่ Dockerfile มี EXPOSE 8080 ฉันใช้งานคอนเทนเนอร์ในเครื่องคอมพิวเตอร์ของฉันผ่าน Quickstart Terminal ของ Docker ฉันลองปิดไฟร์วอลล์ Windows ด้วย แต่ก็ไม่ได้ผลฉันไม่รู้ว่ามีการตั้งค่าบางอย่างหรือไม่ 'm หายไป
redsalt

คำตอบ:


91

TL; DRตรวจสอบโหมดเครือข่ายของโฮสต์ VirtualBox ของคุณ - ควรเป็นbridgedหากคุณต้องการให้เครื่องเสมือน (และคอนเทนเนอร์ Docker ที่โฮสต์อยู่) สามารถเข้าถึงได้บนเครือข่ายท้องถิ่นของคุณ


ดูเหมือนความสับสนของคุณจะอยู่ที่โฮสต์ที่จะเชื่อมต่อเพื่อเข้าถึงแอปพลิเคชันของคุณผ่าน HTTP คุณยังไม่ได้สะกดว่าการกำหนดค่าของคุณคืออะไรฉันจะเดาตามข้อเท็จจริงที่ว่าคุณมี "Windows" และ "VirtualBox" ในแท็กของคุณ

ฉันเดาว่าคุณมี Docker ที่ทำงานบน Linux บางอย่างที่ทำงานใน VirtualBox บนโฮสต์ Windows ฉันจะติดป้ายกำกับที่อยู่ IP ดังนี้:

D = ที่อยู่ IP ของคอนเทนเนอร์ Docker

L = ที่อยู่ IP ของโฮสต์ Linux ที่ทำงานใน VirtualBox

W = ที่อยู่ IP ของโฮสต์ Windows

เมื่อคุณเรียกใช้แอปพลิเคชัน Go บนโฮสต์ Windows คุณสามารถเชื่อมต่อได้http://W:8080/จากทุกที่ในเครือข่ายท้องถิ่นของคุณ วิธีนี้ใช้ได้ผลเนื่องจากแอปพลิเคชัน Go ผูกพอร์ต 8080 บนเครื่อง Windows และใครก็ตามที่พยายามเข้าถึงพอร์ต 8080 ตามที่อยู่ IP Wจะได้รับการเชื่อมต่อ

และนี่คือจุดที่ซับซ้อนมากขึ้น:

VirtualBox เมื่อตั้งค่าเครื่องเสมือน (VM) สามารถกำหนดค่าเครือข่ายในโหมดต่างๆได้หลายโหมด ผมจำไม่ได้สิ่งที่ทุกตัวเลือกที่แตกต่างกันมี bridgedแต่คนที่คุณต้องการคือ ในโหมดนี้ VirtualBox จะเชื่อมต่อเครื่องเสมือนกับเครือข่ายท้องถิ่นของคุณราวกับว่าเป็นเครื่องสแตนด์อะโลนบนเครือข่ายเช่นเดียวกับเครื่องอื่น ๆ ที่เสียบเข้ากับเครือข่ายของคุณ ในbridgedโหมดเครื่องเสมือนจะปรากฏบนเครือข่ายของคุณเหมือนกับเครื่องอื่น ๆ โหมดอื่น ๆ จะตั้งค่าต่างกันและเครื่องจะมองไม่เห็นบนเครือข่ายของคุณ

ดังนั้นสมมติว่าคุณตั้งค่าระบบเครือข่ายได้อย่างถูกต้องสำหรับโฮสต์ลินุกซ์ ( bridged) โฮสต์ลินุกซ์จะมีที่อยู่ IP ในเครือข่ายท้องถิ่นของคุณ (บางอย่างเช่น 192.168.0.x) http://L:8080/และคุณจะสามารถเข้าถึงคอนเทนเนอร์หางของคุณได้ที่

ถ้าโฮสต์ลินุกซ์จะทำงานในโหมดอื่น ๆ กว่าบางbridgedคุณอาจจะสามารถที่จะเข้าถึงจากโฮสต์ Windows แต่นี้จะขึ้นอยู่กับว่าสิ่งที่โหมดมันอยู่ใน

แก้ไข - จากความคิดเห็นด้านล่างดูเหมือนว่าสถานการณ์ที่ฉันอธิบายไว้ข้างต้นนั้นถูกต้อง

ขอสำรองข้อมูลเล็กน้อยนี่คือวิธีการทำงานของ Docker บนคอมพิวเตอร์ของฉัน (Ubuntu Linux)

ลองนึกภาพว่าฉันใช้คำสั่งเดียวกับที่คุณมี: docker run -p 8080:8080 dockertest. สิ่งนี้จะเริ่มต้นคอนเทนเนอร์ใหม่ตามdockertestอิมเมจและส่งต่อ (เชื่อมต่อ) พอร์ต 8080 บนโฮสต์ Linux (พีซีของฉัน) ไปยังพอร์ต 8080 บนคอนเทนเนอร์ Docker ตั้งค่าเครือข่ายภายในของตนเอง (พร้อมชุดที่อยู่ IP ของตัวเอง) เพื่อให้ Docker daemon สื่อสารและอนุญาตให้คอนเทนเนอร์สื่อสารกันได้ โดยพื้นฐานแล้วสิ่งที่คุณกำลังทำอยู่นั้น-p 8080:8080คือการเชื่อมต่อเครือข่ายภายในของ Docker กับเครือข่าย "ภายนอก" นั่นคือ อะแดปเตอร์เครือข่ายของโฮสต์ - บนพอร์ตเฉพาะ

กับฉันจนถึงตอนนี้? ตกลงตอนนี้ลองย้อนกลับไปดูระบบของคุณ เครื่องของคุณกำลังใช้งาน Windows - Docker ไม่ (ในปัจจุบัน) ทำงานบน Windows ดังนั้นเครื่องมือที่คุณใช้จึงตั้งค่าโฮสต์ Linux ในเครื่องเสมือน VirtualBox เมื่อคุณทำdocker runในสภาพแวดล้อมของคุณสิ่งเดียวกันก็เกิดขึ้น - พอร์ต 8080 บนโฮสต์ Linux เชื่อมต่อกับพอร์ต 8080 บนคอนเทนเนอร์ ความแตกต่างใหญ่ที่นี่คือโฮสต์ Windows ของคุณไม่ใช่โฮสต์ Linux ที่คอนเทนเนอร์กำลังทำงานอยู่ดังนั้นจึงมีเลเยอร์อื่นอยู่ที่นี่และเป็นการสื่อสารข้ามเลเยอร์นี้ซึ่งคุณกำลังประสบปัญหา

สิ่งที่คุณต้องการคือหนึ่งในสองสิ่ง:

  1. เพื่อเชื่อมต่อพอร์ต 8080 บน VirtualBox VM กับพอร์ต 8080 บนโฮสต์ Windows เช่นเดียวกับที่คุณเชื่อมต่อคอนเทนเนอร์ Docker กับพอร์ตโฮสต์

  2. เพื่อเชื่อมต่อ VirtualBox VM โดยตรงกับเครือข่ายท้องถิ่นของคุณด้วยbridgedโหมดเครือข่ายที่ฉันอธิบายไว้ข้างต้น

หากคุณเลือกตัวเลือกแรกคุณจะสามารถเข้าถึงคอนเทนเนอร์ได้โดยที่http://W:8080ที่Wอยู่ IP หรือชื่อโฮสต์ของโฮสต์ Windows หากคุณเลือกข้อที่สองคุณจะสามารถเข้าถึงคอนเทนเนอร์ได้โดยที่http://L:8080ที่Lอยู่ IP หรือชื่อโฮสต์ของ Linux VM

นั่นคือคำอธิบายระดับสูงทั้งหมด - ตอนนี้คุณต้องหาวิธีเปลี่ยนการกำหนดค่าของ VirtualBox VM และนี่คือสิ่งที่ฉันไม่สามารถช่วยคุณได้จริงๆ - ฉันไม่รู้ว่าคุณใช้เครื่องมืออะไรทำทั้งหมดนี้บนเครื่อง Windows ของคุณและฉันไม่คุ้นเคยกับการใช้ Docker บน Windows เลย

หากคุณสามารถไปที่หน้าต่างการกำหนดค่า VirtualBox คุณสามารถทำการเปลี่ยนแปลงตามที่อธิบายไว้ด้านล่าง นอกจากนี้ยังมีไคลเอนต์บรรทัดคำสั่งที่จะแก้ไข VM แต่ฉันไม่คุ้นเคยกับสิ่งนั้น

สำหรับbridgedโหมด (และนี่เป็นทางเลือกที่ง่ายที่สุด) ให้ปิด VM ของคุณคลิกปุ่ม "การตั้งค่า" ที่ด้านบนจากนั้นเปลี่ยนโหมดเครือข่ายเป็นbridgedจากนั้นรีสตาร์ท VM เท่านี้ก็พร้อมใช้งาน VM ควรรับที่อยู่ IP บนเครือข่ายท้องถิ่นของคุณผ่าน DHCP และคอมพิวเตอร์เครื่องอื่นในเครือข่ายควรมองเห็นได้ด้วยที่อยู่ IP นั้น


1
ฉันสามารถค้นหา IP ได้เพียง 2 รายการเท่านั้นซึ่งเป็นรายการที่ Docker แสดงเมื่อฉันเปิด Quickstart Terminal (192.168.99.100) และที่คอมพิวเตอร์ของฉันมี (192.168.0.157) โดยใช้docker run -p 8080:8080 dockertestฉันสามารถเข้าถึงเว็บไซต์ของฉันได้โดยใช้http://192.168.99.100:8080เฉพาะจากคอมพิวเตอร์ Windows ของฉัน ( โฮสต์) ไม่ใช่จากโทรศัพท์ของฉัน หากฉันใช้docker run -p 192.168.0.157:8080:8080 dockertestฉันไม่สามารถเข้าถึงเว็บไซต์ด้วย IP จากที่ใดก็ได้ ฉันไม่แน่ใจว่าจะตั้งค่าระบบเครือข่ายอย่างไรฉันลองใช้แล้ว--net=bridgeแต่ก็ไม่ได้ผลเช่นกัน ฉันคิดว่าจะเปิด VirtualBox หรือไม่? ฉันไม่สามารถทำได้โดยใช้เทอร์มินัลของ Docker?
redsalt

ปัญหาไม่ได้อยู่ที่ Docker ดังนั้นไม่ได้ Docker ไม่สามารถช่วยคุณได้ ฉันจะเพิ่มการแก้ไขเพื่ออธิบายสิ่งที่ฉันคิดว่าเกิดขึ้น
Kryten

โอเคขอบคุณ! ตอนนี้ฉันเข้าใจแล้วฉันสับสนกับส่วนเครื่องเสมือน Linux ทั้งหมด ฉันรู้สึกประทับใจ Docker กำลังใช้ Virtual Box สำหรับสิ่งภายในที่ฉันไม่คิดว่าจะสัมผัส จริงๆแล้วมันง่ายมากฉันต้องเปลี่ยนเป็นbridgedVirtual Box และตอนนี้มันก็ใช้งานได้อย่างมหัศจรรย์ขอบคุณมาก
redsalt

ไม่มีวิธีใดที่จะมีหน้าต่างและคอนเทนเนอร์นักเทียบท่าในเครือข่ายเดียวกันดังนั้นเราจึงสามารถเข้าถึงคอนเทนเนอร์ได้โดยตรงโดยไม่ต้องส่งต่อพอร์ต
Vituel

สะดุดกับสิ่งนี้เมื่อค้นหาการเรียกใช้เซิร์ฟเวอร์ Jupyter ในนักเทียบท่าและพยายามเข้าถึงผ่าน LAN ฉันจะรู้ได้อย่างไรว่า L คืออะไรหลังจากเปลี่ยนโหมดเป็นบริดจ์แล้ว?
PaulDong

122
  1. เปิด Oracle VM VirtualBox Manager
  2. เลือก VM ที่ Docker ใช้
  3. คลิกการตั้งค่า -> เครือข่าย
  4. อะแดปเตอร์ 1 (ค่าเริ่มต้น?) ควรเป็น "แนบกับ: NAT"
  5. คลิกขั้นสูง -> การส่งต่อพอร์ต
  6. เพิ่มกฎ: Protocol TCP, Host Port 8080, Guest Port 8080 (ปล่อยให้ Host IP และ Guest IP ว่าง)
  7. แขกคือคอนเทนเนอร์นักเทียบท่าของคุณและโฮสต์คือเครื่องของคุณ

ตอนนี้คุณควรจะสามารถเรียกดูคอนเทนเนอร์ของคุณผ่าน localhost: 8080 และ your-internal-ip: 8080


10
ยืนยันดีและง่าย
Dirk

2
คำตอบที่ดีที่สุดไม่มีคำอธิบายมากมายเหมือนที่เลือก
Amir Qayyum Khan

2
สำหรับผู้ใช้เร่ร่อนให้เพิ่มสิ่งนี้ใน vagrantfile: config.vm.network "forwarded_port", guest: 8080, host: 8080, protocol: "tcp"
Vince Verhoeven

3
โย่! สิ่งนี้ได้ผลอย่างมีเสน่ห์! ขอบคุณ !!!! ฉันใช้เวลาหลายชั่วโมงในการพยายามคิดออก
Joseph Freeman

2
นี่เป็นทางออกที่ยอดเยี่ยมสำหรับทุกคนที่ใช้ Docker ผ่าน VBox!
Mirodinho

7

หลังจากลองทำหลายอย่างสิ่งนี้ใช้ได้ผลสำหรับฉัน:

  • ใช้แฟล็ก --publish = 0.0.0.0: 8080: 8080 docker
  • ตั้งค่าโหมดเครือข่าย virtualbox เป็น NAT และอย่าใช้การส่งต่อพอร์ตใด ๆ

ด้วยที่อยู่อื่นที่0.0.0.0ฉันไม่ประสบความสำเร็จ


4

TLDR:หากคุณเปิดใช้งาน Windows Firewall ตรวจสอบให้แน่ใจว่ามีข้อยกเว้นสำหรับ "vpnkit" บนเครือข่ายส่วนตัว

สำหรับกรณีเฉพาะของฉันฉันพบว่า Windows Firewall บล็อกการเชื่อมต่อของฉันเมื่อฉันพยายามไปที่พอร์ตที่เผยแพร่ของคอนเทนเนอร์จากเครื่องอื่นบนเครือข่ายท้องถิ่นของฉันเนื่องจากการปิดใช้งานทำให้ทุกอย่างทำงานได้

อย่างไรก็ตามฉันไม่ต้องการปิดการใช้งานไฟร์วอลล์ทั้งหมดเพียงเพื่อให้ฉันสามารถเข้าถึงบริการของคอนเทนเนอร์ของฉันได้ สิ่งนี้ทำให้เกิดคำถามว่า "แอป" ใดที่รับฟังในนามของบริการคอนเทนเนอร์ของฉัน หลังจากพบเธรด SO อื่นที่สอนให้ฉันใช้netstat -a -bเพื่อค้นหาแอปที่อยู่เบื้องหลังซ็อกเก็ตการฟังในเครื่องของฉันฉันได้เรียนรู้ว่ามันเป็นvpnkit.exeเช่นนั้นซึ่งมีรายการในการตั้งค่าไฟร์วอลล์ Windows ของฉันอยู่แล้ว แต่ "เครือข่ายส่วนตัว" ถูกปิดใช้งานและ เมื่อฉันเปิดใช้งานฉันสามารถเยี่ยมชมบริการของคอนเทนเนอร์จากเครื่องอื่นได้โดยไม่ต้องปิดไฟร์วอลล์ทั้งหมด


ท่านช่วยฉันจากความขุ่นมัวหลายชั่วโมงหลายชั่วโมง ขอบคุณ.
Behdad

2

นี่เป็นปัญหาที่พบบ่อยที่สุดสำหรับผู้ใช้ Windows ในการเรียกใช้ Docker Containers IMO นี่คือ "คำถามล้านดอลลาร์บน Docker"; @ "Rocco Smit" ได้ชี้ให้เห็นอย่างถูกต้องว่า "การรับส่งข้อมูลขาเข้าเนื่องจากถูกปิดใช้งานโดยค่าเริ่มต้นบนไฟร์วอลล์ของเครื่องโฮสต์ของฉัน"; ในกรณีของฉันซอฟต์แวร์ McAfee Anti Virus ฉันได้เพิ่มพอร์ตเพิ่มเติมที่จะได้รับอนุญาตสำหรับการรับส่งข้อมูลขาเข้าจากคอมพิวเตอร์เครื่องอื่นบน Wifi LAN เดียวกันในการตั้งค่าไฟร์วอลล์ของ McAfee จากนั้นมันก็เป็นเวทมนตร์ ฉันดิ้นรนมานานกว่าหนึ่งสัปดาห์ในการท่องอินเทอร์เน็ตเอกสาร SO, Docker, บทช่วยสอนหลังบทช่วยสอนที่เกี่ยวข้องกับ Networking of Docker และภาพประกอบจำนวนมากของ "ไม่รองรับบน Windows" สำหรับผู้ใช้ "macvlan", "ipvlan", " สะพานที่กำหนด "และแม้กระทั่งเธรด SO เดียวกันนี้สองสามครั้ง ฉันเริ่มท่อง Google ด้วย "มีใครใช้ Docker ในการผลิตหรือไม่" (ใช่ฉันรู้ว่า Linux เป็นที่นิยมสำหรับปริมาณงาน Prod มากกว่าเมื่อเทียบกับเซิร์ฟเวอร์ Windows) เนื่องจากฉันไม่สามารถเข้าถึงได้ (จากมือถือของฉันใน WiFi ที่บ้านเดียวกัน) nginx แอพที่ติดตั้งใน Docker Container บน Windows ท้ายที่สุดจะดีแค่ไหนถ้าคุณไม่สามารถเข้าถึงแอปพลิเคชัน (ติดตั้งบน Docker Container) จากคอมพิวเตอร์ / อุปกรณ์อื่น ๆ ใน LAN เดียวกันอย่างน้อยที่สุด ในกรณีของฉันปัญหาคือไฟร์วอลล์ปิดกั้นการรับส่งข้อมูลขาเข้า หากคุณไม่สามารถเข้าถึงแอปพลิเคชัน (ติดตั้งบน Docker Container) จากคอมพิวเตอร์ / อุปกรณ์อื่น ๆ ใน LAN เดียวกันอย่างน้อยที่สุด ในกรณีของฉันปัญหาคือไฟร์วอลล์ปิดกั้นการรับส่งข้อมูลขาเข้า หากคุณไม่สามารถเข้าถึงแอปพลิเคชัน (ติดตั้งบน Docker Container) จากคอมพิวเตอร์ / อุปกรณ์อื่น ๆ ใน LAN เดียวกันอย่างน้อยที่สุด ในกรณีของฉันปัญหาคือไฟร์วอลล์ปิดกั้นการรับส่งข้อมูลขาเข้า


0

ฉันพบว่าพร้อมกับการตั้งค่าพอร์ต -p Docker สำหรับ Windows ใช้ vpnkit และการรับส่งข้อมูลขาเข้าเนื่องจากถูกปิดใช้งานโดยค่าเริ่มต้นในไฟร์วอลล์ของเครื่องโฮสต์ของฉัน หลังจากเปิดใช้งานกฎ TCP ขาเข้าสำหรับ vpnkit ฉันสามารถเข้าถึงคอนเทนเนอร์ของฉันจากเครื่องอื่นบนเครือข่ายท้องถิ่นได้

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