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


236

คำถามเดิม: วิธีใช้คำสั่ง VOLUME ใน Dockerfile

คำถามที่เกิดขึ้นจริงที่ฉันต้องการที่จะแก้ปัญหาคือ - วิธีการติดตั้งไดรฟ์เป็นเจ้าภาพในภาชนะนักเทียบท่าใน Dockerfile ในระหว่างการสร้างคือการมีความสามารถในช่วงdocker run -v /export:/exportdocker build

เหตุผลที่อยู่เบื้องหลังสำหรับฉันคือเมื่อสร้างสิ่งต่าง ๆ ใน Docker ฉันไม่ต้องการให้apt-get installแคช( ) เหล่านั้นล็อกใน docker เดียว แต่เพื่อแบ่งปัน / นำกลับมาใช้ใหม่ นั่นเป็นเหตุผลหลักที่ฉันถามคำถามนี้

ปรับปรุงล่าสุด:

ก่อนที่นักเทียบท่า v18.09 คำตอบที่ถูกต้องควรเป็นคำตอบที่ขึ้นต้นด้วย:

มีวิธีการเมานต์โวลุ่มในระหว่างบิลด์ แต่ไม่เกี่ยวข้องกับ Dockerfiles

อย่างไรก็ตามนั่นเป็นคำตอบที่ได้รับการจัดการและสนับสนุนที่ไม่ดี เมื่อฉันติดตั้งนักเทียบท่าฉันมีฉันบังเอิญสะดุดกับบทความต่อไปนี้:

เชื่อมต่อบริการ apt-cacher-ng
https://docs.docker.com/engine/examples/apt-cacher-ng/

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

อีกวิธีหนึ่งคือคำตอบที่ยอมรับใหม่เช่น Buildkit ใน v18.09

เลือกสิ่งที่เหมาะกับคุณ


เป็น:มีวิธีแก้ปัญหา - rocker ซึ่งไม่ได้มาจาก Docker แต่ตอนนี้ rocker นั้นถูกยกเลิกฉันกลับคำตอบกลับเป็น"ไม่สามารถทำได้"อีกครั้ง


การอัปเดตเก่า:ดังนั้นคำตอบคือ "ไม่สามารถทำได้" ฉันจะยอมรับว่ามันเป็นคำตอบที่ผมรู้ว่าปัญหาได้รับการกล่าวถึงอย่างกว้างขวางในhttps://github.com/docker/docker/issues/3156 ฉันสามารถเข้าใจได้ว่าการพกพาเป็นปัญหาที่สำคัญยิ่งสำหรับนักพัฒนานักเทียบท่า แต่ในฐานะผู้ใช้นักเทียบท่าฉันต้องบอกว่าฉันผิดหวังมากเกี่ยวกับคุณสมบัติที่ขาดหายไปนี้ ให้ฉันปิดการโต้แย้งของฉันด้วยคำพูดจากการสนทนาดังกล่าว: " ฉันต้องการใช้ Gentoo เป็นภาพฐาน แต่ไม่ต้องการให้> 1GB ของข้อมูลต้นไม้พอร์เทจอยู่ในเลเยอร์ใด ๆ เมื่อภาพถูกสร้างขึ้นคุณ อาจมีภาชนะบรรจุขนาดกะทัดรัดที่ดีถ้ามันไม่ได้สำหรับต้นไม้ขนาดใหญ่ที่ต้องปรากฏในภาพในระหว่างการติดตั้ง"ใช่ฉันสามารถใช้ wget หรือ curl เพื่อดาวน์โหลดสิ่งที่ฉันต้องการได้ แต่ความจริงที่ว่าตอนนี้การพิจารณาเรื่องความสะดวกในการพกพาทำให้ฉันต้องดาวน์โหลด> 1GB ของโครงสร้างต้นไม้ในแต่ละครั้งที่สร้างภาพฐาน Gentoo นั้นไม่มีประสิทธิภาพหรือเป็นมิตรต่อผู้ใช้ ยิ่งกว่านั้นพื้นที่เก็บข้อมูลของแพคเกจจะอยู่ภายใต้ / usr / portage เสมอดังนั้นแบบพกพาภายใต้ Gentoo อีกครั้งฉันเคารพการตัดสินใจ แต่โปรดอนุญาตให้ฉันแสดงความผิดหวังของฉันเช่นกันในเวลาเฉลี่ยขอบคุณ


คำถามเดิมในรายละเอียด:

จาก

แชร์ไดเรกทอรีผ่านไดรฟ์ข้อมูล
http://docker.readthedocs.org/en/v0.7.3/use/working_with_volumes/

มันบอกว่าฟีเจอร์ดาต้าวอลุ่ม "มีให้บริการตั้งแต่ Docker Remote API รุ่น 1" นักเทียบท่าของฉันเป็นรุ่น 1.2.0 แต่ฉันพบตัวอย่างที่ระบุในบทความด้านบนไม่ทำงาน:

# BUILD-USING:        docker build -t data .
# RUN-USING:          docker run -name DATA data
FROM          busybox
VOLUME        ["/var/volume1", "/var/volume2"]
CMD           ["/usr/bin/true"]

อะไรคือวิธีที่เหมาะสมใน Dockerfile เพื่อเมานท์วอลลุ่มที่เมาท์โฮสต์ลงในคอนเทนเนอร์ docker ผ่านคำสั่ง VOLUME

$ apt-cache policy lxc-docker
lxc-docker:
  Installed: 1.2.0
  Candidate: 1.2.0
  Version table:
 *** 1.2.0 0
        500 https://get.docker.io/ubuntu/ docker/main amd64 Packages
        100 /var/lib/dpkg/status

$ cat Dockerfile 
FROM          debian:sid

VOLUME        ["/export"]
RUN ls -l /export
CMD ls -l /export

$ docker build -t data .
Sending build context to Docker daemon  2.56 kB
Sending build context to Docker daemon 
Step 0 : FROM          debian:sid
 ---> 77e97a48ce6a
Step 1 : VOLUME        ["/export"]
 ---> Using cache
 ---> 59b69b65a074
Step 2 : RUN ls -l /export
 ---> Running in df43c78d74be
total 0
 ---> 9d29a6eb263f
Removing intermediate container df43c78d74be
Step 3 : CMD ls -l /export
 ---> Running in 8e4916d3e390
 ---> d6e7e1c52551
Removing intermediate container 8e4916d3e390
Successfully built d6e7e1c52551

$ docker run data
total 0

$ ls -l /export | wc 
     20     162    1131

$ docker -v
Docker version 1.2.0, build fa7b24f

เห็นได้ชัดว่าคำขอคุณสมบัติในปัจจุบันมีมากขึ้น (ไม่ใช่ว่าฉันคาดหวังว่าจะนำไปใช้ แต่ในกรณีนี้): นักเทียบท่า / นักเทียบท่า # 14080
Jesse Glick

VOLUME ~/host_dir ~/container_dirแน่นอนมีการอภิปรายอย่างกว้างขวางว่ามันไม่ควรได้รับอนุญาตให้เชื่อมโยงไดเรกทอรีโฮสต์และไดเรกทอรีภาชนะในระหว่างการสร้างคือสิ่งที่ต้องการ การอภิปรายค่อนข้างกว้างขวางหากมีวิธีสั้น ๆ ในการสรุปเหตุผลคืออะไร
Charlie Parker

คำตอบ:


34

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


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

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

FROM debian:sid as builder
COPY export /export
RUN compile command here >/result.bin

FROM debian:sid
COPY --from=builder /result.bin /result.bin
CMD ["/result.bin"]

ซึ่งจะส่งผลให้บิลด์ที่มีไบนารีเป็นผลลัพธ์เท่านั้นไม่ใช่ไดเร็กทอรีแบบเต็ม / เอ็กซ์พอร์ต


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

# syntax = docker/dockerfile:experimental
FROM debian:latest
RUN --mount=target=/var/lib/apt/lists,type=cache \
    --mount=target=/var/cache/apt,type=cache \
    apt-get update \
 && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
      git

คุณจะปรับไดเรกทอรีแคชสำหรับแอปพลิเคชันแคชใด ๆ ที่คุณมีเช่น $ HOME / .m2 สำหรับ maven หรือ /root/.cache สำหรับ golang


TL; DR: คำตอบอยู่ที่นี่:ด้วยRUN --mountไวยากรณ์นั้นคุณยังสามารถผูกติดไดเรกทอรีอ่านอย่างเดียวจากการสร้างบริบท โฟลเดอร์ต้องมีอยู่ในบริบทของการบิลด์และจะไม่ถูกแม็พกลับไปยังโฮสต์หรือบิลด์ไคลเอ็นต์:

# syntax = docker/dockerfile:experimental
FROM debian:latest
RUN --mount=target=/export,type=bind,source=export \
    process export directory here...

โปรดทราบว่าเนื่องจากไดเรกทอรีถูกเมาท์จากบริบทจึงถูกเมาท์เป็นแบบอ่านอย่างเดียวและคุณไม่สามารถพุชการเปลี่ยนแปลงกลับไปยังโฮสต์หรือไคลเอนต์ เมื่อคุณสร้างคุณจะต้องการ 18.09 หรือใหม่กว่าการติดตั้งและเปิดใช้งาน buildkit export DOCKER_BUILDKIT=1กับ

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


2
น่าเสียดายที่ใน Windows Buildkit ยังไม่รองรับในรุ่น 18.09
Wesley

1
ดูเหมือนว่า "armhf" ไม่รองรับ "mount" เช่นกัน
Mike

2
ฉันได้รับ "การตอบสนองข้อผิดพลาดจาก daemon: Dockerfile แยกบรรทัดข้อผิดพลาด xx: ไม่ทราบค่าสถานะ: mount" บน OSX
ChristoKiwi

1
การสนับสนุนสำหรับนักแต่งเพลงยังไม่ได้มี แต่คุณไม่จำเป็นต้องเขียนเพื่อสร้างภาพ ปัญหาในการติดตาม: github.com/moby/buildkit/issues/685
BMitch

2
เอกสารเกี่ยวกับเรื่องนี้: github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/…
Drew LeSueur

116

ไม่สามารถใช้VOLUMEคำแนะนำเพื่อบอกนักเทียบท่าว่าต้องเมาท์อะไร นั่นจะทำลายการพกพาอย่างจริงจัง คำสั่งนี้บอกนักเทียบท่าว่าเนื้อหาในไดเรกทอรีเหล่านั้นไม่ได้อยู่ในรูปภาพและสามารถเข้าถึงได้จากคอนเทนเนอร์อื่นโดยใช้--volumes-fromพารามิเตอร์บรรทัดคำสั่ง คุณต้องเรียกใช้คอนเทนเนอร์โดยใช้-v /path/on/host:/path/in/containerเพื่อเข้าถึงไดเรกทอรีจากโฮสต์

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


2
ขอบคุณ แก้ไขคำถามแล้ว คำถามจริงที่ฉันต้องการแก้ไขคือ - วิธีติดตั้งไดรฟ์ข้อมูลโฮสต์ลงในคอนเทนเนอร์ของนักเทียบท่าใน Dockerfile ในระหว่างการสร้าง ขอบคุณ.
xpt

2
เป็นไปไม่ได้. ดูคำตอบที่แก้ไขแล้ว
Andreas Steffan

3
ฉันสามารถชื่นชมผลข้างเคียง "ที่มีศักยภาพ" ต่อการพกพาได้ แต่ก็ยังมีกรณีการใช้งานที่ถูกต้องสำหรับการมีตัวเลือกนี้ ในกรณีของฉันฉันชอบที่จะบอกผู้ใช้ถึง "ย้ายไปยังไดเรกทอรีและเรียกใช้คำสั่ง 'นักเทียบท่าเรียกใช้' โดยที่ $ (PWD) ติดตั้งอยู่กับคอนเทนเนอร์ dir $ (PWD) ทำให้มั่นใจในการพกพา แม้ว่านี่อาจเป็นเรื่องมุม แต่ก็จะช่วยฉันอย่างมากในที่ที่ฉันแจกจ่ายสภาพแวดล้อมรันไทม์สำหรับสคริปต์ที่ผู้ใช้จัดหา
ntwrkguru

64

UPDATE: ใครบางคนไม่ตอบว่าเป็นคำตอบและฉันชอบมันมากโดยเฉพาะคำถามนี้

ข่าวที่ดีมีวิธีตอนนี้ -

การแก้ปัญหาคือ Rocker: https://github.com/grammarly/rocker

จอห์น Yani กล่าวว่า , "IMO ก็แก้ทุกจุดที่อ่อนแอของ Dockerfile ทำให้มันเหมาะสำหรับการพัฒนา."

คนโยก

https://github.com/grammarly/rocker

ด้วยการแนะนำคำสั่งใหม่ Rocker มีจุดมุ่งหมายเพื่อแก้ไขกรณีการใช้งานต่อไปนี้ซึ่งเจ็บปวดกับ Docker ธรรมดา:

  1. เมานต์ไดรฟ์ที่นำกลับมาใช้ใหม่ได้ในขั้นตอนการสร้างดังนั้นเครื่องมือการจัดการการพึ่งพาอาจใช้แคชระหว่างการสร้าง
  2. แชร์คีย์ ssh กับบิลด์ (สำหรับดึง repos ส่วนตัว ฯลฯ ) ในขณะที่ไม่ทิ้งไว้ในรูปภาพผลลัพธ์
  3. สร้างและเรียกใช้แอปพลิเคชั่นในภาพต่าง ๆ สามารถส่งผ่านสิ่งประดิษฐ์จากภาพหนึ่งไปยังอีกภาพได้อย่างง่ายดายโดยมีตรรกะนี้ใน Dockerfile เดียว
  4. แท็ก / ดันภาพได้จาก Dockerfiles
  5. ส่งผ่านตัวแปรจากคำสั่ง shell build เพื่อให้สามารถแทนที่ไปยัง Dockerfile

และอื่น ๆ. สิ่งเหล่านี้เป็นปัญหาที่สำคัญที่สุดที่ขัดขวางการยอมรับนักเทียบท่าที่ Grammarly ของเรา

อัปเดต: Rocker ถูกยกเลิกแล้วตามโครงการ repo อย่างเป็นทางการใน Github

ตั้งแต่ต้นปี 2561 ระบบนิเวศของภาชนะบรรจุนั้นมีความสมบูรณ์มากกว่าเมื่อสามปีก่อนเมื่อโครงการนี้เริ่มต้นขึ้น ตอนนี้คุณสมบัติที่สำคัญและโดดเด่นของตัวโยกสามารถครอบคลุมได้อย่างง่ายดายด้วยตัวสร้างนักเทียบท่าหรือเครื่องมือที่ได้รับการสนับสนุนอื่น ๆ แม้ว่าคุณสมบัติบางอย่างจะไม่ซ้ำกันกับตัวโยก ดูhttps://github.com/grammarly/rocker/issues/199สำหรับรายละเอียดเพิ่มเติม


ฉันพยายามใช้ Rocker เพื่อแก้ปัญหาหมายเลข 1 แต่คำสั่ง mount ไม่ทำงานและรูปภาพที่สร้างขึ้นไม่มีโฟลเดอร์โฮสต์ ฉัน Dockerfile ติดรูปลักษณ์คำสั่งเช่นนี้ - MOUNT ~/code/docker-app-dev/new-editor/:/src/และโยกสร้างคำสั่งของฉันนี้ rocker build -f Dockerfile .- ฉันทำผิดอะไร
Yaron Idan

อาจลองใช้เส้นทางโฮสต์จริงหรือ ~เป็นตัวบ่งชี้เชลล์ Bourne
Jesse Glick

Rocker buildไม่อนุญาตให้มีตัวเลือกบรรทัดคำสั่งดังนั้นขณะนี้ไม่อนุญาตให้สิ่งที่ต้องการdocker run --privileged
Monty Wild

สวัสดี @xpt เราจะได้รับการอัปเดตอีกครั้งหรือไม่เนื่องจาก Rocker ถูกยกเลิกในขณะนี้
Shardj

ตอนนี้ผู้โยกนั้นหยุดฉันก็กลับคำตอบกลับเป็น "ไม่สามารถทำได้" อีกครั้ง ดู OP และคำตอบที่เลือก
xpt

14

มีวิธีการเมานต์โวลุ่มในระหว่างบิลด์ แต่ไม่เกี่ยวข้องกับ Dockerfiles

เทคนิคคือการสร้างคอนเทนเนอร์จากฐานใด ๆ ที่คุณต้องการใช้ (ติดตั้งวอลลุ่มในคอนเทนเนอร์ด้วย-vตัวเลือก) เรียกใช้เชลล์สคริปเพื่อทำงานสร้างภาพของคุณจากนั้นผูกคอนเทนเนอร์เป็นรูปภาพเมื่อเสร็จสิ้น .

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

UPDATE:

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

CONTAINER_ID=$(docker run -dit ubuntu:16.04)
docker cp build.sh $CONTAINER_ID:/build.sh
docker exec -t $CONTAINER_ID /bin/sh -c '/bin/sh /build.sh'
docker commit $CONTAINER_ID $REPO:$TAG
docker stop $CONTAINER_ID

6
+1 คุณช่วยอธิบายเพิ่มเติมเกี่ยวกับคำแนะนำในย่อหน้าที่ 2 ได้ไหม ตัวอย่างเช่นหากฐานคือdebian:wheezyและเชลล์สคริปต์คือbuild.shคำแนะนำเฉพาะที่จะใช้?
Drux

6

ในขณะที่คุณเรียกใช้คอนเทนเนอร์ไดเรกทอรีบนโฮสต์ของคุณจะถูกสร้างและติดตั้งลงในคอนเทนเนอร์ คุณสามารถค้นหาไดเรคทอรี่ที่มีอยู่

$ docker inspect --format "{{ .Volumes }}" <ID>
map[/export:/var/lib/docker/vfs/dir/<VOLUME ID...>]

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

docker run -v /export:/export data

ดังนั้นคุณจะใช้โฟลเดอร์โฮสต์ภายในคอนเทนเนอร์ของคุณ


1
ขอบคุณ แก้ไขคำถามแล้ว คำถามจริงที่ฉันต้องการแก้ไขคือ - วิธีติดตั้งไดรฟ์ข้อมูลโฮสต์ลงในคอนเทนเนอร์ของนักเทียบท่าใน Dockerfile ในระหว่างการสร้าง ขอบคุณ.
xpt

กรุณาอย่าแก้ไขคำถามในลักษณะที่รุนแรง สิ่งนี้ทำให้คำถามของฉันไม่ถูกต้องแม้ว่าจะถูกต้องสมบูรณ์ก่อนการแก้ไขของคุณ ลองถามคำถามใหม่แทน
Behe

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

4

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

อีกบทความที่เกี่ยวข้องคือการปรับรูปภาพ Docker ให้เหมาะสม CenturyLink Labsซึ่งอธิบายว่าหากคุณดาวน์โหลดสิ่งต่างๆในระหว่างการสร้างคุณสามารถหลีกเลี่ยงการเสียพื้นที่ในภาพสุดท้ายโดยการดาวน์โหลดสร้างและลบการดาวน์โหลดทั้งหมดในขั้นตอน RUN เดียว


3

มันน่าเกลียด แต่ฉันก็ประสบความสำเร็จในลักษณะนี้:

Dockerfile:

FROM foo
COPY ./m2/ /root/.m2
RUN stuff

imageBuild.sh:

docker build . -t barImage
container="$(docker run -d barImage)"
rm -rf ./m2
docker cp "$container:/root/.m2" ./m2
docker rm -f "$container"

ฉันมีการสร้าง Java ที่ดาวน์โหลดลงในจักรวาล /root/.m2 และทำเพื่อให้ทุกครั้งเดียว imageBuild.shคัดลอกเนื้อหาของโฟลเดอร์นั้นไปยังโฮสต์หลังจากบิลด์และDockerfileคัดลอกกลับไปยังอิมเมจสำหรับบิลด์ถัดไป

นี่คือสิ่งที่ดูเหมือนว่าปริมาณจะทำงานอย่างไร (เช่นมันยังคงอยู่ระหว่างการสร้าง)


นี่เป็นโซลูชันที่ใช้การได้สำหรับการรวมอย่างต่อเนื่องที่ใช้ Docker-based aka CI ตั้งค่าไลบรารีและคอมไพเลอร์และเรียกใช้สร้างผ่านคำสั่ง Dockerfile เรียกใช้อิมเมจเพียงเล็กน้อยเพื่อสร้างคอนเทนเนอร์และคัดลอกสิ่งประดิษฐ์ที่ต้องการเช่น. deb ดูเหมือนว่าจะทำงานขอบคุณสำหรับการโพสต์นี้
chrisinmtown

วิธีการแก้ปัญหานี้ทำให้คุณมีภาพด้วยไฟล์ทั้งหมดใน. /m2/ - ภาพที่คุณต้องการและภาพที่คุณไม่ต้องการ - และสิ่งนี้สามารถนำไปสู่ภาพการผลิตขนาดใหญ่ซึ่งไม่ต้องการ! ด้วยการเมาท์กับไดเร็กทอรีการพึ่งพาภายนอกเฉพาะไฟล์ที่จำเป็นเท่านั้นที่จะถูกคัดลอกไปยังรูปภาพ
Marko Krajnc

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

1

นี่เป็นเวอร์ชันที่เรียบง่ายของวิธีการ 2 ขั้นตอนโดยใช้ build และ commit โดยไม่มีเชลล์สคริปต์ มันเกี่ยวข้องกับ:

  1. การสร้างภาพบางส่วน โดยไม่มีปริมาณ
  2. เรียกใช้คอนเทนเนอร์ด้วยโวลุ่มทำการเปลี่ยนแปลงจากนั้นส่งมอบผลลัพธ์แทนที่ชื่อรูปภาพดั้งเดิม

เมื่อมีการเปลี่ยนแปลงเล็กน้อยขั้นตอนเพิ่มเติมจะเพิ่มเวลาสร้างเพียงไม่กี่วินาที

โดยทั่วไป:

docker build -t image-name . # your normal docker build

# Now run a command in a throwaway container that uses volumes and makes changes:
docker run -v /some:/volume --name temp-container image-name /some/post-configure/command

# Replace the original image with the result:
# (reverting CMD to whatever it was, otherwise it will be set to /some/post-configure/command)   
docker commit --change="CMD bash" temp-container image-name 

# Delete the temporary container:
docker rm temp-container

ในกรณีการใช้งานของฉันฉันต้องการสร้างไฟล์ maven toolchains.xml ล่วงหน้า แต่การติดตั้ง JDK จำนวนมากของฉันอยู่ในโวลุ่มที่ไม่สามารถใช้งานได้จนกว่าจะถึงรันไทม์ รูปภาพบางรูปของฉันไม่สามารถทำงานร่วมกับ JDKS ได้ทั้งหมดดังนั้นฉันต้องทดสอบความเข้ากันได้ในเวลาบิลด์และเติม toolchains.xml แบบมีเงื่อนไข โปรดทราบว่าฉันไม่ต้องการให้รูปภาพพกพาฉันไม่ได้เผยแพร่ไปยัง Docker Hub


1

ตามที่หลายคนได้ตอบไปแล้วการติดตั้งไดรฟ์ข้อมูลโฮสต์ในระหว่างการสร้างเป็นไปไม่ได้ ฉันแค่อยากจะเพิ่มdocker-composeวิธีฉันคิดว่ามันจะเป็นเรื่องดีที่จะมีส่วนใหญ่สำหรับการพัฒนา / ทดสอบการใช้งาน

Dockerfile

FROM node:10
WORKDIR /app
COPY . .
RUN npm ci
CMD sleep 999999999

นักเทียบท่า-compose.yml

version: '3'
services:
  test-service:
    image: test/image
    build:
      context: .
      dockerfile: Dockerfile
    container_name: test
    volumes:
      - ./export:/app/export
      - ./build:/app/build

และเรียกใช้ภาชนะของคุณโดย docker-compose up -d --build

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