ไดรฟ์ข้อมูลการติดตั้งนักเทียบท่าบนโฮสต์


135

ฉันสามารถแชร์โฟลเดอร์ระหว่างคอนเทนเนอร์นักเทียบท่ากับไดรฟ์ข้อมูลโดยใช้ไฟล์

docker run -v /host/path:/container/path ...

แต่คำถามของฉันคือความแตกต่างระหว่างสิ่งนี้กับการใช้VOLUMEคำสั่งใน Dockerfile

VOLUME /path

ฉันใช้รูปภาพที่มีVOLUMEคำสั่งและฉันต้องการทราบวิธีแบ่งปันกับโฮสต์ของฉัน ฉันได้ทำโดยใช้-vคำสั่งด้านบน แต่ฉันไม่รู้ว่าฉันต้องการทั้ง. -vและVOLUME.

คำตอบ:


155

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

แนวคิดก็คือคุณสามารถแชร์ไดรฟ์ข้อมูลของคุณระหว่างคอนเทนเนอร์นักเทียบท่าของคุณและจะคงอยู่ตราบเท่าที่มีคอนเทนเนอร์ (ทำงานหรือหยุดทำงาน) ที่อ้างอิงถึง

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

ความแตกต่างพื้นฐานระหว่างVOLUMEและ-vคือสิ่งนี้: -vจะติดตั้งไฟล์ที่มีอยู่จากระบบปฏิบัติการของคุณภายในคอนเทนเนอร์นักเทียบท่าของคุณและVOLUMEจะสร้างโวลุ่มใหม่ที่ว่างเปล่าบนโฮสต์ของคุณและติดตั้งภายในคอนเทนเนอร์ของคุณ

ตัวอย่าง:

  1. คุณมี Dockerfile ที่กำหนดไฟล์VOLUME /var/lib/mysql.
  2. คุณสร้างอิมเมจนักเทียบท่าและติดแท็ก some-volume
  3. คุณเรียกใช้คอนเทนเนอร์

แล้ว,

  1. คุณมีอิมเมจนักเทียบท่าอื่นที่คุณต้องการใช้โวลุ่มนี้
  2. คุณเรียกใช้คอนเทนเนอร์นักเทียบท่าด้วยสิ่งต่อไปนี้: docker run --volumes-from some-volume docker-image-name:tag
  3. ตอนนี้คุณมีคอนเทนเนอร์นักเทียบท่าทำงานซึ่งจะมีระดับเสียงจากการsome-volumeติดตั้งใน/var/lib/mysql

หมายเหตุ: การใช้--volumes-fromจะเพิ่มระดับเสียงเหนือสิ่งที่มีอยู่ในตำแหน่งของไดรฟ์ข้อมูล กล่าวคือถ้าคุณมีสิ่งของอยู่/var/lib/mysqlมันจะถูกแทนที่ด้วยเนื้อหาของโวลุ่ม


12
จะเกิดอะไรขึ้นถ้าฉันใช้ -v บนไดเร็กทอรีที่ระบุไว้ใน VOLUME แล้ว
Jeff Storey

6
--volumes-fromจะติดคุณไปด้านบนของสิ่งที่คุณระบุด้วยVOLUME -vที่น่าสนใจดูเหมือนว่าการเรียกใช้คอนเทนเนอร์ในโหมดอภิสิทธิ์ ( docker run --privileged) และumounting /var/lib/mysqlจะปล่อยให้ dir ว่างเปล่าดังนั้นการ-vเมาท์ของคุณจะถูกละเว้นโดยสิ้นเชิงเมื่อมันขัดแย้งกับไฟล์VOLUME.
Chris McKinnel

2
คุณบอกว่าปริมาณจะถูกเก็บไว้ตราบเท่าที่คอนเทนเนอร์อ้างอิงถึงพวกเขาและฉันเคยเห็นสิ่งนั้นที่อื่น docs.docker.com/userguide/dockervolumesกล่าวว่า "ปริมาณข้อมูลได้รับการออกแบบให้คงอยู่ของข้อมูลโดยไม่ขึ้นอยู่กับวงจรชีวิตของคอนเทนเนอร์ Docker จึงไม่เคยลบไดรฟ์ข้อมูลโดยอัตโนมัติเมื่อคุณนำคอนเทนเนอร์ออกและจะไม่" รวบรวมขยะ "วอลุ่มที่ไม่มีอีกต่อไป อ้างอิงโดยคอนเทนเนอร์ " ข้อความเหล่านี้ข้อใดข้อหนึ่งต้องผิด
mc0e

1
ไฟล์ที่อยู่ในไดรฟ์ข้อมูลจะถูกเก็บไว้ในดิสก์เมื่อคอนเทนเนอร์ไม่ได้อ้างอิงอีกต่อไป แต่โวลุ่มนั้นไม่สามารถใช้งานได้อีกต่อไป (เว้นแต่คุณจะรู้วิธีเชื่อมต่อไดรฟ์ข้อมูลเข้ากับคอนเทนเนอร์ด้วยตนเอง แต่ถึงอย่างนั้นฉันก็ไม่ ' ไม่รู้ว่าเป็นไปได้หรือไม่) เมื่อฉันบอกว่าไม่สามารถใช้งานได้อีกต่อไปฉันหมายความว่าคุณไม่สามารถใช้ - ปริมาณ - จากที่จะใช้มันได้ เมื่อพวกเขาพูดว่า "รวบรวมขยะ" ด้านบนหมายความว่าลบไฟล์ออกจากดิสก์ของคุณที่อยู่ในโวลุ่ม
Chris McKinnel

1
สามารถใช้งานได้โดยใช้ -v แต่ไม่ใช่ - ปริมาณจาก Volumes-from ใช้ชื่อคอนเทนเนอร์เพื่อดึงข้อมูลโวลุ่มจาก (ฉันเชื่อว่าต้องใช้จุดโวลุ่มทั้งหมด) อย่างไรก็ตามสำหรับ -v เองคู่มือกล่าวถึงว่าคุณสามารถระบุไดรฟ์ข้อมูลที่มีชื่อเป็น -v ในรูปแบบของnamed-volume:/path/in/container. ไดรฟ์ข้อมูลที่ไม่มีชื่อจะถูกกำหนดแฮชสำหรับชื่อและแฮชเหล่านั้นสามารถจัดเตรียมแทนโฮสต์พา ธ เพื่อเข้าถึงไดรฟ์ข้อมูลที่ไม่มีชื่อ :) โปรดทราบว่าvolume lsอาจไม่ได้แสดงทั้งหมด - ลองdocker volume ls -f dangling=trueด้วย
Jasmine Hegman

44

ให้ฉันเพิ่มคำตอบของตัวเองเพราะฉันเชื่อว่าคนอื่น ๆ ไม่มีจุดของ Docker

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

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

ตอนนี้ในการเข้าถึงข้อมูลนั้นจากโฮสต์คุณจะต้องตรวจสอบคอนเทนเนอร์ของคุณเท่านั้น:

# docker inspect myapp
[{
    .
    .
    .
    "Volumes": {
        "/var/www": "/var/lib/docker/vfs/dir/b3ef4bc28fb39034dd7a3aab00e086e6...",
        "/var/cache/nginx": "/var/lib/docker/vfs/dir/62499e6b31cb3f7f59bf00d8a16b48d2...",
        "/var/log/nginx": "/var/lib/docker/vfs/dir/71896ce364ef919592f4e99c6e22ce87..."
    },
    "VolumesRW": {
        "/var/www": false,
        "/var/cache/nginx": true,
        "/var/log/nginx": true
    }
}]

สิ่งที่ฉันมักจะทำคือสร้าง symlink ในสถานที่มาตรฐานบางแห่งเช่น / srvเพื่อให้ฉันสามารถเข้าถึงไดรฟ์ข้อมูลและจัดการข้อมูลที่มีได้อย่างง่ายดาย (เฉพาะไดรฟ์ข้อมูลที่คุณสนใจ):

ln -s /var/lib/docker/vfs/dir/b3ef4bc28fb39034dd7a3aab00e086e6... /srv/myapp-www
ln -s /var/lib/docker/vfs/dir/71896ce364ef919592f4e99c6e22ce87... /srv/myapp-log

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

4
กับนักเทียบท่า-เขียนให้คุณเห็นว่าสามารถทำเช่นนั้นติดปริมาณในสถานที่เฉพาะของระบบปฏิบัติการโฮสต์ ไม่จำเป็นต้องใช้ symlink ...
Hugo Koopmans

@Tobia: ตัวอย่าง docker-compose ดูเอกสารdocs.docker.com/compose/compose-file/…
Hugo Koopmans

11

VOLUME ใช้Dockerfileเพื่อแสดงปริมาตรที่จะใช้โดยภาชนะอื่น ตัวอย่างสร้างDockerfileเป็น:

จาก ubuntu: 14.04

RUN mkdir /myvol  
RUN echo "hello world" > /myvol/greeting  
VOLUME /myvol

สร้างภาพ:

$ docker build -t testing_volume .

เรียกใช้คอนเทนเนอร์พูดว่า container1:

$ docker run -it <image-id of above image> bash

ตอนนี้เรียกใช้คอนเทนเนอร์อื่นด้วยตัวเลือกไดรฟ์ข้อมูลเป็น (say-container2)

$ docker run -it --volumes-from <id-of-above-container> ubuntu:14.04 bash

คุณจะได้รับข้อมูลทั้งหมดจาก/myvolไดเร็กทอรี container1 ไปยัง container2 ที่ตำแหน่งเดียวกัน

-vตัวเลือกจะได้รับในขณะรันของคอนเทนเนอร์ซึ่งใช้เพื่อต่อเชื่อมไดเรกทอรีของคอนเทนเนอร์บนโฮสต์ มันเป็นเรื่องง่ายที่จะใช้เพียงแค่ให้ตัวเลือกที่มีข้อโต้แย้งเป็น-v <host-path>:<container-path>คำสั่งทั้งหมดอาจเป็น$ docker run -v <host-path>:<container-path> <image-id>


8

โดยทั่วไปVOLUMEและ-vตัวเลือกเกือบเท่ากัน เหล่านี้หมายถึง 'ติดตั้งไดเร็กทอรีเฉพาะบนคอนเทนเนอร์ของคุณ' ตัวอย่างเช่นVOLUME /dataและ-v /dataมีความหมายเหมือนกันทุกประการ หากคุณเรียกใช้รูปภาพที่มีVOLUME /dataหรือมี-v /dataตัวเลือก/dataไดเร็กทอรีจะติดตั้งคอนเทนเนอร์ของคุณ ไดเรกทอรีนี้ไม่ได้อยู่ในคอนเทนเนอร์ของคุณ

ลองนึกภาพว่าคุณเพิ่มไฟล์บางไฟล์ลง/dataในคอนเทนเนอร์จากนั้นผูกคอนเทนเนอร์เป็นรูปภาพใหม่ ไม่มีไฟล์ใด ๆ ในไดเร็กทอรีข้อมูลเนื่องจาก/dataไดเร็กทอรีที่ต่อเชื่อมเป็นของคอนเทนเนอร์ดั้งเดิม

$ docker run -it -v /data --name volume ubuntu:14.04 bash
root@2b5e0f2d37cd:/# cd /data
root@2b5e0f2d37cd:/data# touch 1 2 3 4 5 6 7 8 9
root@2b5e0f2d37cd:/data# cd /tmp
root@2b5e0f2d37cd:/tmp# touch 1 2 3 4 5 6 7 8 9
root@2b5e0f2d37cd:/tmp# exit
exit

$ docker commit volume nacyot/volume  
835cfe3d8d159622507ba3256bb1c0b0d6e7c1419ae32751ad0f925c40378945
nacyot $ docker run -it nacyot/volume
root@dbe335c7e64d:/# cd /data
root@dbe335c7e64d:/data# ls
root@dbe335c7e64d:/data# cd /tmp
root@dbe335c7e64d:/tmp# ls
1  2  3  4  5  6  7  8  9
root@dbe335c7e64d:/tmp# 
root@dbe335c7e64d:/tmp# 

ไดเร็กทอรีที่เมาท์/dataนี้ใช้เพื่อเก็บข้อมูลที่ไม่ได้เป็นของแอปพลิเคชันของคุณ และคุณสามารถกำหนดไดเร็กทอรีข้อมูลที่ไม่ได้เป็นของคอนเทนเนอร์ไว้ล่วงหน้าได้โดยใช้VOLUME .

ความแตกต่างระหว่างVolumeและ-vตัวเลือกคือคุณสามารถใช้-vตัวเลือกแบบไดนามิกในคอนเทนเนอร์เริ่มต้น หมายความว่าคุณสามารถเมานต์ไดเร็กทอรีบางไดเร็กทอรีได้ และข้อแตกต่างอีกประการหนึ่งคือคุณสามารถเมานต์ไดเรกทอรีโฮสต์บนคอนเทนเนอร์ของคุณได้โดยใช้-v


8

นี่มาจากเอกสาร Docker เองอาจช่วยได้ง่ายและธรรมดา:

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

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