วิธีการบังคับนักเทียบท่าสำหรับโครงสร้างที่สะอาดของรูปภาพ


814

ฉันสร้างภาพนักเทียบท่าจากไฟล์นักเทียบท่าโดยใช้คำสั่งด้านล่าง

$ docker build -t u12_core -f u12_core .

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

Step 1 : FROM ubuntu:12.04
 ---> eb965dfb09d2
Step 2 : MAINTAINER Pavan Gupta <pavan.gupta@gmail.com>
 ---> Using cache
 ---> 4354ccf9dcd8
Step 3 : RUN apt-get update
 ---> Using cache
 ---> bcbca2fcf204
Step 4 : RUN apt-get install -y openjdk-7-jdk
 ---> Using cache
 ---> 103f1a261d44
Step 5 : RUN apt-get install -y openssh-server
 ---> Using cache
 ---> dde41f8d0904
Step 6 : RUN apt-get install -y git-core
 ---> Using cache
 ---> 9be002f08b6a
Step 7 : RUN apt-get install -y build-essential
 ---> Using cache
 ---> a752fd73a698
Step 8 : RUN apt-get install -y logrotate
 ---> Using cache
 ---> 93bca09b509d
Step 9 : RUN apt-get install -y lsb-release
 ---> Using cache
 ---> fd4d10cf18bc
Step 10 : RUN mkdir /var/run/sshd
 ---> Using cache
 ---> 63b4ecc39ff0
Step 11 : RUN echo 'root:root' | chpasswd
 ---> Using cache
 ---> 9532e31518a6
Step 12 : RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
 ---> Using cache
 ---> 47d1660bd544
Step 13 : RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
 ---> Using cache
 ---> d1f97f1c52f7
Step 14 : RUN wget -O aerospike.tgz 'http://aerospike.com/download/server/latest/artifact/ubuntu12'
 ---> Using cache
 ---> bd7dde7a98b9
Step 15 : RUN tar -xvf aerospike.tgz
 ---> Using cache
 ---> 54adaa09921f
Step 16 : RUN dpkg -i aerospike-server-community-*/*.deb
 ---> Using cache
 ---> 11aba013eea5
Step 17 : EXPOSE 22 3000 3001 3002 3003
 ---> Using cache
 ---> e33aaa78a931
Step 18 : CMD /usr/sbin/sshd -D
 ---> Using cache
 ---> 25f5fe70fa84
Successfully built 25f5fe70fa84

แคชแสดงว่ามีการติดตั้ง aerospike อย่างไรก็ตามฉันไม่พบภายในภาชนะวางไข่จากภาพนี้ดังนั้นฉันต้องการสร้างภาพนี้ใหม่โดยไม่ใช้แคช ฉันจะบังคับให้นักเทียบท่าสร้างภาพใหม่ที่ไม่มีแคชได้อย่างไร


10
นอกจากนี้คุณควรพยายามลดจำนวนRUNคำสั่งให้น้อยที่สุด
tripleee

4
@tripleee คุณช่วยอธิบายได้ไหม
ยะ

9
@Ya มันเคยเป็นที่ Docker สร้างเลเยอร์แยกต่างหากสำหรับแต่ละRUNคำสั่งเสมอดังนั้นคำสั่งที่DockerfileมีหลายRUNคำสั่งจะใช้เนื้อที่ดิสก์จำนวนมหาศาล แต่สิ่งนี้ได้รับการปรับปรุงให้ดีขึ้นบ้างในเวอร์ชันล่าสุด
tripleee

เมื่อฉันลองdocker-compose up -dฉันสามารถใช้--no-cacheที่ไหน
Oo

@Oo นั่นเป็นไปไม่ได้ ก่อนอื่นคุณต้องทำdocker-compose build --no-cacheแล้วdocker-compose up -d
มาร์ตินเมลกา

คำตอบ:


1441

มี--no-cacheตัวเลือกคือ:

docker build --no-cache -t u12_core -f u12_core .

ใน Docker เวอร์ชันเก่าที่คุณต้องผ่าน--no-cache=trueแต่นี่ไม่ใช่กรณีอีกต่อไป


89
นอกจากนี้ทราบว่าทำงานร่วมกับ--no-cache docker-compose build
Blackus

42
--pullนอกจากนี้คุณยังอาจต้องการที่จะใช้ นี่จะบอกนักเทียบท่าเพื่อรับอิมเมจฐานเวอร์ชันล่าสุด สิ่งนี้มีความจำเป็นเพิ่มเติม--no-cacheหากคุณมีภาพฐาน (เช่น:) อยู่แล้วubuntu/latestและภาพพื้นฐานได้รับการอัปเดตนับตั้งแต่คุณดึงภาพครั้งสุดท้าย ดูเอกสารที่นี่
Collin Krawll

2
@CollinKrawll: --pullตัวเลือกนี้ทำเพื่อฉัน เพียงแค่--no-cacheสร้างยังคงยากจน ใส่ใน--pullเช่นกันสร้างงาน! ขอบคุณ!
Erdős-Bacon

1
หากมีใครบางคนกำลังเรียกนักสร้างนักเทียบท่าไม่คิดว่าพวกเขาต้องการสร้างโดยไม่มีแคชใช่หรือไม่ มีกรณีใดบ้างที่ผู้ใช้ต้องการสร้างภาพและใช้ภาพที่สร้างขึ้นก่อนหน้านี้ <rant> ฉันเพิ่งเสียวันไปเพราะการสร้างก่อนหน้านี้ล้มเหลวอย่างเงียบ ๆ แต่เสร็จสิ้น "ประสบความสำเร็จ" และฉันใช้ภาพที่เสียหายไม่เข้าใจว่าทำไมการอัปเดตสคริปต์สร้างไม่ทำงาน </rant>
Jeff

3
@Jeff เมื่อคุณพัฒนาอิมเมจนักเทียบท่าบิลด์บิลเดอร์จะทำซ้ำชั้น / ขั้นตอนที่ได้รับการแก้ไข หากฉันมีห้าขั้นตอนและฉันเพิ่มขั้นตอนใหม่ที่ดัชนี 3 เลเยอร์ที่เกี่ยวข้องกับขั้นตอนที่ 1 และ 2 สามารถนำกลับมาใช้ใหม่ได้ สิ่งนี้จะช่วยเร่งกระบวนการพัฒนาอย่างมาก
สะเก็ด

130

ในบางกรณีวิธีเดียวที่คุณจะประสบกับความล้มเหลวในการสร้างซ้ำคือการเรียกใช้:

docker system prune

คำสั่งจะขอให้คุณยืนยัน:

WARNING! This will remove:
    - all stopped containers
    - all volumes not used by at least one container
    - all networks not used by at least one container
    - all images without at least one container associated to them
Are you sure you want to continue? [y/N]

แน่นอนว่านี่ไม่ใช่คำตอบที่ตรงกับคำถาม แต่อาจช่วยชีวิตบางคน ... มันช่วยชีวิตฉันไว้


8
การเพิ่ม -a -f ทำให้ดีขึ้น
Ravi

1
@IulianOnofrei ใช้งานได้สำหรับฉันDocker version 17.09.0-ce, build afdb6d4
ต่อ Lundberg

1
@PerLundberg ฉันอัปเดตdockerเป็นรุ่นเดียวกันและใช้งานได้ดีขอบคุณ
Iulian Onofrei

1
นี่เป็นวิธี overkill สำหรับสถานการณ์นี้และไม่ใช่คำตอบที่ใช้ได้ถ้าคุณไม่ต้องการลบทุกอย่าง
M_dk

1
สิ่งนี้จะลบรูปภาพของคอนเทนเนอร์ที่หยุดทำงานซึ่งอาจเป็นสิ่งที่คุณไม่ต้องการ เวอร์ชันล่าสุดของนักเทียบท่ามีคำสั่งdocker builder pruneเพื่อล้างเลเยอร์การสร้างแคช เพิ่งตกลงไปในกับดักหลังจากคัดลอกคำสั่งจากสแตกล้นอย่างสุ่ม
Evil Azrael

59

คำสั่งdocker build --no-cache .แก้ไขปัญหาที่คล้ายกันของเรา

Dockerfile ของเราคือ:

RUN apt-get update
RUN apt-get -y install php5-fpm

แต่ควรจะ:

RUN apt-get update && apt-get -y install php5-fpm

เพื่อป้องกันการแคชอัพเดตและติดตั้งแยกต่างหาก

โปรดดู: แนวทางปฏิบัติที่ดีที่สุดสำหรับการเขียน Dockerfiles


10
"ควร" ถูกทำให้เข้าใจผิด หากนักเทียบท่าเห็นว่ามันมีสำเนาแคชของRUN apt-get update && apt-get -y install php5-fpmคุณจะยังคงเห็นว่ามันถูกนำมาใช้ซ้ำกับเนื้อหาเก่า
tripleee

10
จริงๆแล้วมันยังมีเหตุผลที่จะเข้าร่วมเพราะถ้าคุณเปลี่ยนสายการติดตั้งมันจะยังคงใช้แคชแพ็กเกจเก่าซึ่งมักจะมีปัญหาหากแคชล้าสมัย (ปกติแล้วไฟล์จะ 404)
John Chadwick

18

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

--no-cache - สิ่งนี้จะบังคับให้สร้างเลเยอร์ใหม่ที่มีอยู่แล้ว

--pull - สิ่งนี้จะทริกเกอร์การดึงภาพฐานอ้างอิงโดยใช้ FROM เพื่อให้แน่ใจว่าคุณได้รับเวอร์ชันล่าสุด

คำสั่งเต็มจะมีลักษณะเช่นนี้:

docker build --pull --no-cache --tag myimage:version .

มีตัวเลือกเดียวกันสำหรับ docker-compose:

docker-compose build --no-cache --pull

13

ฉันจะไม่แนะนำให้ใช้--no-cacheในกรณีของคุณ

คุณกำลังเรียกใช้งานการติดตั้งสองสามขั้นตอนตั้งแต่ 3 ถึง 9 (โดยปกติแล้วฉันชอบใช้สายการบินเดียว) และหากคุณไม่ต้องการใช้ขั้นตอนเหล่านี้ซ้ำในทุกครั้งที่คุณสร้างภาพคุณสามารถทำได้ ปรับเปลี่ยนของคุณDockerfileด้วยขั้นตอนชั่วคราวก่อนที่จะมีการwgetสอนของคุณ

ฉันใช้เพื่อทำสิ่งที่ชอบRUN ls .และเปลี่ยนเป็นRUN ls ./แล้วเรื่อยRUN ls ./.ๆ สำหรับการดัดแปลงแต่ละอย่างที่ทำใน tarball ที่ดึงมาโดยwget

แน่นอนคุณสามารถทำบางสิ่งบางอย่างเช่นการRUN echo 'test1' > test && rm testเพิ่มจำนวนใน'test1แต่ละรอบซ้ำ

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


3
ความสามารถในการไม่สามารถใช้แคชหลังจากจุดหนึ่งเป็นคุณลักษณะที่ร้องขอโดยหลายคน (ดูgithub.com/moby/moby/issues/1996สำหรับทางเลือกสำหรับการแคชแคช)
leszek.hanusz

13

ด้วยความพยายามเขียนนักเทียบท่า docker-compose up -d --build --force-recreate


5

ข้อมูลส่วนใหญ่ที่นี่ถูกต้อง
นี่เป็นการรวบรวมพวกเขาและวิธีการใช้งานของพวกเขา

แนวคิดคือการยึดตามแนวทางที่แนะนำ (สร้างเฉพาะและไม่มีผลกระทบกับวัตถุนักเทียบท่าที่เก็บไว้อื่น ๆ ) และลองใช้วิธีที่รุนแรงกว่านี้ (ไม่สร้างเฉพาะและมีผลกระทบกับวัตถุนักเทียบท่าที่เก็บไว้อื่น ๆ ) เมื่อมันไม่เพียงพอ

วิธีที่แนะนำ:

1) บังคับให้ดำเนินการตามแต่ละขั้นตอน / คำสั่งใน Dockerfile:

docker build --no-cache 

หรือด้วยdocker-compose build:

docker-compose build --no-cache

เราสามารถรวมupคำสั่งย่อยนั้นกับคำสั่งย่อยที่สร้างคอนเทนเนอร์ทั้งหมดขึ้นมาใหม่:

docker-compose build --no-cache &&
docker-compose up -d --force-recreate 

วิธีเหล่านี้ไม่ใช้แคช แต่สำหรับตัวสร้างนักเทียบท่าและอิมเมจพื้นฐานที่อ้างอิงกับFROMคำแนะนำ

2) เช็ดแคชตัวสร้างนักเทียบท่า (ถ้าเราใช้ Buildkit เราอาจจำเป็นต้องใช้มันมาก):

docker builder prune -af

3) หากเราไม่ต้องการใช้แคชของภาพหลักเราอาจลองลบภาพเช่น:

docker image rm -f fooParentImage

ในกรณีส่วนใหญ่ 3 สิ่งเหล่านี้สมบูรณ์เพียงพอที่จะทำให้ภาพลักษณ์ของเราสะอาดตา
ดังนั้นเราควรพยายามทำเช่นนั้น

วิธีการที่รุนแรงมากขึ้น:

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

1) ลบรูปภาพทั้งหมดโดยไม่มีคอนเทนเนอร์อย่างน้อยหนึ่งคอนเทนเนอร์ที่เกี่ยวข้อง:

docker image prune -a

2) ลบสิ่งอื่น ๆ อีกมากมาย:

docker system prune -a

ที่พูดว่า:

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

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


3

คุณสามารถจัดการแคชตัวสร้างด้วย docker builder

ในการทำความสะอาดแคชทั้งหมดโดยไม่แจ้งให้ทำดังนี้ docker builder prune -af

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