ทำความเข้าใจกับคำสั่ง“ VOLUME” ใน DockerFile


136

ด้านล่างนี้คือเนื้อหาของ "Dockerfile" ของฉัน

FROM node:boron

# Create app directory
RUN mkdir -p /usr/src/app

# change working dir to /usr/src/app
WORKDIR /usr/src/app

VOLUME . /usr/src/app

RUN npm install

EXPOSE 8080

CMD ["node" , "server" ]

ในไฟล์นี้ฉันคาดว่าคำสั่ง "VOLUME. / usr / src / app" เพื่อเมานต์เนื้อหาของไดเรกทอรีทำงานปัจจุบันในโฮสต์ที่จะติดตั้งบน / usr / src / app โฟลเดอร์ของคอนเทนเนอร์

โปรดแจ้งให้ฉันทราบว่านี่เป็นวิธีที่ถูกต้องหรือไม่

คำตอบ:


88

บทสอนนักเทียบท่าอย่างเป็นทางการพูดว่า:

วอลุ่มข้อมูลเป็นไดเร็กทอรีที่กำหนดเป็นพิเศษภายในหนึ่งคอนเทนเนอร์ขึ้นไปที่ข้ามระบบไฟล์ยูเนี่ยน ปริมาณข้อมูลมีคุณสมบัติที่มีประโยชน์มากมายสำหรับข้อมูลถาวรหรือข้อมูลที่แชร์:

  • ปริมาณจะเริ่มต้นได้เมื่อสร้างภาชนะ หากอิมเมจพื้นฐานของคอนเทนเนอร์มีข้อมูลที่จุดเมานท์ที่ระบุ
    ข้อมูลที่มีอยู่จะถูกคัดลอกไปยังโวลุ่มใหม่เมื่อ
    เริ่มต้นโวลุ่ม (โปรดทราบว่าสิ่งนี้ไม่สามารถใช้ได้เมื่อติดตั้ง
    ไดเรกทอรีโฮสต์)
  • ปริมาณข้อมูลสามารถใช้ร่วมกันและนำมาใช้ใหม่ในภาชนะ

  • การเปลี่ยนแปลงปริมาณข้อมูลจะทำโดยตรง

  • การเปลี่ยนแปลงปริมาณข้อมูลจะไม่รวมเมื่อคุณอัปเดตรูปภาพ

  • ปริมาณข้อมูลยังคงอยู่แม้ว่าตัวคอนเทนเนอร์จะถูกลบ

ในDockerfileคุณสามารถระบุเพียงปลายทางของปริมาณภายในภาชนะ /usr/src/appเช่น

เมื่อคุณเรียกใช้คอนเทนเนอร์เช่นdocker run --volume=/opt:/usr/src/app my_imageคุณอาจแต่ไม่จำเป็นต้องระบุจุดติดตั้ง ( / opt ) บนเครื่องโฮสต์ ถ้าคุณไม่ได้ระบุประเด็นโต้แย้งแล้วติดจะได้รับเลือกโดยอัตโนมัติมักจะต่ำกว่า--volume/var/lib/docker/volumes/


275

กล่าวโดยย่อ: ไม่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ตัวเลือกเมื่อเรียกใช้คอนเทนเนอร์ บางคนอาจจำที่จะลบภาชนะ แต่ลืมที่จะลบระดับเสียง นอกจากนี้ถึงแม้จะมีหน่วยความจำที่ดีที่สุดของมนุษย์ แต่ก็อาจเป็นงานที่น่ากังวลที่จะต้องทราบว่าไดรฟ์ข้อมูลที่ไม่ระบุชื่อใดที่ปลอดภัยในการลบ


2
เมื่อใดที่เราควรใช้ปริมาณที่ไม่ระบุชื่อ / ไม่ระบุชื่อ
เซีย

10
@ มาร์ตินขอบคุณมาก การแฮ็กตันและบทช่วยสอนที่ได้จากที่นี่นั้นได้รับการชื่นชมเป็นอย่างมาก
Beezer

6
"ฉันไม่สามารถให้ลิงก์เพื่อล้างเอกสารที่เหมือนภาษาอังกฤษได้ ... ฉันคิดว่านี่เป็นเพราะขาดเอกสาร" ฉันสามารถยืนยัน นี่เป็นเอกสารที่ละเอียดที่สุดและเป็นปัจจุบันที่ฉันได้พบและฉันกำลังมองหาเวลาหลายชั่วโมง
user697576

4
docker volume pruneสามารถใช้ในการล้างปริมาณที่เหลือซึ่งไม่ได้เชื่อมต่อกับภาชนะที่ใช้ ไม่ต้องบอกว่ามันจะง่ายต่อการกลั่นแกล้งสิ่งสำคัญที่อาจเกิดขึ้นโดยใช้ id เพียงอย่างเดียว ...
Jeremy

4
"สำหรับผลลัพธ์ของ minitutorial นี้มันไม่ต่างอะไรถ้าเราระบุ vol1 vol2 หรือ / vol1 / vol2 - อย่าถามฉันว่าทำไม" @MartinAndersson นั่นเป็นเพราะไดเรกทอรีการทำงานปัจจุบันคือ/เพื่อให้vol1สัมพันธ์กับที่หายไป/ /vol1ถ้าคุณใช้WORKDIRเพื่อระบุไดเรกทอรีการทำงานอื่น ๆ กว่า/, vol1และ/vol1จะไม่ชี้ไปที่ไดเรกทอรีเดียวกัน
เซบาสเตียน

41

การระบุVOLUMEบรรทัดใน Dockerfile กำหนดค่าบิตของข้อมูลเมตาบนรูปภาพของคุณ แต่การใช้เมทาดาทานั้นสำคัญอย่างไร

ก่อนอื่นสองบรรทัดนี้ทำอะไร:

WORKDIR /usr/src/app
VOLUME . /usr/src/app

WORKDIRบรรทัดมีสร้างไดเรกทอรีถ้ามันไม่ได้อยู่และการปรับปรุงบางส่วนเมตาดาต้าที่ภาพเพื่อระบุเส้นทางที่เกี่ยวข้องทั้งหมดพร้อมกับไดเรกทอรีปัจจุบันสำหรับคำสั่งเหมือนRUNจะอยู่ในสถานที่นั้น VOLUMEบรรทัดมีระบุสองเล่มหนึ่งคือทางญาติ.และอื่น ๆ ที่เป็น/usr/src/appทั้งเพิ่งเกิดขึ้นจะเป็นไดเรกทอรีเดียวกัน บ่อยครั้งที่VOLUMEบรรทัดมีเพียงไดเรกทอรีเดียว แต่สามารถมีได้หลายรายการตามที่คุณทำหรืออาจเป็นรูปแบบอาร์เรย์ของ json

คุณไม่สามารถระบุแหล่งที่มาของปริมาณใน Dockerfile : เป็นแหล่งทั่วไปของความสับสนเมื่อปริมาณที่ระบุใน Dockerfile พยายามที่จะตรงกับไวยากรณ์รันไทม์ของต้นทางและปลายทางที่ภาพสร้างครั้งนี้จะไม่ทำงาน Dockerfile สามารถระบุปลายทางของไดรฟ์ได้เท่านั้น มันจะเป็นการเอาเปรียบความปลอดภัยเล็กน้อยหากใครบางคนสามารถกำหนดแหล่งที่มาของไดรฟ์ข้อมูลได้เนื่องจากพวกเขาสามารถอัพเดตอิมเมจทั่วไปบนฮับ docker เพื่อเมานต์รูทไดเร็กทอรีลงในคอนเทนเนอร์และจากนั้นเปิดใช้กระบวนการพื้นหลังภายในคอนเทนเนอร์ เพิ่มการเข้าสู่ระบบเพื่อ / etc / passwd, กำหนดค่า systemd เพื่อเปิดตัว bitcoin miner ในการรีบูตครั้งต่อไปหรือค้นหาระบบไฟล์สำหรับบัตรเครดิต, SSNs และกุญแจส่วนตัวเพื่อส่งไปยังไซต์ระยะไกล

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

VOLUME แบ่งสิ่งต่าง ๆ :คุณไม่สามารถปิดการใช้งานไดรฟ์เมื่อกำหนดไว้ใน Dockerfile และที่สำคัญRUNคำสั่งในตัวเทียบท่านั้นถูกนำไปใช้กับคอนเทนเนอร์ชั่วคราว ภาชนะบรรจุชั่วคราวเหล่านั้นจะได้รับปริมาณไม่ระบุชื่อชั่วคราว ปริมาณที่ไม่ระบุชื่อนั้นจะเริ่มต้นด้วยเนื้อหาของภาพของคุณ การเขียนใด ๆ ภายในคอนเทนเนอร์จากRUNคำสั่งของคุณจะถูกทำให้เป็นโวลุ่มนั้น เมื่อRUNคำสั่งเสร็จสิ้นการเปลี่ยนแปลงรูปภาพจะถูกบันทึกและการเปลี่ยนแปลงในโวลุ่มที่ไม่ระบุชื่อจะถูกยกเลิก ด้วยเหตุนี้ฉันขอแนะนำอย่างยิ่งต่อการกำหนดVOLUMEภายใน Dockerfile มันส่งผลให้เกิดพฤติกรรมที่ไม่คาดคิดสำหรับผู้ใช้รูปภาพของคุณที่ต้องการขยายภาพด้วยข้อมูลเริ่มต้นในตำแหน่งระดับเสียง

คุณควรระบุปริมาณอย่างไร docker-compose.ymlเพื่อระบุตำแหน่งที่คุณต้องการรวมเล่มกับภาพของคุณให้เป็น ผู้ใช้สามารถปรับเปลี่ยนที่จะปรับตำแหน่งเสียงให้เข้ากับสภาพแวดล้อมท้องถิ่นของพวกเขาและจับการตั้งค่ารันไทม์อื่น ๆ เช่นการเผยแพร่พอร์ตและเครือข่าย

ใครบางคนควรจัดทำเอกสารนี้! พวกเขามี. นักเทียบท่ามีคำเตือนเกี่ยวกับการใช้งาน VOLUME ในเอกสารประกอบของพวกเขาใน Dockerfileพร้อมกับคำแนะนำในการระบุแหล่งที่มาที่รันไทม์:

  • การเปลี่ยนระดับเสียงจากภายใน Dockerfile:หากขั้นตอนบิลด์ใด ๆ เปลี่ยนข้อมูลภายในโวลุ่มหลังจากได้รับการประกาศการเปลี่ยนแปลงเหล่านั้นจะถูกยกเลิก

...

  • ไดเรกทอรีโฮสต์ถูกประกาศ ณ เวลาที่คอนเทนเนอร์:ไดเรกทอรีโฮสต์ (จุดเชื่อมต่อ) นั้นขึ้นอยู่กับลักษณะของโฮสต์ นี่คือเพื่อรักษาความเบาพกพาภาพเนื่องจากไดเรกทอรีโฮสต์ที่กำหนดไม่สามารถรับประกันได้ว่าจะสามารถใช้ได้กับโฮสต์ทั้งหมด ด้วยเหตุผลนี้คุณไม่สามารถเมานต์โฮสต์ไดเรกทอรีจากภายใน Dockerfile VOLUME คำแนะนำและไม่สนับสนุนการระบุhost-dirพารามิเตอร์ คุณต้องระบุจุดเมานต์เมื่อคุณสร้างหรือเรียกใช้คอนเทนเนอร์

36

VOLUMEคำสั่งในDockerfileค่อนข้าง Legit ธรรมดาโดยสิ้นเชิงอย่างดีกับการใช้งานและจะไม่เลิกในอยู่แล้ว เพียงแค่ต้องเข้าใจ

เราใช้เพื่อชี้ไปยังไดเรกทอรีใด ๆ ที่แอปในคอนเทนเนอร์จะเขียนลงไปมาก เราไม่ได้ใช้VOLUMEเพียงเพราะเราต้องการแบ่งปันระหว่างโฮสต์และที่เก็บเช่นไฟล์ปรับแต่ง

คำสั่งต้องการเพียงหนึ่งพารามิเตอร์ พา ธ ไปยังโฟลเดอร์ซึ่งสัมพันธ์กับการWORKDIRตั้งค่าหากจากภายในคอนเทนเนอร์ จากนั้นนักเทียบท่าจะสร้างโวลุ่มในกราฟ (/ var / lib / docker) และเมานต์ลงในโฟลเดอร์ในคอนเทนเนอร์ ตอนนี้คอนเทนเนอร์จะมีที่สำหรับเขียนที่มีประสิทธิภาพสูง หากไม่มีVOLUMEคำสั่งความเร็วในการเขียนไปยังโฟลเดอร์ที่ระบุจะช้ามากเพราะตอนนี้คอนเทนเนอร์กำลังใช้copy on writeกลยุทธ์ในคอนเทนเนอร์เอง copy on writeกลยุทธ์เป็นเหตุผลหลักว่าทำไมเล่มที่มีอยู่

หากคุณเมานต์โฟลเดอร์ที่ระบุโดยVOLUMEคำสั่งคำสั่งจะไม่ทำงานเนื่องจากVOLUMEจะดำเนินการเมื่อคอนเทนเนอร์เริ่มต้นENVเท่านั้น

โดยพื้นฐานแล้วด้วยVOLUMEคำสั่งคุณจะได้รับประสิทธิภาพโดยไม่ต้องติดตั้งไดรฟ์ภายนอก ข้อมูลจะถูกบันทึกข้ามคอนเทนเนอร์ที่ทำงานด้วยโดยไม่มีการเมาต์ภายนอก จากนั้นเมื่อพร้อมก็เพียงแค่ติดตั้งอะไรก็ได้

ตัวอย่างที่ดีบางกรณีใช้:
- บันทึก
- โฟลเดอร์ temp

กรณีการใช้งานที่ไม่ดี:
- ไฟล์คงที่
- กำหนดค่า
- รหัส


2
เกี่ยวกับกรณีการใช้งานตัวอย่างที่ดีและไม่ดีหน้า"dockerfile best-practice"ของ Docker กล่าวว่า: "คุณควรใช้ VOLUME สำหรับชิ้นส่วนที่ไม่แน่นอนและ / หรือที่ผู้ใช้บริการสามารถแก้ไขได้ของรูปภาพ" ฉันคิดว่า configs อยู่ในนั้น
OmerSch

2
มันก็โอเคที่จะชัดเจนเกี่ยวกับVOLUMEdirs สำหรับการกำหนดค่า อย่างไรก็ตามเมื่อคุณเมานท์ตั้งค่าจริง ๆ แล้วคุณจะต้องเมานต์ไดเร็กทอรีนั้นและดังนั้นVOLUMEคำสั่งจะไม่ทำงาน ดังนั้นจึงไม่มีประโยชน์ที่จะใช้VOLUMEคำสั่งบน dir ที่ระบุสำหรับการกำหนดค่า การเตรียมข้อมูลเบื้องต้นของกราฟปริมาณด้วยไฟล์แบบอ่านอย่างเดียวแบบสแตติกนั้นเกินความเป็นจริงอย่างมาก ดังนั้นฉันจึงยืนตามสิ่งที่ฉันพูดไม่จำเป็นต้องมีVOLUMEคำสั่งในการกำหนดค่า
สวรรค์

เล่มอาจมีลักษณะการทำงานที่แตกต่างกันเนื่องจากรายละเอียดการใช้งาน ไฟล์ข้อมูลฐานข้อมูลเหมาะสมในกรณีการใช้งานนี้ แต่สิ่งที่จะเป็นจุดของการจัดเก็บข้อมูลควบคู่ไปกับการจัดเก็บภาชนะ (ชั่วคราว)? นั่นคือปริมาณที่มีอยู่ต่อประสิทธิภาพไม่ถูกต้อง
André Werlang

33

เพื่อให้เข้าใจvolumeคำแนะนำใน dockerfile ได้ดียิ่งขึ้นให้เราเรียนรู้การใช้งานทั่วไปในการใช้งานไฟล์อย่างเป็นทางการของ mysql

VOLUME /var/lib/mysql

การอ้างอิง: https://github.com/docker-library/mysql/blob/3362baccb4352bcf0022014f67c1ec7e6808b8c5/8.0/Dockerfile

นี่/var/lib/mysqlคือตำแหน่งเริ่มต้นของ MySQL ที่จัดเก็บไฟล์ข้อมูล

เมื่อคุณเรียกใช้คอนเทนเนอร์ทดสอบเพื่อการทดสอบเท่านั้นคุณไม่สามารถระบุจุดยึดได้เช่น

docker run mysql:8

จากนั้นอินสแตนซ์คอนเทนเนอร์ mysql จะใช้เส้นทางเมานต์เริ่มต้นซึ่งระบุโดยvolumeคำสั่งใน dockerfile ไดรฟ์ข้อมูลถูกสร้างขึ้นด้วยชื่อ ID ที่ยาวมาก ๆ ภายในรูทของนักเทียบท่าซึ่งเรียกว่าโวลุ่ม "unnamed" หรือ "anonymous" ในโฟลเดอร์ของระบบโฮสต์ / var / lib / docker / volume

/var/lib/docker/volumes/320752e0e70d1590e905b02d484c22689e69adcbd764a69e39b17bc330b984e4

สิ่งนี้สะดวกมากสำหรับการทดสอบอย่างรวดเร็วโดยไม่จำเป็นต้องระบุจุดยึด แต่ยังสามารถรับประสิทธิภาพที่ดีที่สุดได้โดยใช้ระดับเสียงสำหรับแหล่งเก็บข้อมูลไม่ใช่ชั้นของคอนเทนเนอร์

สำหรับการใช้งานอย่างเป็นทางการคุณจะต้องระบุเส้นทางเมานท์โดยใช้วอลลุ่มที่มีชื่อ

docker run  -v /my/own/datadir:/var/lib/mysql mysql:8

คำสั่งเมานต์ไดเร็กทอรี / my / own / datadir จากระบบโฮสต์พื้นฐานเป็น / var / lib / mysql ภายในคอนเทนเนอร์ไดเร็กทอรีข้อมูล / my / own / datadir จะไม่ถูกลบโดยอัตโนมัติแม้จะลบคอนเทนเนอร์ก็ตาม

การใช้ภาพอย่างเป็นทางการของ mysql (โปรดตรวจสอบในส่วน "แหล่งข้อมูลการจัดเก็บ"):

การอ้างอิง: https://hub.docker.com/_/mysql/


2
ฉันชอบคำอธิบายของคุณมาก
LukaszTaraszka

แต่นักเทียบท่าจะบันทึกการเปลี่ยนแปลงต่อไป นอกจากนี้คุณสามารถตั้งค่าเส้นทาง-vใช้งานได้โดยไม่ต้องตั้งค่าระดับเสียงใน Dockerfile
Alex78191

1

ฉันไม่คิดว่าจะใช้ VOLUME ได้ดีในทุกกรณียกเว้นว่าคุณกำลังสร้างภาพสำหรับตัวคุณเองและไม่มีใครจะใช้มัน

ฉันได้รับผลกระทบในทางลบเนื่องจาก VOLUME เปิดเผยในภาพฐานที่ฉันขยายและเพิ่งรู้เรื่องปัญหาหลังจากที่รูปภาพทำงานอยู่แล้วเช่น wordpress ที่ประกาศว่า/var/www/htmlโฟลเดอร์เป็นVOLUMEและนั่นหมายความว่าไฟล์ใด ๆ ที่เพิ่มหรือเปลี่ยนแปลงระหว่าง ขั้นตอนการสร้างจะไม่ได้รับการพิจารณาและการเปลี่ยนแปลงที่เกิดขึ้นจะยังคงมีอยู่แม้ว่าคุณจะไม่รู้ มีวิธีแก้ปัญหาที่น่าเกลียดในการกำหนดเว็บไดเร็กตอรี่ในที่อื่น, แต่นี่เป็นเพียงวิธีแก้ปัญหาที่ไม่ดีสำหรับหนึ่งที่ต้องง่ายกว่า: เพียงแค่ลบคำสั่ง VOLUME

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

โดยทั่วไปแล้วการใช้ VOLUMES นั้นไม่ดีเนื่องจากเหตุผลดังต่อไปนี้ดังที่คำตอบนี้ :

อย่างไรก็ตามคำสั่ง VOLUME มีค่าใช้จ่าย

  • ผู้ใช้อาจไม่ทราบว่ามีการสร้างวอลุ่มที่ไม่มีชื่อและดำเนินการต่อเพื่อใช้พื้นที่เก็บข้อมูลบนโฮสต์นักเทียบท่าหลังจากลบคอนเทนเนอร์
  • ไม่มีวิธีในการลบโวลุ่มที่ประกาศใน Dockerfile รูปภาพแบบดาวน์สตรีมไม่สามารถเพิ่มข้อมูลลงในพา ธ ที่มีปริมาณ

ปัญหาหลังส่งผลให้เกิดปัญหาเช่นนี้

การมีตัวเลือกในการยกเลิกการประกาศโวลุ่มจะช่วยได้ แต่ถ้าคุณทราบปริมาณที่กำหนดไว้ใน dockerfile ที่สร้างภาพ (และ parent dockerfiles!) นอกจากนี้ยังสามารถเพิ่ม VOLUME ใน Dockerfile เวอร์ชันใหม่และทำลายสิ่งที่ไม่คาดคิดสำหรับผู้บริโภคของภาพ

คำอธิบายที่ดีอื่น ( เกี่ยวกับภาพ oracle ที่มี VOLUMEซึ่งถูกลบออก ): https://github.com/oracle/docker-images/issues/640#issuecomment-412647328

กรณีเพิ่มเติมที่ VOLUME สร้างความเสียหายให้กับผู้คน:

คำขอดึงเพื่อเพิ่มตัวเลือกในการตั้งค่าคุณสมบัติของภาพหลัก (รวมทั้ง VOLUME) ถูกปิดและจะถูกกล่าวถึงที่นี่ (และคุณสามารถเห็นหลาย กรณีของคนที่ได้รับผลกระทบเนื่องจากปริมาณที่กำหนดไว้ใน dockerfiles) ซึ่งมีความคิดเห็นด้วยดี คำอธิบายกับ VOLUME:

การใช้ VOLUME ใน Dockerfile นั้นไม่มีค่า หากผู้ใช้ต้องการความคงทนพวกเขาจะต้องแน่ใจว่าได้จัดทำแผนที่ปริมาณเมื่อใช้ภาชนะที่ระบุ มันยากมากที่จะติดตามว่าปัญหาของฉันที่ไม่สามารถตั้งค่าความเป็นเจ้าของไดเรกทอรี (/ var / lib / influxdb) ได้เนื่องจากการประกาศ VOLUME ใน Dockerfile ของ InfluxDB หากไม่มีตัวเลือกประเภท UNVOLUME หรือกำจัดออกไปโดยสิ้นเชิงฉันไม่สามารถเปลี่ยนแปลงสิ่งที่เกี่ยวข้องกับโฟลเดอร์ที่ระบุได้ นี่น้อยกว่าอุดมคติโดยเฉพาะอย่างยิ่งเมื่อคุณตระหนักถึงความปลอดภัยและต้องการระบุ UID ที่แน่นอนรูปภาพควรจะถูกเรียกใช้เพื่อหลีกเลี่ยงผู้ใช้แบบสุ่มที่มีสิทธิ์มากกว่าที่จำเป็นต้องใช้ซอฟต์แวร์บนโฮสต์ของคุณ

ฉันคิดว่า EXPOSE ไม่ดี แต่มันมีผลข้างเคียงน้อย สิ่งเดียวที่ดีที่ฉันเห็นเกี่ยวกับ VOLUME และ EXPOSE เป็นเรื่องเกี่ยวกับเอกสารและฉันจะถือว่าพวกเขาดีถ้าพวกเขาทำหน้าที่เพื่อสิ่งนั้นเท่านั้น (ไม่มีผลข้างเคียงใด ๆ )

TL; DR

ฉันคิดว่าการใช้ VOLUME ที่ดีที่สุดคือเลิกใช้

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