ฉันจะปรับใช้คอนเทนเนอร์นักเทียบท่าและที่เก็บข้อมูลที่เกี่ยวข้องรวมถึงเนื้อหาได้อย่างไร


18

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

นี่คือวิธีที่ฉันคิดว่ามันใช้งานได้:

  1. สร้างที่เก็บข้อมูลเพื่อเก็บข้อมูลถาวรบางอย่างบนเครื่อง A
  2. สร้างแอปพลิเคชันคอนเทนเนอร์ซึ่งใช้โวลุ่มจากดาต้าคอนเทนเนอร์
  3. ทำงานบางอย่างอาจเปลี่ยนข้อมูลในที่เก็บข้อมูล
  4. หยุดคอนเทนเนอร์แอ็พพลิเคชัน
  5. กระทำ & ติดแท็กที่เก็บข้อมูล
  6. ผลักดันภาชนะบรรจุข้อมูลไปยังพื้นที่เก็บข้อมูล (ส่วนตัว)
  7. ดึงและเรียกใช้รูปภาพจากขั้นตอนที่ 6 บนเครื่อง B
  8. รับที่ที่คุณทิ้งไว้บนเครื่อง B

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

แต่ดูเหมือนว่าจะไม่ได้ผล สิ่งที่ฉันพบคือว่าขั้นตอนที่ 5 ไม่ได้ทำในสิ่งที่ฉันคิดหรือขั้นตอนที่ 7 (การดึงและเรียกใช้รูปภาพ) "รีเซ็ต" คอนเทนเนอร์เป็นสถานะเริ่มต้น

ฉันได้รวบรวมชุดของอิมเมจและคอนเทนเนอร์สามตัวเพื่อทดสอบสิ่งนี้: data container, นักเขียนที่เขียนสตริงสุ่มลงในไฟล์ใน data container ทุก 30 วินาทีและผู้อ่านที่เพียงแค่echoใส่ค่าในข้อมูล ไฟล์คอนเทนเนอร์และออก

ที่เก็บข้อมูล

สร้างด้วย

docker run \
    --name datatest_data \
    -v /datafolder \
    myrepository:5000/datatest-data:latest

Dockerfile:

FROM ubuntu:trusty

# make the data folder
#
RUN mkdir /datafolder

# write something to the data file
#
RUN echo "no data here!" > /datafolder/data.txt

# expose the data folder
#
VOLUME /datafolder

นักเขียน

สร้างด้วย

docker run \
    --rm \
    --name datatest_write \
    --volumes-from datatest_data \
    myrepository:5000/datatest-write:latest

Dockerfile:

FROM ubuntu:trusty

# Add script
#
ADD run.sh /usr/local/sbin/run.sh
RUN chmod 755 /usr/local/sbin/*.sh

CMD ["/usr/local/sbin/run.sh"]

run.sh

#!/bin/bash

while :
do
    sleep 30s

    NEW_STRING=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)

    echo "$NEW_STRING" >> /datafolder/data.txt

    date >> /datafolder/data.txt

    echo "wrote '$NEW_STRING' to file"
done

สคริปต์นี้เขียนสตริงแบบสุ่มและวันที่ / เวลาลง/datafolder/data.txtในที่เก็บข้อมูล

ผู้อ่าน

สร้างด้วย

docker run \
    --rm \
    --name datatest_read \
    --volumes-from datatest_data \
    myrepository:5000/datatest-read:latest

Dockerfile:

FROM ubuntu:trusty

# Add scripts
ADD run.sh /run.sh
RUN chmod 0777 /run.sh

CMD ["/run.sh"]

run.sh:

#!/bin/bash

echo "reading..."

echo "-----"

cat /datafolder/data.txt

echo "-----"

เมื่อฉันสร้างและเรียกใช้คอนเทนเนอร์เหล่านี้พวกเขาจะทำงานได้ดีและทำงานอย่างที่ฉันคาดไว้:

หยุด & เริ่มบนเครื่องพัฒนา:

  1. สร้างที่เก็บข้อมูล
  2. เรียกใช้นักเขียน
  3. เรียกใช้ผู้อ่านทันทีดู "ไม่มีข้อมูลที่นี่!" ข่าวสาร
  4. รอสักครู่
  5. เรียกใช้ผู้อ่านดูสตริงแบบสุ่ม
  6. หยุดนักเขียน
  7. รีสตาร์ทตัวเขียน
  8. เรียกใช้ผู้อ่านดูสตริงสุ่มเดียวกัน

แต่การกระทำและการผลักดันอย่าทำสิ่งที่ฉันคาดหวัง

  1. สร้างที่เก็บข้อมูล
  2. เรียกใช้นักเขียน
  3. เรียกใช้ผู้อ่านทันทีดู "ไม่มีข้อมูลที่นี่!" ข่าวสาร
  4. รอสักครู่
  5. เรียกใช้ผู้อ่านดูสตริงแบบสุ่ม
  6. หยุดนักเขียน
  7. กระทำ & ติดแท็กคอนเทนเนอร์ข้อมูลด้วย docker commit datatest_data myrepository:5000/datatest-data:latest
  8. ผลักดันไปยังพื้นที่เก็บข้อมูล
  9. ลบคอนเทนเนอร์ทั้งหมด & สร้างใหม่

ณ จุดนี้ฉันคาดว่าจะเรียกใช้ตัวอ่าน & ดูสตริงแบบสุ่มเดียวกันเนื่องจากมีการส่งข้อมูลไปยังที่เก็บข้อมูลผลักไปยังที่เก็บข้อมูลแล้วสร้างใหม่จากอิมเมจเดียวกันในที่เก็บ อย่างไรก็ตามสิ่งที่ฉันเห็นจริง ๆ คือ "ไม่มีข้อมูลที่นี่!" ข่าวสาร

บางคนสามารถอธิบายได้ว่าฉันผิดตรงไหนหรือไม่ หรืออีกวิธีหนึ่งคือชี้ให้ฉันเห็นตัวอย่างของวิธีการปรับใช้กับ Docker

คำตอบ:


22

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

ก่อนอื่นให้เรานึกถึงคำจำกัดความเล็กน้อย

ภาพนักเทียบท่า

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

ปริมาณข้อมูล

จากคู่มือผู้ใช้ Docker :

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

สิ่งสำคัญคือให้สังเกตที่นี่ว่าไดรฟ์ข้อมูลที่กำหนด (เป็นไดเรกทอรีหรือไฟล์ที่มีข้อมูล) สามารถนำมาใช้ซ้ำได้หากมีอยู่อย่างน้อยหนึ่งคอนเทนเนอร์นักเทียบท่าที่ใช้มัน อิมเมจของ Docker ไม่มีวอลุ่ม แต่จะมีเมทาดาทาเท่านั้นซึ่งในที่สุดจะบอกว่าโวลุ่มใดที่จะถูกเมานต์บนระบบไฟล์รวม ปริมาณข้อมูลไม่ได้เป็นส่วนหนึ่งของระบบไฟล์ร่วมของ docker container ดังนั้นจะอยู่ที่ไหน ภายใต้/var/lib/docker/volumesในโฮสต์นักเทียบท่า (ในขณะที่ภาชนะจะถูกเก็บไว้ภายใต้/var/lib/docker/containers)

ภาชนะบรรจุปริมาณข้อมูล

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

การทำงานกับคอนเทนเนอร์วอลุ่มข้อมูล

วิธีสร้างคอนเทนเนอร์โวลุ่มข้อมูล

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

docker run --name datatest_data --volume /datafolder busybox true

นี่baseคือชื่อรูปภาพ (ขนาดเล็กที่สะดวก) และtrueเป็นคำสั่งที่เราจัดเตรียมไว้เพียงเพื่อหลีกเลี่ยงการเห็นนักเทียบท่า daemon บ่นเกี่ยวกับคำสั่งที่หายไป อย่างไรก็ตามหลังจากที่คุณมีคอนเทนเนอร์หยุดชื่อที่datatest_dataมีวัตถุประสงค์เพื่อให้คุณเข้าถึงไดรฟ์ข้อมูลนั้นด้วย--volumes-fromตัวเลือกของdocker runคำสั่ง

วิธีอ่านจาก data volume container

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

ตัวอย่างเช่น

docker run --rm --volumes-from datatest_data busybox cat /datafolder/data.txt

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

ทำงานกับโวลุ่ม (ตั้งแต่ Docker 1.9.0)

วิธีสร้างโวลุ่ม (ตั้งแต่ Docker 1.9.0)

นักเทียบท่า 1.9.0 แนะนำคำสั่งใหม่docker volumeที่ช่วยให้สร้างไดรฟ์:

docker volume create --name hello

วิธีอ่านจากโวลุ่ม (ตั้งแต่ Docker 1.9.0)

สมมติว่าคุณสร้างโวลุ่มที่helloมีชื่อdocker volume create --name helloคุณสามารถเมานต์ในคอนเทนเนอร์ด้วย-vตัวเลือก:

docker run -v hello:/data busybox ls /data

เกี่ยวกับการส่งและผลักตู้คอนเทนเนอร์

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

การทำสำเนาสำรองของปริมาณข้อมูล

คู่มือผู้ใช้นักเทียบท่ามีบทความที่ดีเกี่ยวกับการสำรองข้อมูลของปริมาณข้อมูล


บทความที่ดี reagarding ปริมาณ: http://container42.com/2014/11/03/docker-indepth-volumes/


ดูเหมือนว่า "รูปภาพที่ใช้ในการสร้างที่เก็บข้อมูลปริมาณไม่สำคัญ" ไม่ถูกต้องนัก เพียงแค่ลองด้วยภาพ "เริ่มต้น" ซึ่งจะทำให้คุณ "exec:" true ": ไม่พบไฟล์ปฏิบัติการ"
tcurdt

แม้จะมีข้อผิดพลาดนี้ตู้คอนเทนเนอร์ของคุณจะถูกสร้างขึ้นให้สมบูรณ์ตามบทบาทในฐานะผู้ถือไดรฟ์ข้อมูล
Thomasleveil

1
หืม - อาจจะคุ้มค่าที่จะเปิดประเด็นสำหรับเรื่องนั้น
tcurdt

ไม่พฤติกรรมนั้นเป็นที่คาดหวังเนื่องจากภาพรอยขีดข่วนเป็นภาพว่างเปล่าซึ่งไม่สามารถมี/bin/trueไบนารี (หรืออื่น ๆ ) ได้
Thomasleveil

1
เพียงสิ่งหนึ่ง. คุณบอกว่า "ทันทีที่คอนเทนเนอร์สุดท้าย (ใช้งานหรือหยุดทำงาน) โดยใช้ปริมาณข้อมูลที่กำหนดจะถูกลบออกนักเทียบท่าจะทำลายปริมาณข้อมูลนั้นจาก / var / lib / docker / ไดรฟ์ข้อมูล" แต่นั่นไม่ใช่ความจริง: เพียงเห็น: docs.docker.com/userguide/dockervolumes (ปริมาณข้อมูลยังคงอยู่แม้ว่าตัวคอนเทนเนอร์จะถูกลบคุณต้องระบุdocker rm -vคำสั่งกับที่เก็บล่าสุดเพื่อลบโวลุ่มด้วย)
juanra

1

คุณสามารถใช้ที่เก็บข้อมูลนักเทียบท่าเพื่อปรับใช้รหัส

ฉันไม่รู้ว่ามันเป็นวิธีปฏิบัติที่ดี แต่ฉันก็ทำเช่นนั้น:

FROM ubuntu:trusty

# make the data folder
#
RUN mkdir /data-image

# in my case, I have a 
# ADD dest.tar /data-image/
#
# but to follow your example :
# write something to the data file
RUN echo "no data here!" > /data-image/data.txt

# expose the data folder 
#
VOLUME /datafolder

ENTRYPOINT cp -r /data-image/* /datafolder/

ตอนนี้คุณสามารถดันภาพและใช้วอลลุ่มจาก ฯลฯ


นี่คือสิ่งที่ฉันกำลังมองหา แต่คำตอบที่ยอมรับได้ระบุไว้อย่างชัดเจนว่าไม่สามารถทำได้ ลองตอนนี้เลย
andho

1
เมื่อตอบกลับอย่างรวดเร็วคำตอบที่ยอมรับจะบอกว่าโวลุ่ม (หรือข้อมูลอยู่ภายใน) จะไม่ถูกส่งมอบ แต่คุณสามารถเพิ่มข้อมูลลงในคอนเทนเนอร์โดยใช้COPYหรือADDสร้างโวลุ่มโดยใช้VOLUMEใน Dockerfile
andho
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.