รูปภาพอย่างเป็นทางการของ Docker เป็นรูปภาพที่ได้รับการดูแลจัดการซึ่งโฮสต์บน Docker Hub หลักการหลักคือ:
มุ่งเน้นไปที่ซอฟต์แวร์ฟรีและโอเพ่นซอร์ส
รองรับสถาปัตยกรรมหลายแบบ
เป็นตัวอย่างแนวทางปฏิบัติที่ดีที่สุด Dockerfile
สร้างใหม่อย่างแข็งขันเพื่อรับการอัปเดตและการแก้ไขความปลอดภัย
ปฏิบัติตามคำแนะนำต้นน้ำ
เพิ่มพฤติกรรมคุณภาพชีวิตขั้นต่ำสำหรับสภาพแวดล้อมคอนเทนเนอร์ที่เหมาะสม
ดูเอกสารประกอบของ Docker สำหรับภาพรวมระดับสูงที่ดีของโปรแกรม
โดยพื้นฐานแล้ว เรามุ่งมั่นที่จะรับฟังคำแนะนำของต้นน้ำเกี่ยวกับวิธีการที่พวกเขาตั้งใจจะใช้งานซอฟต์แวร์ของตน รูปภาพจำนวนมากได้รับการดูแลโดยความร่วมมือกับโครงการต้นน้ำที่เกี่ยวข้อง หากไม่ได้รับการดูแลโดยตรง นอกจากนี้ เรายังมุ่งหวังที่จะเป็นตัวอย่างแนวทางปฏิบัติที่ดีที่สุดสำหรับ Dockerfiles เพื่อใช้เป็นข้อมูลอ้างอิงในการสร้างหรือรับอิมเมจของคุณเองจากสิ่งเหล่านี้
(หากคุณเป็นตัวแทนของต้นน้ำที่มีรูปภาพอยู่ และคุณต้องการมีส่วนร่วม โปรดดูส่วนการบำรุงรักษาด้านล่าง!)
ภาพบางภาพได้รับการย้ายสำหรับสถาปัตยกรรมอื่น ๆ และหลายภาพได้รับการสนับสนุนอย่างเป็นทางการ (ในระดับต่างๆ)
arm32v6
): https://hub.docker.com/u/arm32v6/arm32v7
): https://hub.docker.com/u/arm32v7/arm64v8
): https://hub.docker.com/u/arm64v8/amd64
): https://hub.docker.com/u/amd64/windows-amd64
): https://hub.docker.com/u/winamd64/arm32v5
): https://hub.docker.com/u/arm32v5/ppc64le
): https://hub.docker.com/u/ppc64le/s390x
): https://hub.docker.com/u/s390x/mips64le
): https://hub.docker.com/u/mips64le/riscv64
): https://hub.docker.com/u/riscv64/i386
): https://hub.docker.com/u/i386/ ณ วันที่ 12-09-2560 สถาปัตยกรรมอื่นๆ เหล่านี้จะรวมอยู่ในรูปภาพที่ไม่มีคำนำหน้าผ่าน "รายการรายการ" (หรือที่เรียกว่า "ดัชนี" ในข้อกำหนดรูปภาพของ OCI) เช่นว่า docker run hello-world
ควร ทำงานตามที่เป็นอยู่บนแพลตฟอร์มที่รองรับทั้งหมด
หากคุณสงสัยว่าสิ่งเหล่านี้ถูกสร้างขึ้นอย่างไร ให้ไปที่ https://doi-janky.infosiftr.net/job/multiarch/ เพื่อดูโครงนั่งร้าน
ดูส่วนโค้งหลายส่วนด้านล่างสำหรับคำแนะนำในการเพิ่มสถาปัตยกรรมให้กับภาพที่เป็นทางการ
ใช่! เรามีพื้นที่เก็บข้อมูลคำถามที่พบบ่อยโดยเฉพาะซึ่งเราพยายามรวบรวมคำถามทั่วไปอื่นๆ (ทั้งเกี่ยวกับโปรแกรมและแนวทางปฏิบัติของเรา)
ขอขอบคุณที่ให้ความสนใจในโครงการรูปภาพอย่างเป็นทางการของ Docker! เรามุ่งมั่นที่จะทำให้คำแนะนำเหล่านี้เรียบง่ายและตรงไปตรงมาที่สุดเท่าที่จะเป็นไปได้ แต่หากคุณพบว่าตัวเองหลงทาง อย่าลังเลที่จะติดต่อเราที่ Libera.Chat IRC ในช่อง #docker-library
หรือโดยสร้างปัญหา GitHub ที่นี่
อย่าลืมทำความคุ้นเคยกับ Official Repositories บน Docker Hub และแนวปฏิบัติที่ดีที่สุดในการเขียน Dockerfiles ในเอกสารประกอบของ Docker สิ่งเหล่านี้จะเป็นพื้นฐานของกระบวนการตรวจสอบที่ดำเนินการโดยผู้ดูแลรูปภาพอย่างเป็นทางการ หากคุณต้องการให้กระบวนการตรวจสอบดำเนินไปอย่างราบรื่นยิ่งขึ้น โปรดตรวจสอบให้แน่ใจว่า Dockerfile
ของคุณปฏิบัติตามประเด็นทั้งหมดที่กล่าวถึงในที่นี้ รวมถึงด้านล่าง ก่อนที่จะส่งคำขอดึงข้อมูล
นอกจากนี้ คำอธิบาย Hub สำหรับอิมเมจเหล่านี้ยังถูกจัดเก็บแยกต่างหากในพื้นที่เก็บ docker-library/docs
ซึ่งไฟล์ README.md
จะอธิบายเพิ่มเติมเกี่ยวกับวิธีการจัดโครงสร้างและวิธีการมีส่วนร่วม โปรดเตรียมส่งประชาสัมพันธ์ที่นั่นด้วย โดยรอการยอมรับภาพของคุณที่นี่
เนื่องจากอิมเมจอย่างเป็นทางการมีจุดมุ่งหมายเพื่อเป็นเครื่องมือการเรียนรู้สำหรับผู้ที่เพิ่งเริ่มใช้ Docker เช่นเดียวกับอิมเมจพื้นฐานสำหรับผู้ใช้ขั้นสูงในการสร้างเวอร์ชันที่ใช้งานจริง เราจึงตรวจสอบแต่ละ Dockerfile
ที่เสนอเพื่อให้แน่ใจว่าเป็นไปตามมาตรฐานขั้นต่ำในด้านคุณภาพและการบำรุงรักษา แม้ว่ามาตรฐานบางส่วนนั้นยากที่จะให้คำจำกัดความ (เนื่องจากความเป็นส่วนตัว) แต่ให้กำหนดไว้ที่นี่ให้มากที่สุดเท่าที่จะเป็นไปได้ ขณะเดียวกันก็ปฏิบัติตาม "แนวทางปฏิบัติที่ดีที่สุด" ตามความเหมาะสม
รายการตรวจสอบที่อาจใช้โดยผู้ดูแลในระหว่างการตรวจสอบสามารถพบได้ใน NEW-IMAGE-CHECKLIST.md
การเปลี่ยนแปลงเวอร์ชันและการแก้ไขด้านความปลอดภัยควรได้รับการดูแลอย่างทันท่วงที
หากคุณไม่ได้เป็นตัวแทนของอัพสตรีมและอัพสตรีมเริ่มสนใจที่จะดูแลรักษาอิมเมจ ควรดำเนินการตามขั้นตอนเพื่อให้แน่ใจว่าการเปลี่ยนการดูแลอิมเมจไปเป็นอัปสตรีมเป็นไปอย่างราบรื่น
สำหรับต้นน้ำที่สนใจรับช่วงการดูแลรักษาพื้นที่เก็บข้อมูลที่มีอยู่ ขั้นตอนแรกคือการเข้าไปมีส่วนร่วมในพื้นที่เก็บข้อมูลที่มีอยู่ การแสดงความคิดเห็นเกี่ยวกับประเด็นต่างๆ เสนอการเปลี่ยนแปลง และการทำให้ตัวเองเป็นที่รู้จักใน "ชุมชนรูปภาพ" (แม้ว่า "ชุมชน" จะเป็นเพียงผู้ดูแลคนปัจจุบันก็ตาม) ล้วนเป็นจุดเริ่มต้นที่สำคัญเพื่อให้แน่ใจว่าการเปลี่ยนแปลงนี้จะไม่น่าแปลกใจสำหรับผู้มีส่วนร่วมและผู้ใช้ที่มีอยู่
เมื่อเข้าครอบครองพื้นที่เก็บข้อมูลที่มีอยู่ โปรดตรวจสอบให้แน่ใจว่าประวัติ Git ทั้งหมดของพื้นที่เก็บข้อมูลเดิมถูกเก็บไว้ในพื้นที่เก็บข้อมูลที่ได้รับการดูแลแบบอัปสตรีมใหม่ เพื่อให้แน่ใจว่ากระบวนการตรวจสอบจะไม่หยุดชะงักในระหว่างการเปลี่ยนแปลง สิ่งนี้ทำได้ง่ายที่สุดโดยการฟอร์กอันใหม่จากที่เก็บที่มีอยู่ แต่ยังสามารถทำได้ด้วยการดึงคอมมิตโดยตรงจากต้นฉบับแล้วดันเข้าไปใน repo ใหม่ (เช่น git fetch https://github.com/jsmith/example.git master
, git rebase FETCH_HEAD
, git push -f
) บน GitHub อีกทางเลือกหนึ่งคือการย้ายการเป็นเจ้าของที่เก็บ git ซึ่งสามารถทำได้โดยไม่ต้องให้สิทธิ์ผู้ดูแลระบบกลุ่มใดกลุ่มหนึ่งเข้าถึงพื้นที่เก็บข้อมูลของเจ้าของอีกราย:
การสร้าง Dockerfile
เดียวกันใหม่ควรส่งผลให้อิมเมจเวอร์ชันเดียวกันถูกแพ็กเกจ แม้ว่าบิลด์ที่สองจะเกิดขึ้นหลายเวอร์ชันในภายหลัง หรือบิลด์ควรล้มเหลวโดยสิ้นเชิง ดังนั้นการสร้าง Dockerfile
ที่แท็กเป็น 0.1.0
ใหม่โดยไม่ตั้งใจจะไม่สิ้นสุด ขึ้นไปมี 0.2.3
ตัวอย่างเช่น หากใช้ apt
เพื่อติดตั้งโปรแกรมหลักสำหรับอิมเมจ อย่าลืมปักหมุดเป็นเวอร์ชันเฉพาะ (เช่น ... apt-get install -y my-package=0.1.0 ...
) สำหรับแพ็คเกจที่ต้องพึ่งพาซึ่งติดตั้งโดย apt
มักจะไม่จำเป็นต้องปักหมุดให้เป็นเวอร์ชัน
ไม่มีภาพที่เป็นทางการสามารถได้รับจากหรือขึ้นอยู่กับภาพที่ไม่เป็นทางการ (อนุญาตให้ scratch
ที่ไม่ใช่ภาพและมีข้อยกเว้นที่จำกัดโดยเจตนาปักหมุดใน .external-pins
-- ดูเพิ่มเติม .external-pins/list.sh
)
รูปภาพที่เป็นทางการทั้งหมดควรมีอินเทอร์เฟซที่สอดคล้องกัน ผู้ใช้เริ่มต้นควรจะสามารถ docker run official-image bash
(หรือ sh
) โดยไม่จำเป็นต้องเรียนรู้เกี่ยวกับ --entrypoint
นอกจากนี้ยังเป็นการดีสำหรับผู้ใช้ขั้นสูงที่จะใช้ประโยชน์จากจุดเข้าใช้ เพื่อให้พวกเขาสามารถ docker run official-image --arg1 --arg2
โดยไม่ต้องระบุไบนารีที่จะดำเนินการ
หากกระบวนการเริ่มต้นไม่ต้องการอาร์กิวเมนต์ ให้ใช้ CMD
:
CMD [ "irb" ]
หากมีการเริ่มต้นที่ต้องทำตั้งแต่เริ่มต้น เช่น การสร้างฐานข้อมูลเริ่มต้น ให้ใช้ ENTRYPOINT
ร่วมกับ CMD
:
ENTRYPOINT [ "/docker-entrypoint.sh" ]
CMD [ "postgres" ]
ตรวจสอบให้แน่ใจว่า docker run official-image bash
(หรือ sh
) ก็ใช้งานได้เช่นกัน วิธีที่ง่ายที่สุดคือตรวจสอบคำสั่งที่คาดไว้ และหากเป็นอย่างอื่น ให้ exec "$@"
(เรียกใช้คำสั่งใดก็ตามที่ถูกส่งผ่าน โดยหลีกเลี่ยงอาร์กิวเมนต์อย่างเหมาะสม)
#! /bin/sh
set -e
# this if will check if the first argument is a flag
# but only works if all arguments require a hyphenated flag
# -v; -SL; -f arg; etc will work, but not arg1 arg2
if [ " $# " -eq 0 ] || [ " ${1 # -} " != " $1 " ] ; then
set -- mongod " $@ "
fi
# check for the expected command
if [ " $1 " = ' mongod ' ] ; then
# init db stuff....
# use gosu (or su-exec) to drop to a non-root user
exec gosu mongod " $@ "
fi
# else default to run whatever the user wanted like "bash" or "sh"
exec " $@ "
หากรูปภาพมีเพียงไฟล์เรียกทำงานหลักและไลบรารีที่เชื่อมโยง (เช่น ไม่มีเชลล์) ก็สามารถใช้ไฟล์เรียกทำงานเป็น ENTRYPOINT
ได้ เนื่องจากนั่นเป็นสิ่งเดียวที่สามารถทำงานได้:
ENTRYPOINT [ "fully-static-binary" ]
CMD [ "--help" ]
ตัวบ่งชี้ที่พบบ่อยที่สุดว่าสิ่งนี้เหมาะสมหรือไม่คืออิมเมจ Dockerfile
เริ่มต้นด้วย scratch
( FROM scratch
)
พยายามทำให้ Dockerfile
เข้าใจ/อ่านง่าย เพื่อความกระชับ อาจเป็นการดึงดูดให้ใส่รายละเอียดการเริ่มต้นที่ซับซ้อนลงในสคริปต์แบบสแตนด์อโลนและเพียงเพิ่มคำสั่ง RUN
ใน Dockerfile
อย่างไรก็ตาม สิ่งนี้ทำให้ผลลัพธ์ของ Dockerfile
มีความทึบมากเกินไป และ Dockerfile
ดังกล่าวไม่น่าจะผ่านการตรวจสอบ ขอแนะนำให้ใส่คำสั่งทั้งหมดสำหรับการเริ่มต้นลงใน Dockerfile
แทนโดยใช้ชุดคำสั่ง RUN
หรือ ENV
ที่เหมาะสม หากต้องการค้นหาตัวอย่างที่ดี โปรดดูภาพที่เป็นทางการในปัจจุบัน
ตัวอย่างบางส่วนในขณะที่เขียน:
ตามแนวทางของ Docker ขอแนะนำอย่างยิ่งให้รูปภาพผลลัพธ์เป็นเพียงข้อกังวลเดียวต่อคอนเทนเนอร์ โดยส่วนใหญ่หมายถึงเพียงหนึ่งกระบวนการต่อคอนเทนเนอร์ ดังนั้นจึงไม่จำเป็นต้องมีระบบเริ่มต้นแบบเต็ม มีสองสถานการณ์ที่กระบวนการคล้าย init จะเป็นประโยชน์สำหรับคอนเทนเนอร์ สิ่งแรกคือการจัดการสัญญาณ หากกระบวนการที่เรียกใช้ไม่จัดการ SIGTERM
ด้วยการออก กระบวนการนั้นจะไม่ถูกฆ่าเนื่องจากเป็น PID 1 ในคอนเทนเนอร์ (ดู "หมายเหตุ" ที่ส่วนท้ายของส่วนเบื้องหน้าในเอกสารนักเทียบท่า) สถานการณ์ที่สองคือการเก็บเกี่ยวซอมบี้ หากกระบวนการวางไข่กระบวนการย่อยและไม่ได้เก็บเกี่ยวอย่างเหมาะสม จะนำไปสู่ตารางกระบวนการแบบเต็ม ซึ่งสามารถป้องกันไม่ให้ทั้งระบบวางไข่กระบวนการใหม่ใดๆ สำหรับข้อกังวลทั้งสองข้อนี้ เราขอแนะนำ tini มันมีขนาดเล็กอย่างไม่น่าเชื่อ มีการพึ่งพาภายนอกน้อยที่สุด เติมเต็มแต่ละบทบาทเหล่านี้ และทำเฉพาะส่วนที่จำเป็นในการเก็บเกี่ยวและการส่งต่อสัญญาณเท่านั้น
อย่าลืมใช้ tini ใน CMD
หรือ ENTRYPOINT
ตามความเหมาะสม
วิธีที่ดีที่สุดคือติดตั้ง tini จากแพ็คเกจที่ให้มา (เช่น apt-get install tini
) หากไม่มี tini ในการแจกจ่ายของคุณหรือเก่าเกินไป นี่คือตัวอย่างข้อมูลของ Dockerfile
ที่จะเพิ่มใน tini:
# Install tini for signal processing and zombie killing
ENV TINI_VERSION v0.18.0
ENV TINI_SIGN_KEY 595E85A6B1B4779EA4DAAEC70B588DFF0527A9B7
RUN set -eux;
wget -O /usr/local/bin/tini "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini" ;
wget -O /usr/local/bin/tini.asc "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini.asc" ;
export GNUPGHOME= "$(mktemp -d)" ;
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$TINI_SIGN_KEY" ;
gpg --batch --verify /usr/local/bin/tini.asc /usr/local/bin/tini;
command -v gpgconf && gpgconf --kill all || :;
rm -r "$GNUPGHOME" /usr/local/bin/tini.asc;
chmod +x /usr/local/bin/tini;
tini --version
นี่เป็นที่เดียวที่ประสบการณ์กลายเป็นเอกสารสำคัญสำหรับเส้นทางสู่การตรัสรู้ แต่เคล็ดลับต่อไปนี้อาจช่วยได้:
หลีกเลี่ยง COPY
/ ADD
ทุกครั้งที่เป็นไปได้ แต่เมื่อจำเป็น ให้ระบุให้เฉพาะเจาะจงที่สุดเท่าที่จะทำได้ (เช่น COPY one-file.sh /somewhere/
แทน COPY . /somewhere
)
เหตุผลก็คือแคชสำหรับคำสั่ง COPY
ถือว่าการเปลี่ยนแปลง mtime
ของไฟล์เป็นแคชที่หยุดทำงาน ซึ่งอาจทำให้ลักษณะการทำงานของแคชของ COPY
ไม่สามารถคาดเดาได้ในบางครั้ง โดยเฉพาะอย่างยิ่งเมื่อ .git
เป็นส่วนหนึ่งของสิ่งที่จำเป็นต้องมี COPY
ed (ตัวอย่าง)
ตรวจสอบให้แน่ใจว่าบรรทัดที่มีโอกาสน้อยที่จะเปลี่ยนแปลงมาก่อนบรรทัดที่มีแนวโน้มว่าจะเปลี่ยนแปลงมากกว่า (โดยมีข้อแม้ที่แต่ละบรรทัดควรสร้างภาพที่ยังคงทำงานได้สำเร็จโดยไม่ต้องสันนิษฐานว่าเป็นบรรทัดต่อๆ ไป)
ตัวอย่างเช่น บรรทัดที่มีหมายเลขเวอร์ชันซอฟต์แวร์ ( ENV MYSOFTWARE_VERSION 4.2
) ควรอยู่หลังบรรทัดที่ตั้งค่าไฟล์ .list
ที่เก็บ APT ( RUN echo 'deb http://example.com/mysoftware/debian some-suite main' > /etc/apt/sources.list.d/mysoftware.list
)
ควรเขียน Dockerfile
เพื่อช่วยลดการโจมตีแบบสกัดกั้นระหว่างการสร้าง ข้อกำหนดของเรามุ่งเน้นไปที่วัตถุประสงค์หลักสามประการ: การตรวจสอบแหล่งที่มา การตรวจสอบผู้เขียน และการตรวจสอบเนื้อหา สิ่งเหล่านี้สำเร็จตามลำดับโดยทำดังนี้: ใช้ https เมื่อเป็นไปได้; การนำเข้าคีย์ PGP ด้วยลายนิ้วมือแบบเต็มใน Dockerfile
เพื่อตรวจสอบลายเซ็น การฝังเช็คซัมโดยตรงใน Dockerfile
ควรใช้ทั้งสามอย่างเมื่อเป็นไปได้ คุณสามารถใช้ https และเช็คซัมแบบฝังได้เมื่อไม่มีการเผยแพร่ลายเซ็น ทางเลือกสุดท้าย สามารถใช้เช็คซัมแบบฝังได้หากไซต์ไม่มี https และไม่มีลายเซ็น
จุดประสงค์ในการแนะนำให้ใช้ https ในการดาวน์โหลดส่วนที่จำเป็นคือเพื่อให้แน่ใจว่าการดาวน์โหลดนั้นมาจากแหล่งที่เชื่อถือได้ ซึ่งจะทำให้การสกัดกั้นทำได้ยากขึ้นเช่นกัน
วัตถุประสงค์ในการแนะนำการตรวจสอบลายเซ็น PGP คือเพื่อให้แน่ใจว่ามีเพียงผู้ใช้ที่ได้รับอนุญาตเท่านั้นที่เผยแพร่อาร์ติแฟกต์ที่กำหนด เมื่อนำเข้าคีย์ PGP โปรดใช้บริการ keys.openpgp.org
เมื่อเป็นไปได้ (เลือกใช้ keyserver.ubuntu.com
เป็นอย่างอื่น) ดูเพิ่มเติมที่ส่วนคำถามที่พบบ่อยเกี่ยวกับกุญแจและการตรวจสอบ
วัตถุประสงค์ในการแนะนำการตรวจสอบความถูกต้องคือการตรวจสอบว่าอาร์ติแฟกต์เป็นไปตามที่คาดไว้ สิ่งนี้ทำให้แน่ใจได้ว่าเมื่อเนื้อหาระยะไกลเปลี่ยนแปลง Dockerfile ก็จะเปลี่ยนและจัดให้มีแคชแคช docker build
ตามธรรมชาติ นอกจากนี้ ยังช่วยป้องกันการดาวน์โหลดอาร์ติแฟกต์ที่ใหม่กว่าที่คาดไว้ในไฟล์ที่มีเวอร์ชันไม่ดีโดยไม่ตั้งใจอีกด้วย
ด้านล่างนี้เป็นตัวอย่างบางส่วน:
ที่ต้องการ : ดาวน์โหลดผ่าน https, การนำเข้าลายนิ้วมือแบบเต็มของคีย์ PGP และการตรวจสอบ asc
, ตรวจสอบผลรวมที่ฝังไว้
ENV PYTHON_DOWNLOAD_SHA512 (sha512-value-here)
RUN set -eux;
curl -fL "https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tar.xz" -o python.tar.xz;
curl -fL "https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tar.xz.asc" -o python.tar.xz.asc;
export GNUPGHOME= "$(mktemp -d)" ;
# gpg: key F73C700D: public key "Larry Hastings <[email protected]>" imported
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 97FC712E4C024BBEA48A61ED3A5CA953F73C700D;
gpg --batch --verify python.tar.xz.asc python.tar.xz;
rm -r "$GNUPGHOME" python.tar.xz.asc;
echo "$PYTHON_DOWNLOAD_SHA512 *python.tar.xz" | sha512sum --strict --check;
# install
ทางเลือก : นำเข้าลายนิ้วมือแบบเต็มคีย์ไปยัง apt ซึ่งจะตรวจสอบลายเซ็นและเช็คซัมเมื่อมีการดาวน์โหลดและติดตั้งแพ็คเกจ
RUN set -eux;
key= 'A4A9406876FCBD3C456770C88C718D3B5072E1F5' ;
export GNUPGHOME= "$(mktemp -d)" ;
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ;
gpg --batch --armor --export "$key" > /etc/apt/trusted.gpg.d/mysql.gpg.asc;
gpgconf --kill all;
rm -rf "$GNUPGHOME" ;
apt-key list > /dev/null
RUN set -eux;
echo "deb http://repo.mysql.com/apt/debian/ bookworm mysql-${MYSQL_MAJOR}" > /etc/apt/sources.list.d/mysql.list;
apt-get update;
apt-get install -y mysql-community-client= "${MYSQL_VERSION}" mysql-community-server-core= "${MYSQL_VERSION}" ;
rm -rf /var/lib/apt/lists/*;
# ...
(ตามหมายเหตุด้านข้าง rm -rf /var/lib/apt/lists/*
ตรงกันข้ามกับ apt-get update
โดยประมาณ - ช่วยให้มั่นใจได้ว่าเลเยอร์จะไม่รวมข้อมูลรายการแพ็คเกจ APT เพิ่มเติม ~ 8MB และ บังคับใช้การใช้งาน apt-get update
ที่เหมาะสม)
Less Secure Alternate : ฝังเช็คซัมลงใน Dockerfile
ENV RUBY_DOWNLOAD_SHA256 (sha256-value-here)
RUN set -eux;
curl -fL -o ruby.tar.gz "https://cache.ruby-lang.org/pub/ruby/$RUBY_MAJOR/ruby-$RUBY_VERSION.tar.gz" ;
echo "$RUBY_DOWNLOAD_SHA256 *ruby.tar.gz" | sha256sum --strict --check;
# install
หมายเหตุ: การใช้ SHA1 หรือ MD5 ควรถือเป็น "การตรวจสอบทางเลือกสุดท้าย" เนื่องจากโดยทั่วไปแล้วทั้งสองอย่างถือว่าไม่ปลอดภัย:
ยอมรับไม่ได้ : ดาวน์โหลดไฟล์ผ่าน http โดยไม่มีการยืนยัน
RUN curl -fL "https://julialang.s3.amazonaws.com/bin/linux/x64/${JULIA_VERSION%[.-]*}/julia-${JULIA_VERSION}-linux-x86_64.tar.gz" | tar ...
# install
ตามค่าเริ่มต้น คอนเทนเนอร์ Docker จะถูกดำเนินการโดยมีสิทธิ์ลดลง: ความสามารถของ Linux ที่อนุญาตพิเศษ กลุ่มควบคุม และโปรไฟล์ Seccomp เริ่มต้น (1.10+ พร้อมการรองรับโฮสต์) ซอฟต์แวร์ที่ทำงานในคอนเทนเนอร์อาจต้องการสิทธิ์เพิ่มเติมเพื่อให้ทำงานได้อย่างถูกต้อง และมีตัวเลือกบรรทัดคำสั่งมากมายในการปรับแต่งการทำงานของคอนเทนเนอร์ ดูการอ้างอิง docker run
และ Seccomp สำหรับนักเทียบท่าสำหรับการอ้างอิง
พื้นที่เก็บข้อมูลอย่างเป็นทางการที่ต้องการสิทธิ์เพิ่มเติมควรระบุชุดตัวเลือกบรรทัดคำสั่งขั้นต่ำเพื่อให้ซอฟต์แวร์ทำงานได้ และอาจถูกปฏิเสธหากสิ่งนี้ทำให้เกิดปัญหาด้านการพกพาหรือความปลอดภัยที่สำคัญ โดยทั่วไป ไม่อนุญาตให้ใช้ --privileged
แต่อาจยอมรับตัวเลือก --cap-add
และ --device
ร่วมกันได้ นอกจากนี้ --volume
อาจยุ่งยากเนื่องจากมีตำแหน่งของระบบไฟล์โฮสต์หลายแห่งที่แนะนำปัญหาด้านการพกพา/ความปลอดภัย (เช่น ซ็อกเก็ต X11)
สำหรับการอัปเดตรูปภาพที่ถือเป็นการแก้ไขด้านความปลอดภัย มีบางสิ่งที่เราแนะนำเพื่อช่วยให้แน่ใจว่าการอัปเดตของคุณจะถูกผสาน สร้าง และเผยแพร่โดยเร็วที่สุด:
[email protected]
ล่วงหน้าสองสามวัน (ธุรกิจ) เพื่อแจ้งข้อมูลล่วงหน้าและประมาณการเวลา (เพื่อให้เราสามารถกำหนดเวลาสำหรับการอัปเดตที่เข้ามาได้อย่างเหมาะสม)[security]
ไว้ในชื่อเรื่องของคำขอดึงของคุณ (เช่น [security] Update FooBar to 1.2.5, 1.3.7, 2.0.1
) แต่ละ repo สามารถระบุสถาปัตยกรรมได้หลายแบบสำหรับแท็กใด ๆ และทั้งหมด หากไม่มีการระบุสถาปัตยกรรม อิมเมจจะถูกสร้างขึ้นใน Linux บน amd64
(หรือที่เรียกว่า x86-64) หากต้องการระบุสถาปัตยกรรมเพิ่มเติมหรือแตกต่างกัน ให้ใช้ฟิลด์ Architectures
(รายการที่คั่นด้วยเครื่องหมายจุลภาค ช่องว่างจะถูกตัดออก) สถาปัตยกรรมที่ถูกต้องมีอยู่ในไฟล์ oci-platform.go
ของ Bashbrew:
amd64
arm32v6
arm32v7
arm64v8
i386
mips64le
ppc64le
riscv64
s390x
windows-amd64
Architectures
ของแท็กใดๆ จะต้องเป็นส่วนย่อยที่เข้มงวดของ Architectures
ของแท็กที่เป็น FROM
รูปภาพต้องมี Dockerfile
เดียวต่อรายการในไฟล์ไลบรารีที่สามารถใช้ได้กับหลายสถาปัตยกรรม ซึ่งหมายความว่าแต่ละสถาปัตยกรรมที่รองรับจะมีบรรทัด FROM
เหมือนกัน (เช่น FROM debian:bookworm
) ดู golang
, docker
, haproxy
และ php
สำหรับตัวอย่างไฟล์ไลบรารีที่ใช้หนึ่ง Dockerfile
ต่อรายการ และดู repos git ที่เกี่ยวข้อง เช่น Dockerfile
s
หากส่วนต่างๆ ของ Dockerfile เกิดขึ้นในสถาปัตยกรรมเดียวหรืออีกสถาปัตยกรรมหนึ่ง ให้ใช้โฟลว์การควบคุม (เช่น if
/ case
) ร่วมกับ dpkg --print-architecture
หรือ apk -print-arch
เพื่อตรวจจับสถาปัตยกรรม userspace ใช้ uname
สำหรับการตรวจจับสถาปัตยกรรมเมื่อไม่สามารถติดตั้งเครื่องมือที่แม่นยำกว่านี้ได้เท่านั้น ดู golang สำหรับตัวอย่างที่สถาปัตยกรรมบางตัวต้องการการสร้างไบนารีจากแพ็คเกจต้นทางอัปสตรีม และบางตัวเพียงดาวน์โหลดไบนารี่รีลีสเท่านั้น
สำหรับอิมเมจพื้นฐาน เช่น debian
จำเป็นต้องมี Dockerfile
อื่นและสร้างบริบทเพื่อ ADD
ไบนารีเฉพาะของสถาปัตยกรรม และนี่คือข้อยกเว้นที่ถูกต้องสำหรับข้างต้น เนื่องจากรูปภาพเหล่านี้ใช้ Tags
เดียวกัน จึงจำเป็นต้องอยู่ในรายการเดียวกัน ใช้ฟิลด์เฉพาะสถาปัตยกรรมสำหรับ GitRepo
, GitFetch
, GitCommit
และ Directory
ซึ่งเป็นสถาปัตยกรรมที่ต่อกันด้วยยัติภังค์ ( -
) และฟิลด์ (เช่น arm32v7-GitCommit
) สถาปัตยกรรมใดๆ ที่ไม่มีฟิลด์เฉพาะสถาปัตยกรรมจะใช้ฟิลด์เริ่มต้น (เช่น ไม่มี arm32v7-Directory
หมายความว่า Directory
จะถูกใช้สำหรับ arm32v7
) ดูตัวอย่างไฟล์ debian
หรือ ubuntu
ในไลบรารี ต่อไปนี้เป็นตัวอย่างสำหรับ hello-world
:
Maintainers: Tianon Gravi <[email protected]> (@tianon),
Joseph Ferguson <[email protected]> (@yosifkit)
GitRepo: https://github.com/docker-library/hello-world.git
GitCommit: 7d0ee592e4ed60e2da9d59331e16ecdcadc1ed87
Tags: latest
Architectures: amd64, arm32v5, arm32v7, arm64v8, ppc64le, s390x
# all the same commit; easy for us to generate this way since they could be different
amd64-GitCommit: 7d0ee592e4ed60e2da9d59331e16ecdcadc1ed87
amd64-Directory: amd64/hello-world
arm32v5-GitCommit: 7d0ee592e4ed60e2da9d59331e16ecdcadc1ed87
arm32v5-Directory: arm32v5/hello-world
arm32v7-GitCommit: 7d0ee592e4ed60e2da9d59331e16ecdcadc1ed87
arm32v7-Directory: arm32v7/hello-world
arm64v8-GitCommit: 7d0ee592e4ed60e2da9d59331e16ecdcadc1ed87
arm64v8-Directory: arm64v8/hello-world
ppc64le-GitCommit: 7d0ee592e4ed60e2da9d59331e16ecdcadc1ed87
ppc64le-Directory: ppc64le/hello-world
s390x-GitCommit: 7d0ee592e4ed60e2da9d59331e16ecdcadc1ed87
s390x-Directory: s390x/hello-world
Tags: nanoserver
Architectures: windows-amd64
# if there is only one architecture, you can use the unprefixed fields
Directory: amd64/hello-world/nanoserver
# or use the prefixed versions
windows-amd64-GitCommit: 7d0ee592e4ed60e2da9d59331e16ecdcadc1ed87
Constraints: nanoserver
ดูส่วนรูปแบบคำแนะนำสำหรับข้อมูลเพิ่มเติมเกี่ยวกับรูปแบบของไฟล์ไลบรารี
การเสนอภาพลักษณ์อย่างเป็นทางการใหม่ไม่ควรกระทำอย่างไม่ใส่ใจ เราคาดหวังและจำเป็นต้องมีความมุ่งมั่นในการรักษาภาพลักษณ์ของคุณ (รวมถึงและโดยเฉพาะอย่างยิ่งการอัปเดตที่ทันเวลาตามความเหมาะสมตามที่ระบุไว้ข้างต้น)
ไฟล์คำจำกัดความของไลบรารีคือไฟล์ข้อความธรรมดาที่พบใน library/
ไดเร็กทอรีของที่เก็บ official-images
ไฟล์ไลบรารีแต่ละไฟล์จะควบคุมชุดแท็กรูปภาพที่ "รองรับ" ปัจจุบันซึ่งปรากฏบนคำอธิบาย Docker Hub แท็กที่ถูกลบออกจากไฟล์ไลบรารีจะไม่ถูกลบออกจาก Docker Hub เพื่อให้เวอร์ชันเก่าสามารถใช้งานได้ต่อไป แต่ไม่ได้รับการดูแลโดยอัพสตรีมหรือผู้ดูแลอิมเมจอย่างเป็นทางการ แท็กในไฟล์ไลบรารีถูกสร้างขึ้นผ่านการอัปเดตไฟล์ไลบรารีนั้นเท่านั้น หรือเป็นผลมาจากการอัปเดตอิมเมจพื้นฐาน (เช่น รูปภาพ FROM debian:bookworm
จะถูกสร้างขึ้นใหม่เมื่อมีการสร้าง debian:bookworm
) เฉพาะสิ่งที่อยู่ในไฟล์ไลบรารีเท่านั้นที่จะถูกสร้างขึ้นใหม่เมื่อฐานมีการอัพเดต
ด้วยนโยบายนี้ จึงควรชี้แจงบางกรณี: เวอร์ชันทดแทน ผู้สมัครที่เผยแพร่ และบิวด์การผสานรวมอย่างต่อเนื่อง เมื่อมีการเสนอพื้นที่เก็บข้อมูลใหม่ เป็นเรื่องปกติที่จะรวมเวอร์ชันเก่าที่ไม่รองรับบางเวอร์ชันไว้ในคำขอดึงเริ่มต้นพร้อมกับข้อตกลงเพื่อลบออกทันทีหลังจากการยอมรับ อย่าสับสนกับเอกสารสำคัญทางประวัติศาสตร์ที่ครอบคลุมซึ่งไม่ได้มีเจตนา อีกกรณีทั่วไปที่คำว่า "สนับสนุน" ถูกขยายออกไปเล็กน้อยคือกับผู้สมัครที่เผยแพร่ จริงๆ แล้วผู้สมัครที่เผยแพร่เป็นเพียงแบบแผนการตั้งชื่อสำหรับสิ่งที่คาดว่าจะเป็นรุ่นที่อายุสั้นกว่า ดังนั้นจึงเป็นที่ยอมรับและสนับสนุนอย่างเต็มที่ ซึ่งแตกต่างจากตัวเลือกการเปิดตัว การสร้างการผสานรวมอย่างต่อเนื่องซึ่งมีวงจรการเปิดตัวแบบอัตโนมัติโดยสมบูรณ์ตามการคอมมิตโค้ดหรือกำหนดการปกตินั้นไม่เหมาะสม
ขอแนะนำอย่างยิ่งให้คุณเรียกดูเนื้อหา library/
ไฟล์ที่มีอยู่ (และประวัติเพื่อดูว่ามีการเปลี่ยนแปลงอย่างไรเมื่อเวลาผ่านไป) ก่อนที่จะสร้างเนื้อหาใหม่เพื่อทำความคุ้นเคยกับแบบแผนที่มีอยู่ และช่วยปรับปรุงกระบวนการตรวจสอบเพิ่มเติม (เช่น ที่เราสามารถมุ่งเน้นไปที่เนื้อหาแทนการจัดรูปแบบที่ลึกลับหรือการใช้แท็ก/การตั้งชื่อ)
ชื่อไฟล์ของไฟล์คำจำกัดความจะกำหนดชื่อของที่เก็บรูปภาพที่สร้างบน Docker Hub ตัวอย่างเช่น ไฟล์ library/ubuntu
จะสร้างแท็กในพื้นที่เก็บข้อมูล ubuntu
แท็กของที่เก็บควรสะท้อนถึงเวอร์ชันหรือรูปแบบของอัปสตรีม ตัวอย่างเช่น Ubuntu 14.04 มีชื่อเรียกอีกอย่างว่า Ubuntu Trusty Tahr แต่บ่อยครั้งเป็นเพียง Ubuntu Trusty (โดยเฉพาะในการใช้งาน) ดังนั้น ubuntu:14.04
(หมายเลขเวอร์ชัน) และ ubuntu:trusty
(ชื่อเวอร์ชัน) จึงเป็นนามแฝงที่เหมาะสมสำหรับเนื้อหารูปภาพเดียวกัน ใน Docker แท็ก latest
เป็นกรณีพิเศษ แต่เป็นชื่อเรียกที่ผิดเล็กน้อย latest
คือแท็ก "เริ่มต้น" จริงๆ เมื่อนัก docker run xyz
นักเทียบท่าตีความว่าหมายถึง docker run xyz:latest
เนื่องจากพื้นหลังดังกล่าว จึงไม่มีแท็กอื่นใดที่มีสตริง latest
เนื่องจากไม่ใช่สิ่งที่ผู้ใช้คาดหวังหรือสนับสนุนให้พิมพ์ออกมาจริงๆ (เช่น xyz:latest
ควรใช้เป็นเพียง xyz
) กล่าวอีกนัยหนึ่ง การมีนามแฝงสำหรับ "XYZ รุ่น 2.2 ที่สูงที่สุด" ควรเป็น xyz:2.2
ไม่ใช่ xyz:2.2-latest
ในทำนองเดียวกัน หากมีตัวแปร Alpine ของ xyz:latest
ก็ควรมีนามแฝงว่า xyz:alpine
ไม่ใช่ xyz:alpine-latest
หรือ xyz:latest-alpine
ขอแนะนำอย่างยิ่งให้ระบุแท็กหมายเลขเวอร์ชัน ซึ่งจะทำให้ผู้ใช้สามารถคงอยู่ในซีรีส์ "ล่าสุด" ที่เผยแพร่โดยเฉพาะได้ ตัวอย่างเช่น เนื่องจากซอฟต์แวร์ XYZ เวอร์ชัน 2.3.7 และ 2.2.4 ที่รองรับในปัจจุบัน นามแฝงที่แนะนำคือ Tags: 2.3.7, 2.3, 2, latest
และ Tags: 2.2.4, 2.2
ตามลำดับ ในตัวอย่างนี้ ผู้ใช้สามารถใช้ xyz:2.2
เพื่อใช้แพตช์ล่าสุดของซีรีส์ 2.2 ได้อย่างง่ายดาย หรือ xyz:2
หากต้องการรายละเอียดที่น้อยลง (Python เป็นตัวอย่างที่ดีของส่วนที่มีประโยชน์อย่างเห็นได้ชัดที่สุด -- python:2
และ python:3
นั้นแตกต่างกันมาก และถือเป็นแท็ก latest
สำหรับเพลงที่เผยแพร่หลัก ๆ ของ Python แต่ละเพลง)
ตามที่อธิบายไว้ข้างต้น latest
ถือเป็น "ค่าเริ่มต้น" จริงๆ ดังนั้นรูปภาพที่ใช้เป็นนามแฝงควรสะท้อนถึงเวอร์ชันหรือรูปแบบต่างๆ ของซอฟต์แวร์ที่ผู้ใช้ควรใช้ หากพวกเขาไม่ทราบหรือไม่สนใจเวอร์ชันที่พวกเขาใช้ การใช้ Ubuntu เป็นตัวอย่าง ubuntu:latest
ชี้ไปที่ LTS ล่าสุด เนื่องจากเป็นสิ่งที่ผู้ใช้ส่วนใหญ่ควรใช้หากพวกเขารู้ว่าพวกเขาต้องการ Ubuntu แต่ไม่ทราบหรือสนใจเวอร์ชันใด (โดยเฉพาะอย่างยิ่งเมื่อพิจารณาว่าจะเป็น รุ่น "เสถียร" และได้รับการสนับสนุนอย่างดีที่สุดในช่วงเวลาใดก็ตาม)
รูปแบบไฟล์รายการนั้นอิงอย่างเป็นทางการตาม RFC 2822 และด้วยเหตุนี้จึงควรเป็นที่คุ้นเคยสำหรับผู้ที่คุ้นเคยกับ "ส่วนหัว" ของโปรโตคอล/รูปแบบอินเทอร์เน็ตยอดนิยมมากมาย เช่น HTTP หรืออีเมล
ส่วนเพิ่มเติมหลักได้รับแรงบันดาลใจจากวิธีที่ Debian ใช้โดยทั่วไปคือ 2822 กล่าวคือ บรรทัดที่ขึ้นต้นด้วย #
จะถูกละเว้น และ "รายการ" จะถูกคั่นด้วยบรรทัดว่าง
รายการแรกคือข้อมูลเมตา "ทั่วโลก" สำหรับรูปภาพ ฟิลด์ที่จำเป็นเพียงรายการเดียวในรายการโกลบอลคือ Maintainers
ซึ่งค่าจะคั่นด้วยเครื่องหมายจุลภาคในรูปแบบของ Name <email> (@github)
หรือ Name (@github)
ฟิลด์ใดๆ ที่ระบุในรายการส่วนกลางจะเป็นค่าเริ่มต้นสำหรับรายการที่เหลือและสามารถแทนที่ได้ในแต่ละรายการ
# this is a comment and will be ignored
Maintainers: John Smith <[email protected]> (@example-jsmith),
Anne Smith <[email protected]> (@example-asmith)
GitRepo: https://github.com/example/docker-example.git
GitCommit: deadbeefdeadbeefdeadbeefdeadbeefdeadbeef
# this is also a comment, and will also be ignored
Tags: 1.2.3, 1.2, 1, latest
Directory: 1
Tags: 2.0-rc1, 2.0-rc, 2-rc, rc
GitRepo: https://github.com/example/docker-example-rc.git
GitFetch: refs/heads/2.0-pre-release
GitCommit: beefdeadbeefdeadbeefdeadbeefdeadbeefdead
Directory: 2
File: Dockerfile-to-use
Bashbrew จะดึงโค้ดออกจากที่เก็บ Git ( GitRepo
) ที่คอมมิตที่ระบุ ( GitCommit
) หากการคอมมิตที่อ้างอิงไม่พร้อมใช้งานโดยการดึงข้อมูล master
ของ GitRepo
ที่เกี่ยวข้อง จำเป็นต้องระบุค่าสำหรับ GitFetch
เพื่อบอก Bashbrew ว่าการอ้างอิงอะไรที่จะดึงข้อมูล เพื่อให้ได้การคอมมิตที่จำเป็น
รูปภาพที่สร้างขึ้นจะถูกแท็กเป็น <manifest-filename>:<tag>
(เช่น library/golang
ที่มีค่า Tags
1.6, 1, latest
จะสร้างแท็กของ golang:1.6
, golang:1
และ golang:latest
)
อีกทางเลือกหนึ่ง หากมี Directory
อยู่ Bashbrew จะค้นหา Dockerfile
ภายในไดเร็กทอรีย่อยที่ระบุแทนที่จะเป็นที่รูท (และ Directory
จะถูกใช้เป็น "บริบท" สำหรับบิลด์แทนระดับบนสุดของที่เก็บ) หากมี File
อยู่ ระบบจะใช้ชื่อไฟล์ที่ระบุแทน Dockerfile
ดูส่วน multi-arch สำหรับรายละเอียดเกี่ยวกับวิธีระบุ GitRepo
, GitFetch
, GitCommit
หรือ Directory
ที่แตกต่างกันสำหรับสถาปัตยกรรมเฉพาะ
library/
โฟลเดอร์ ชื่อของมันจะเป็นชื่อของพื้นที่เก็บข้อมูลของคุณบนฮับ Bashbrew ( bashbrew
) เป็นเครื่องมือสำหรับการโคลน การสร้าง การแท็ก และการผลักดันอิมเมจอย่างเป็นทางการของ Docker ดู Bashbrew README
สำหรับข้อมูลเพิ่มเติม