สร้างบริบทสำหรับภาพนักเทียบท่าที่มีขนาดใหญ่มาก


166

ฉันได้สร้างไดเรกทอรีที่แตกต่างกันสองสามรายการบนเครื่องโฮสต์ของฉันขณะที่ฉันพยายามเรียนรู้เกี่ยวกับ Docker เพื่อให้ Dockerfiles ของฉันเป็นระเบียบ Dockerfile ของฉันฉันเพิ่งวิ่งมีลักษณะดังนี้:

FROM crystal/centos
MAINTAINER crystal

ADD ./rpms/test.rpm ./rpms/ 
RUN yum -y --nogpgcheck localinstall /rpms/test.rpm 

รอบต่อนาทีจริงของฉันคือ 1 GB เท่านั้น แต่เมื่อฉันพยายามทำsudo docker build -t="crystal/test" .ฉันได้รับการส่ง build context ไปยัง Docker daemon 3.5 GB มีอะไรอีกบ้างที่ฉันไม่รู้ขณะที่คุณสร้างอิมเมจ Docker ต่อไป? หน่วยความจำของฉันกำลังสะสมเมื่อฉันสร้างภาพเพิ่มเติมในไดเรกทอรีอื่นบนเครื่องโฮสต์ของฉันหรือไม่


3
บริบทการสร้างคือไฟล์ / ไดเร็กทอรีทั้งหมดในไดเร็กทอรีปัจจุบัน
นาบิน

1
เก็บเฉพาะไฟล์ที่คุณต้องการสำหรับบิลด์ในไดเร็กทอรีนี้ นั่นคือ Dockerfile และไฟล์ / ไดเร็กทอรีในเครื่องใด ๆ ที่คัดลอก / เพิ่มลงในอิมเมจบิลด์ใน Dockerfile นอกจากนี้ให้ใช้.dockerignore
Vishrant

คำตอบ:


304

ไคลเอ็นต์ Docker ส่ง "บริบทการสร้าง" ทั้งหมดไปยัง Docker daemon บริบทการสร้างนั้น (โดยค่าเริ่มต้น) คือไดเร็กทอรีทั้งหมดที่Dockerfileอยู่ใน (ดังนั้นrpmsโครงสร้างทั้งหมด)

คุณสามารถตั้งค่า.dockerignoreไฟล์เพื่อให้ Docker ละเว้นไฟล์บางไฟล์ได้ คุณอาจต้องการทดลองกับมัน

หรือคุณสามารถย้ายrpmsโฟลเดอร์ของคุณขึ้นหนึ่งระดับไดเร็กทอรีของคุณDockerfileและมีเพียง symlink test.rpmไปยังDockerfileไดเร็กทอรีของ


คุณมักจะต้องการเพิ่ม.gitโฟลเดอร์.dockerignoreซึ่งเป็นสาเหตุของความแตกต่าง 150MB -> 5GB สำหรับผู้ใช้บางคนในความคิดเห็นที่นี่


4
น่าเสียดายที่ดูเหมือนว่า symlinking จะไม่สามารถทำได้ในกรณีนี้เนื่องจากADDคำสั่งไม่ติดตามลิงก์ sym ระหว่างการสร้าง ดู: github.com/docker/docker/issues/1676
JimmidyJoo

5
ช่วยชีวิต! นักพัฒนา Rails: อย่าลืมเพิ่มtmp logไปยัง.dockerignore+ รายการที่กำหนดเองอื่น ๆ
เทียบเท่า

8
อย่าลืมเพิ่มโฟลเดอร์. git ไปยังไฟล์. dockerignore (สมมติว่าคุณใช้ git)
dsncode

8
ใช่.gitโฟลเดอร์จะถูกรวมไว้โดยค่าเริ่มต้น - สิ่งนี้ทำให้ฉันรู้สึกแย่อย่างแน่นอน
Paul Suart

1
"บริบทการสร้าง" คืออะไรกันแน่? ฉันพยายามค้นหาไฟล์เหล่านี้โดยใช้คำสั่ง docker build RUN แต่ฉันไม่เห็นไฟล์ในโฟลเดอร์ Dockerfile ของฉันภายในระบบไฟล์นักเทียบท่า (ในช่วงเวลาสร้าง) ใครช่วยยกตัวอย่างง่ายๆให้ฉันหน่อยได้ไหมว่าบริบทการสร้างมีประโยชน์อย่างไร
Patrick

65

อัปเดต 2019

เริ่มต้นจากการเทียบท่า v18.06 มีตัวเลือกที่จะใช้ภาพใหม่ที่เรียกว่าสร้างชุดรูปร่าง

มาพร้อมกับ Docker โดยไม่จำเป็นต้องติดตั้งอะไรเลย เข้ากันได้กับDockerfileไวยากรณ์แบบย้อนหลังโดยไม่จำเป็นต้องเปลี่ยนไฟล์Dockerfile.

Legacy Docker Build เทียบกับ Docker BuildKit ใหม่

นี่คือตัวอย่างของการสร้างอิมเมจด้วยไฟล์ขนาดใหญ่ที่ไม่ได้ใช้ในไดเร็กทอรี build:

Legacy Docker Build:

$ time docker image build --no-cache .
Sending build context to Docker daemon  4.315GB
[...]
Successfully built c9ec5d33e12e

real    0m51.035s
user    0m7.189s
sys 0m10.712s

ใหม่ Docker BuildKit:

$ time DOCKER_BUILDKIT=1 docker image build --no-cache .
[+] Building 0.1s (5/5) FINISHED                                                
 => [internal] load build definition from Dockerfile                       0.0s
 => => transferring dockerfile: 37B                                        0.0s
 => [internal] load .dockerignore                                          0.0s
 => => transferring context: 2B                                            0.0s
[...]
 => => writing image sha256:ba5bca3a525ac97573b2e1d3cb936ad50cf8129eedfa9  0.0s

real    0m0.166s
user    0m0.034s
sys 0m0.026s

การเปลี่ยนแปลงเพียงอย่างเดียวคือDOCKER_BUILDKIT=1ตัวแปรสภาพแวดล้อมความแตกต่างของเวลามีมาก

.dockerignore ไฟล์

โปรดทราบว่า.dockerignoreไฟล์ยังคงถูกต้องและมีประโยชน์ บางDockerfileคำสั่งเช่นCOPY . .จะยังคงคำนึงถึง.dockerignoreกฎ แต่ไฟล์ด้านข้างในไดเร็กทอรี build (ไม่ได้อ้างอิงในDockerfile) จะไม่ถูกคัดลอกอีกต่อไปในฐานะ "build context" โดย BuildKit


2
โปรดทราบว่าปัจจุบัน DOCKER_BUILDKIT ยังไม่รองรับ Windows Containers (เฉพาะ Linux ระบุไว้ภายใต้ข้อ จำกัด : docs.docker.com/develop/develop-images/build_enhancements )
Vaccano

ใช้งานได้บน macOS 10.15 ตั้งแต่วันที่ 2020-09-05!
LexH

สิ่งนี้ดูเหมือนจะไม่มีเหตุผล buildkit ยังคงส่งบริบทการสร้างก่อน บริบทการสร้างเปลี่ยนจาก 4.3GB เป็น ?? B และ 0s ได้อย่างไรเพียงแค่เปิดตัวเลือก? เพราะนั่นไม่ใช่ประสบการณ์ของฉัน ฉันมีขนาดบริบทเดียวกันที่ถ่ายโอน: => [internal] load build context => => transferring context: 924.39MB 86.3sคุณแค่[...]บรรทัดที่ควรแสดง 4.3 GB อย่างน้อยครั้งแรกที่ทำงาน จริงอยู่ที่ครั้งที่สองจะไม่ถ่ายโอนบริบทอีกครั้งซึ่งเป็นสิ่งที่เราทุกคนต้องการ
dlamblin

@dlamblin โปรดดู.dockerignoreส่วนของคำตอบ: BuildKit ไม่คัดลอกไฟล์ด้านข้างในไดเร็กทอรี build อีกต่อไป (ไม่ได้อ้างอิงใน Dockerfile) โดยปกติจะเป็นเช่นนั้น แต่ประสบการณ์ของคุณอาจแตกต่างกันไป)
Andriy Berestovskyy

1
ฉันเห็น; คุณมีไฟล์ที่ไม่จำเป็นในบริบทการสร้างในขณะที่ฉันมีไฟล์ที่จำเป็นเกือบ 1GB ตอนนี้ ... buildkit ดีกว่ามาก มันไม่ได้ส่งไฟล์ซ้ำสำหรับการสร้างความล้มเหลวที่แคชไว้และดูเหมือนว่าจะย้ายไฟล์ที่จำเป็นเท่านั้น (ตามที่คุณชี้ให้เห็น)
dlamblin

17

ฉันแก้ไขโดยย้าย Dockerfile และ docker-compose.yml ไปไว้ในโฟลเดอร์ย่อยและใช้งานได้ดี เห็นได้ชัดว่านักเทียบท่าส่งโฟลเดอร์ปัจจุบันไปยัง daemon และโฟลเดอร์ของฉันคือ 9 กิ๊ก


5
วิธีนี้ให้พา ธ Forbidden: นอกข้อผิดพลาดบริบทการสร้างหากไฟล์จากไดเร็กทอรีพาเรนต์ถูกคัดลอกวิธีแก้ปัญหานี้หรือไม่
Kitwradr

9

หากคุณมี.dockerignoreไฟล์และบริบทของบิลด์ยังมีขนาดใหญ่คุณสามารถตรวจสอบสิ่งที่กำลังส่งไปยังบริบทการสร้างนักเทียบท่าโดยใช้The Silver Searcher :

ag --path-to-ignore .dockerignore --files-with-matches

โปรดทราบว่า**รูปแบบบางอย่างอาจทำงานไม่ถูกต้อง

ดูปัญหา Github นี้สำหรับความคิดเห็นเพิ่มเติม: https://github.com/moby/moby/issues/16056


4

ในกรณีของฉันนั่นคือเมื่อฉันดำเนินการกับ-fอาร์กิวเมนต์ที่ไม่ถูกต้อง- โดยไม่มีเส้นทางไปยังไดเร็กทอรีที่ Dockerfile อยู่

docker build --no-cache -t nginx5 -f /home/DF/Dockerfile /home/DF/ - ใช่

docker build --no-cache -t nginx5 -f /home/DF/Dockerfile - ไม่ถูกต้อง


1

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

docker build - < Dockerfile

ข้อเสียอย่างหนึ่งคือด้วยวิธีนี้คุณสามารถทำได้เฉพาะADDสิ่งต่างๆใน Dockerfile ที่อ้างถึง URL ระยะไกลเท่านั้นไม่ใช่ไฟล์จากโฮสต์ภายในของคุณ

ดูhttps://docs.docker.com/engine/reference/commandline/build/#build-with--


0

ฉันมีปัญหาเดียวกันกับ FreeStyler อย่างไรก็ตามฉันสร้างจากไดเรกทอรีหนึ่งขึ้นมาจากบริบทของฉัน ดังนั้นอาร์กิวเมนต์ -f จึงถูกต้องบริบทไม่ถูกต้อง

project 
|
-------docker-dir 

การสร้างจาก Docker-dir สิ่งต่อไปนี้ทำได้ดี

docker build -t br_base:0.1 . 

การสร้างจากท่าเรือทำให้บริบทการสร้างเปลี่ยนไป ดังนั้นฉันต้องเปลี่ยนบริบทในคำสั่ง บริบทกำหนดโดย "." ในคำสั่งด้านบน

คำสั่งใหม่จากไดเร็กทอรีโปรเจ็กต์ควรเป็น

docker build -t br_base:0.1 ./base

บริบทที่นี่กำหนดโดย "./base"


0

หากคุณกำลังสร้างอิมเมจและรับข้อความที่ ส่งบริบทการสร้างไปยัง Docker daemonซึ่งใช้เวลาบันทึกในการคัดลอก

จากนั้นเพิ่มไฟล์ . dockerignore ควรมีไฟล์หรือไดเร็กทอรีที่ไม่จำเป็นต้องคัดลอก



-1

เพื่อสรุปสิ่งที่คุณสามารถทำได้หากบริบทของ Docker สร้างขึ้นมีขนาดใหญ่เกินไป:

  • ตรวจสอบให้แน่ใจว่าคุณไม่มีไฟล์ที่ไม่ได้ใช้ในบริบท (ไฟล์ที่ไม่ได้ใช้ - ไฟล์ที่ยังไม่สามารถแตะต้องได้ในระหว่างการสร้างภาพ)
  • เพิ่มไฟล์และ / หรือไดเร็กทอรีที่ไม่ได้ใช้ลงใน. dockerignore (ตามที่กล่าวไว้ที่นี่ );
  • ตรวจสอบให้แน่ใจว่าคุณระบุโฟลเดอร์ที่ถูกต้องเป็นบริบทการสร้างภาพ (ดังที่กล่าวไว้ที่นี่ )
  • พยายามใช้ BuildKit กับ DOCKER_BUILDKIT = 1 (ตามที่กล่าวไว้ที่นี่ );
  • พยายามแบ่งโครงการของคุณออกเป็นส่วนย่อย ๆ เพื่อปรับเนื้อหาของบริบทการสร้างให้เหมาะสม
  • หากคุณมีโปรเจ็กต์ที่ซับซ้อนคุณอาจต้องการรวบรวมไฟล์ที่จำเป็นทั้งหมดด้วยตนเองในโฟลเดอร์ที่แยกจากกันก่อนสร้างและใช้เป็นบริบทการสร้างสำหรับรูปภาพเฉพาะ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.