Docker ADD เทียบกับ VOLUME


116

ฉันกำลังเรียนรู้ Docker และฉันมีข้อสงสัยเกี่ยวกับเวลาและสถานที่ที่จะใช้ADDและVOLUME. นี่คือสิ่งที่ฉันคิดว่าทั้งสองอย่างนี้ทำ:

เพิ่ม

คัดลอกไฟล์ไปยังรูปภาพในเวลาสร้าง อิมเมจมีไฟล์ทั้งหมดเพื่อให้คุณปรับใช้งานได้ง่ายมาก ในทางกลับกันการต้องสร้างทุกครั้งดูเหมือนไม่ใช่ความคิดที่ดีในการพัฒนาเพราะการสร้างต้องการให้นักพัฒนารันคำสั่งเพื่อสร้างคอนเทนเนอร์ใหม่ นอกจากนี้การสร้างตู้คอนเทนเนอร์อาจใช้เวลานาน

VOLUME

ฉันเข้าใจว่าการใช้docker run -vคุณสามารถเมานต์โฟลเดอร์โฮสต์ภายในคอนเทนเนอร์ของคุณด้วยวิธีนี้คุณสามารถแก้ไขไฟล์ได้อย่างง่ายดายและดูแอปในคอนเทนเนอร์ของคุณตอบสนองต่อการเปลี่ยนแปลง มันดูดีในการพัฒนา แต่ฉันไม่แน่ใจว่าจะปรับใช้ไฟล์ของฉันด้วยวิธีนี้ได้อย่างไร


3
โดยทั่วไปจะดีที่สุดที่จะชอบที่จะCOPY ADDเกือบจะเหมือนกัน แต่ADDมีความสามารถพิเศษบางอย่างในการเขียน URL และไฟล์เก็บถาวรที่น่าแปลกใจ
Adrian Mouat

2
@jamesmstone - ลิงก์นั้น (และเอกสารนักเทียบท่าอย่างเป็นทางการ) แนะนำสิ่งที่ตรงกันข้าม - ใช้ COPY แทน ADD
Software Engineer

โอ๊ะคุณพูดถูก - ไชโย!
jamesmstone

คำตอบ:


183

เพิ่ม

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

ตัวอย่างบางกรณีที่คุณต้องการใช้ADD:

  • คุณมีข้อกำหนดบางประการในไฟล์ requirements.txt ที่คุณต้องการอ้างอิงและติดตั้งใน Dockerfile ของคุณ จากนั้นคุณสามารถทำได้: ADD ./requirements.txt /requirements.txtตามด้วยRUN pip install -r /requirements.txt
  • คุณต้องการใช้โค้ดแอพของคุณเป็นบริบทใน Dockerfile ของคุณตัวอย่างเช่นหากคุณต้องการตั้งค่าไดเรกทอรีแอพของคุณเป็นไดเร็กทอรีที่ทำงานในรูปภาพของคุณและมีคำสั่งเริ่มต้นในคอนเทนเนอร์ที่เรียกใช้จากรูปภาพของคุณให้เรียกใช้แอพของคุณคุณ ทำได้:

    ADD ./ /usr/local/git/my_app

    WORKDIR /usr/local/git/my_app

    CMD python ./main.py

VOLUME

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

ตัวอย่างบางกรณีที่คุณต้องการใช้VOLUME:

  • แอปที่กำลังทำงานในคอนเทนเนอร์ของคุณทำให้เข้า/var/log/my_appสู่ระบบ คุณต้องการให้บันทึกเหล่านั้นสามารถเข้าถึงได้บนเครื่องโฮสต์และไม่ให้ถูกลบเมื่อนำคอนเทนเนอร์ออก คุณสามารถทำได้โดยสร้างจุดเชื่อมต่อที่/var/log/my_appโดยเพิ่มVOLUME /var/log/my_appลงใน Dockerfile ของคุณแล้วเรียกใช้คอนเทนเนอร์ของคุณด้วยdocker run -v /host/log/dir/my_app:/var/log/my_app some_repo/some_image:some_tag
  • คุณมีไฟล์การตั้งค่าในเครื่องที่คุณต้องการให้แอปในคอนเทนเนอร์เข้าถึงได้ บางทีไฟล์การตั้งค่าเหล่านั้นอาจแตกต่างกันในเครื่องของคุณเทียบกับ dev เทียบกับการผลิต โดยเฉพาะอย่างยิ่งหากไฟล์การตั้งค่าเหล่านั้นเป็นความลับซึ่งในกรณีนี้คุณไม่ต้องการให้อยู่ในภาพของคุณอย่างแน่นอน กลยุทธ์ที่ดีในกรณีนี้คือการเพิ่มลงVOLUME /etc/settings/my_app_settingsใน Dockerfile ของคุณเรียกใช้คอนเทนเนอร์ของคุณdocker run -v /host/settings/dir:/etc/settings/my_app_settings some_repo/some_image:some_tagและตรวจสอบให้แน่ใจว่า / host / settings / dir มีอยู่ในทุกสภาพแวดล้อมที่คุณคาดว่าแอปของคุณจะทำงาน

13
จนถึงตอนนี้โพสต์ที่มีประโยชน์ที่สุดที่ฉันพบใน ADD และ VOLUME
Jasmeet

5
จะเกิดอะไรขึ้นถ้ามีการระบุ VOLUME แต่ไม่ได้ระบุไว้ในระหว่างการทำงานของนักเทียบท่า (เช่นพารามิเตอร์ -v xxx หายไป) คือการหายใจ ปริมาณแล้วกลายเป็นชั่วคราวอย่างมีประสิทธิภาพ?
col.panic

ภายใน Dockerfile ปริมาณอาจจะหมายถึงเฉพาะสำหรับการติดตาและ / หรือการแก้จุดบกพร่อง แต่คุณสามารถใช้สวิตช์บรรทัดคำสั่งเสียงเพื่อรับการตรวจสอบลงในภาพที่มีอยู่ (ไม่ Dockerfile จำเป็น) docker run -v $HOST_PATH:$CONTAINER_PATH node:latest node $CONTAINER_PATH/app.jsและเรียกมันเช่นนี้
Chinoto Vokro

รายละเอียด "เลเยอร์" ที่ดี
stratovarius

27

VOLUMEคำแนะนำและสร้างปริมาณข้อมูลในภาชนะหางของคุณที่รันไทม์ ไดเร็กทอรีที่ระบุเป็นอาร์กิวเมนต์VOLUMEเป็นไดเร็กทอรีที่ข้ามUnion File Systemและส่วนใหญ่จะใช้สำหรับข้อมูลถาวรและข้อมูลที่แชร์

หากคุณเรียกใช้docker inspect <your-container>คุณจะเห็นภายใต้Mountsส่วนนี้Sourceซึ่งแสดงถึงตำแหน่งไดเร็กทอรีบนโฮสต์และDestinationซึ่งแสดงถึงตำแหน่งไดเร็กทอรีที่ต่อเชื่อมในคอนเทนเนอร์ ตัวอย่างเช่น,

"Mounts": [
  {
    "Name": "fac362...80535",
    "Source": "/var/lib/docker/volumes/fac362...80535/_data",
    "Destination": "/webapp",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  }
]

นี่คือ 3 กรณีการใช้งานสำหรับdocker run -v:

  1. docker run -v /data: นี่คล้ายกับการระบุVOLUMEคำสั่งใน Dockerfile ของคุณ
  2. docker run -v $host_path:$container_path: สิ่งนี้ช่วยให้คุณสามารถต่อเชื่อม$host_pathจากโฮสต์ของคุณไปยัง$container_pathคอนเทนเนอร์ของคุณในระหว่างรันไทม์ ในการพัฒนาสิ่งนี้มีประโยชน์สำหรับการแชร์ซอร์สโค้ดบนโฮสต์ของคุณกับคอนเทนเนอร์ ในการใช้งานจริงสามารถใช้เพื่อเชื่อมต่อสิ่งต่างๆเช่นข้อมูล DNS ของโฮสต์ (ที่พบใน/etc/resolv.conf) หรือความลับลงในคอนเทนเนอร์ ในทางกลับกันคุณยังสามารถใช้เทคนิคนี้เพื่อเขียนบันทึกของคอนเทนเนอร์ลงในโฟลเดอร์เฉพาะบนโฮสต์ ทั้งสองอย่าง$host_pathและ$container_pathต้องเป็นเส้นทางที่แน่นอน
  3. docker run -v my_volume:$container_path: นี้จะสร้างปริมาณข้อมูลในภาชนะของคุณที่และชื่อมัน$container_path มันเป็นหลักเช่นเดียวกับการสร้างและการตั้งชื่อปริมาณการใช้my_volume docker volume create my_volumeการตั้งชื่อปริมาณเช่นนี้จะเป็นประโยชน์สำหรับปริมาณข้อมูลภาชนะและปริมาณที่ใช้ร่วมกันจัดเก็บข้อมูลโดยใช้โปรแกรมควบคุมที่เก็บหลายโฮสต์เช่นFlocker

สังเกตว่าวิธีการติดตั้งโฟลเดอร์โฮสต์เป็นไดรฟ์ข้อมูลไม่มีอยู่ใน Dockerfile การอ้างอิงเอกสารนักเทียบท่า ,

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

ตอนนี้หากคุณต้องการคัดลอกไฟล์ของคุณไปยังคอนเทนเนอร์ในสภาพแวดล้อมที่ไม่ใช่การพัฒนาคุณสามารถใช้ADDหรือCOPYคำแนะนำใน Dockerfile ของคุณ นี่คือสิ่งที่ฉันมักจะใช้สำหรับการปรับใช้ที่ไม่ใช่การพัฒนา


3
ฉันควรสร้างไฟล์นักเทียบท่า 2 ไฟล์หรือไม่ หนึ่งสำหรับการพัฒนาและสำหรับการปรับใช้?
Cristian Garcia

ฉันไม่คิดอย่างนั้น ไม่มีอะไรผิดปกติกับการมีADDคำสั่งใน Dockerfile ของคุณเนื่องจากดำเนินการโดยdocker buildคำสั่งเท่านั้น สิ่งนี้จำเป็นเมื่อผู้อื่นสร้างคอนเทนเนอร์ของคุณเป็นครั้งแรกและเมื่อคุณพร้อมที่จะปรับใช้กับสภาพแวดล้อมอื่น ๆ ที่ไม่ใช่การพัฒนา
ivan.sim

3
แต่การสร้างอิมเมจโดยไม่มีไฟล์และใช้-vคำสั่งเพื่อการพัฒนาจะมีประสิทธิภาพหรือไม่และมีไฟล์นักเทียบท่าอื่นสร้างอิมเมจที่มีไฟล์ADDสำหรับการปรับใช้หรือไม่?
Cristian Garcia

1
เป็นการแลกเปลี่ยนที่คุณต้องตัดสินใจ เลือกสิ่งที่เหมาะกับคุณ การสร้างโดยADDใช้เวลานานแค่ไหน? รวมสองสามวินาที? หากคุณมีไฟล์ Dockerfile สองไฟล์และคุณแชร์กับผู้อื่น (หรือเผยแพร่บนDocker Registry ) ไฟล์ใดเป็นค่าเริ่มต้น คุณจะมีค่าใช้จ่ายในการบำรุงรักษาเพิ่มเติมเพื่อให้แน่ใจว่า Dockerfile เริ่มต้นที่ถูกต้องจะส่งถึงผู้ใช้ที่เหมาะสม แต่ในตอนท้ายของวันคุณเป็นผู้ตัดสินใจว่าอะไรดีที่สุดสำหรับคุณ โดยส่วนตัวแล้วฉันต้องการให้แน่ใจว่ามี Dockerfile หนึ่งเดียวในการสร้างคอนเทนเนอร์ของฉัน
ivan.sim

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