กล่าวโดยย่อ: ไม่VOLUME
คำแนะนำของคุณไม่ถูกต้อง
Dockerfile VOLUME
ระบุวอลุ่มตั้งแต่หนึ่งตัวขึ้นไปที่กำหนดพา ธ ฝั่งคอนเทนเนอร์ แต่ไม่อนุญาตให้ผู้สร้างรูปภาพระบุเส้นทางโฮสต์ บนฝั่งโฮสต์วอลุ่มนั้นถูกสร้างขึ้นด้วยชื่อ ID ที่ยาวมากภายในรูทของนักเทียบท่า /var/lib/docker/volumes
ในเครื่องของฉันนี้อยู่
หมายเหตุ: เนื่องจากชื่อที่สร้างอัตโนมัติมีความยาวมากและไม่มีเหตุผลจากมุมมองของมนุษย์หนังสือเหล่านี้มักถูกเรียกว่า "ไม่มีชื่อ" หรือ "ไม่ระบุชื่อ"
ตัวอย่างของคุณที่ใช้ '.' ตัวละครจะไม่ทำงานบนเครื่องของฉันไม่ว่าฉันจะทำให้ dot เป็นอาร์กิวเมนต์แรกหรืออาร์กิวเมนต์ที่สอง ฉันได้รับข้อความแสดงข้อผิดพลาดนี้:
นักเทียบท่า: การตอบสนองข้อผิดพลาดจาก daemon: ข้อผิดพลาดรันไทม์ oci: container_linux.go: 265: กระบวนการเริ่มต้นของคอนเทนเนอร์ก่อให้เกิด "process_linux.go: 368: คอนเทนเนอร์ init ทำให้เกิด \" open / dev / ptmx: ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว \ ""
ฉันรู้ว่าสิ่งที่พูดถึงจุดนี้อาจไม่ได้มีค่ามากสำหรับคนที่พยายามจะเข้าใจVOLUME
และ-v
แน่นอนว่ามันไม่ได้เป็นทางออกสำหรับสิ่งที่คุณพยายามทำให้สำเร็จ ดังนั้นหวังว่าตัวอย่างต่อไปนี้จะให้ความกระจ่างเกี่ยวกับปัญหาเหล่านี้มากขึ้น
Minitutorial: การระบุปริมาณ
รับ Dockerfile นี้:
FROM openjdk:8u131-jdk-alpine
VOLUME vol1 vol2
(สำหรับผลลัพธ์ของ minitutorial นี้มันไม่ได้สร้างความแตกต่างถ้าเราระบุvol1 vol2
หรือ/vol1 /vol2
- อย่าถามฉันว่าทำไม)
สร้างมัน:
docker build -t my-openjdk
วิ่ง:
docker run --rm -it my-openjdk
ภายในคอนเทนเนอร์ให้รันls
ในบรรทัดคำสั่งและคุณจะสังเกตเห็นสองไดเรกทอรีอยู่ และ/vol1
/vol2
การเรียกใช้คอนเทนเนอร์ยังสร้างสองไดเรกทอรีหรือ "ไดรฟ์" บนฝั่งโฮสต์
ในขณะที่มีการเรียกใช้คอนเทนเนอร์ให้ดำเนินการdocker volume ls
บนเครื่องโฮสต์และคุณจะเห็นสิ่งนี้ (ฉันได้เปลี่ยนชื่อตรงกลางของชื่อด้วยจุดสามจุดเพื่อความกะทัดรัด):
DRIVER VOLUME NAME
local c984...e4fc
local f670...49f0
กลับไปที่คอนเทนเนอร์ดำเนินการtouch /vol1/weird-ass-file
(สร้างไฟล์เปล่าที่ตำแหน่งดังกล่าว)
ตอนนี้ไฟล์นี้มีอยู่ในเครื่องโฮสต์ในหนึ่งในวอลุ่มที่ไม่มีชื่อ lol ฉันใช้ความพยายามสองครั้งเพราะฉันลองไดรฟ์ข้อมูลที่แสดงรายการแรก แต่ในที่สุดฉันก็พบไฟล์ของฉันในไดรฟ์ข้อมูลที่สองที่แสดงโดยใช้คำสั่งนี้บนเครื่องโฮสต์:
sudo ls /var/lib/docker/volumes/f670...49f0/_data
คุณสามารถลองลบไฟล์นี้บนโฮสต์และไฟล์นั้นจะถูกลบในคอนเทนเนอร์ด้วย
หมายเหตุ: _data
โฟลเดอร์นี้ยังเรียกว่า "จุดเชื่อมต่อ"
ออกจากคอนเทนเนอร์และแสดงรายการไดรฟ์บนโฮสต์ พวกเขาไปแล้ว. เราใช้การ--rm
ตั้งค่าสถานะเมื่อเรียกใช้คอนเทนเนอร์และตัวเลือกนี้จะล้างออกได้อย่างมีประสิทธิภาพไม่เพียง แต่คอนเทนเนอร์เมื่อออก
เรียกใช้คอนเทนเนอร์ใหม่ แต่ระบุปริมาณโดยใช้-v
:
docker run --rm -it -v /vol3 my-openjdk
นี่เป็นการเพิ่มไดรฟ์ข้อมูลที่สามและทั้งระบบสิ้นสุดลงโดยมีโวลุ่มที่ไม่มีชื่อสามรายการ -v vol3
คำสั่งจะมีความล้มเหลวได้เราระบุไว้เท่านั้น อาร์กิวเมนต์ต้องเป็นพา ธสัมบูรณ์ภายในคอนเทนเนอร์ /var/lib/docker/volumes/
ในพื้นที่ฝั่งปริมาณที่สามใหม่จะไม่ระบุชื่อและอาศัยอยู่ร่วมกันกับอีกสองเล่ม
มันถูกระบุไว้ก่อนหน้านี้ว่าDockerfile
ไม่สามารถแมปไปยังโฮสต์พา ธ ซึ่งก่อให้เกิดปัญหาสำหรับเราเมื่อพยายามนำไฟล์จากโฮสต์ไปยังคอนเทนเนอร์ระหว่างรันไทม์ -v
ไวยากรณ์ที่แตกต่างแก้ปัญหานี้
ลองนึกภาพฉันมีโฟลเดอร์ย่อยในไดเรกทอรีโครงการของฉัน./src
ที่ฉันต้องการที่จะซิงค์/src
ภายในภาชนะ คำสั่งนี้ทำเคล็ดลับ:
docker run -it -v $(pwd)/src:/src my-openjdk
ทั้งสองด้านของ:
ตัวละครคาดว่าเส้นทางที่แน่นอน ด้านซ้ายเป็นพา ธ สัมบูรณ์บนเครื่องโฮสต์ด้านขวาเป็นพา ธ สัมบูรณ์ภายในคอนเทนเนอร์ pwd
เป็นคำสั่งที่ "พิมพ์ไดเรกทอรีปัจจุบัน / ทำงาน" การวางคำสั่งใน$()
รับคำสั่งภายในวงเล็บให้รันคำสั่งในเชลล์ย่อยและให้ผลตอบแทนเส้นทางที่แน่นอนไปยังไดเรกทอรีโครงการของเรา
รวบรวมทั้งหมดเข้าด้วยกันสมมติว่าเรามี./src/Hello.java
ในโฟลเดอร์โครงการของเราบนเครื่องโฮสต์โดยมีเนื้อหาดังต่อไปนี้:
public class Hello {
public static void main(String... ignored) {
System.out.println("Hello, World!");
}
}
เราสร้าง Dockerfile นี้:
FROM openjdk:8u131-jdk-alpine
WORKDIR /src
ENTRYPOINT javac Hello.java && java Hello
เรารันคำสั่งนี้:
docker run -v $(pwd)/src:/src my-openjdk
สิ่งนี้พิมพ์ว่า "สวัสดีโลก!"
ส่วนที่ดีที่สุดคือเรามีอิสระอย่างเต็มที่ในการแก้ไขไฟล์. java ด้วยข้อความใหม่สำหรับเอาต์พุตอื่นในการรันครั้งที่สอง - โดยไม่ต้องสร้างภาพ =)
หมายเหตุสุดท้าย
ฉันค่อนข้างใหม่สำหรับนักเทียบท่าและ "บทช่วยสอน" ดังกล่าวสะท้อนข้อมูลที่ฉันรวบรวมจากการแฮ็กบรรทัดคำสั่ง 3 วัน ฉันเกือบละอายใจที่ฉันไม่สามารถให้ลิงก์ไปยังเอกสารที่เหมือนภาษาอังกฤษที่ชัดเจนสำรองข้อมูลของฉันได้ แต่ฉันคิดว่านี่เป็นเพราะขาดเอกสารและไม่ใช่ความพยายามส่วนตัว ฉันรู้ว่าตัวอย่างทำงานตามที่โฆษณาไว้โดยใช้การตั้งค่าปัจจุบันของฉันซึ่งก็คือ "Windows 10 -> Vagrant 2.0.0 -> Docker 17.09.0-ce"
บทช่วยสอนไม่ได้แก้ปัญหา "เราจะระบุเส้นทางของคอนเทนเนอร์ใน Dockerfile อย่างไรและให้คำสั่ง run ระบุเส้นทางโฮสต์เท่านั้น" อาจจะมีวิธีฉันไม่ได้พบมัน
สุดท้ายผมมีความรู้สึกที่ระบุVOLUME
ใน Dockerfile ไม่แปลกเพียง VOLUME
แต่มันอาจจะเป็นวิธีที่ดีที่สุดที่จะไม่ใช้ ด้วยเหตุผลสองประการ เหตุผลแรกที่เราระบุแล้ว: เราไม่สามารถระบุเส้นทางโฮสต์ - ซึ่งเป็นสิ่งที่ดีเพราะ Dockerfiles ควรเป็นผู้ไม่เชื่อเรื่องพระเจ้าที่เฉพาะเจาะจงของเครื่องโฮสต์ แต่เหตุผลที่สองคือคนอาจลืมใช้--rm
ตัวเลือกเมื่อเรียกใช้คอนเทนเนอร์ บางคนอาจจำที่จะลบภาชนะ แต่ลืมที่จะลบระดับเสียง นอกจากนี้ถึงแม้จะมีหน่วยความจำที่ดีที่สุดของมนุษย์ แต่ก็อาจเป็นงานที่น่ากังวลที่จะต้องทราบว่าไดรฟ์ข้อมูลที่ไม่ระบุชื่อใดที่ปลอดภัยในการลบ