ความแตกต่างระหว่าง RUN และ CMD ใน Dockerfile


294

ฉันสับสนเกี่ยวกับเมื่อฉันควรใช้VSCMD RUNตัวอย่างเช่นในการรันคำสั่ง bash / shell (เช่นls -la) ฉันมักจะใช้CMDหรือมีสถานการณ์ที่ฉันจะใช้RUNหรือไม่? พยายามทำความเข้าใจแนวปฏิบัติที่ดีที่สุดเกี่ยวกับDockerfileคำสั่งที่คล้ายกันสองประการนี้


คำตอบ:


426

RUNเป็นขั้นตอนการสร้างอิมเมจสถานะของคอนเทนเนอร์หลังจากRUNคำสั่งจะถูกส่งไปยังอิมเมจคอนเทนเนอร์ Dockerfile สามารถมีหลายRUNขั้นตอนที่เลเยอร์อยู่ด้านบนของอีกขั้นเพื่อสร้างอิมเมจ

CMDเป็นคำสั่งที่คอนเทนเนอร์ดำเนินการตามค่าเริ่มต้นเมื่อคุณเรียกใช้อิมเมจที่สร้างขึ้น Dockerfile จะใช้เฉพาะการCMDกำหนดขั้นสุดท้ายเท่านั้น สามารถแทนที่เมื่อเริ่มต้นภาชนะด้วยCMDdocker run $image $other_command

รายการยังเกี่ยวข้องอย่างใกล้ชิดCMDและสามารถปรับเปลี่ยนวิธีที่ภาชนะเริ่มต้นภาพ


15
คุณทำทุกอย่างที่RUNจำเป็นในการตั้งค่าสภาพแวดล้อมของคุณและ CMD ของคุณ (เท่านั้น) เปิดตัวกระบวนการทำงานในภาชนะของคุณตัวอย่างเช่นสำหรับ nginx แยกจากgithub.com/nginxinc/docker-nginx/blob/ …คุณเห็นบรรทัดCMD ["nginx", "-g", "daemon off;"]
user2915097

"Dockerfile สามารถมีหนึ่ง CMD ได้เท่านั้น" - ไม่ใช่ความจริงทางเทคนิค แต่มีประสิทธิภาพทั้งหมด แต่จะถูกละเว้น ดูคำตอบของ GingerBeer
Colm Bhandal

"Dockerfile จะใช้เฉพาะ CMD สุดท้ายที่กำหนด" จริงๆแล้ว CMD สุดท้ายที่กำหนดไว้จะถูกใช้ในการเปิดภาพเป็นคอนเทนเนอร์ใช่ไหม?
paul cheung

1
ใช่ @paulcheung คำสั่งสุดท้ายใน dockerfile จะถูกเขียนไปยังอิมเมจและเป็นคำสั่งที่คอนเทนเนอร์จะดำเนินการตามค่าเริ่มต้นเมื่อคุณเรียกใช้อิมเมจที่สร้างขึ้น
แมตต์

126

RUN - ทริกเกอร์คำสั่งในขณะที่เราสร้างภาพนักเทียบท่า

CMD - ทริกเกอร์คำสั่งในขณะที่เราเปิดภาพนักเทียบท่าที่สร้างขึ้น


67

ฉันพบนี้บทความที่เป็นประโยชน์มากที่จะเข้าใจความแตกต่างระหว่างพวกเขา:

RUN - คำสั่ง RUN อนุญาตให้คุณติดตั้งแอปพลิเคชันและแพ็คเกจที่จำเป็นสำหรับมัน มันรันคำสั่งใด ๆ ที่ด้านบนของภาพปัจจุบันและสร้างเลเยอร์ใหม่โดยยอมรับผล บ่อยครั้งที่คุณจะพบคำสั่ง RUN หลายคำสั่งใน Dockerfile

CMD - คำสั่ง CMD ช่วยให้คุณสามารถตั้งค่าคำสั่งเริ่มต้นซึ่งจะดำเนินการเฉพาะเมื่อคุณเรียกใช้คอนเทนเนอร์โดยไม่ระบุคำสั่ง หากคอนเทนเนอร์ Docker รันด้วยคำสั่งคำสั่งเริ่มต้นจะถูกละเว้น หาก Dockerfile มีคำสั่ง CMD มากกว่าหนึ่งคำสั่งทั้งหมด แต่
คำสั่ง CMD สุดท้ายจะถูกละเว้น


13

RUN - ติดตั้ง Python ตอนนี้คอนเทนเนอร์ของคุณมี python ที่เขียนลงในรูปภาพแล้ว
CMD - python hello.py เรียกใช้สคริปต์ที่คุณชื่นชอบ


CMD - ติดตั้ง Python แล้วตอนนี้คอนเทนเนอร์ของฉันไม่เร่งการทำงานของหลามในรูปหรือไม่
Carlos Fontes

RUN จะสร้างเลเยอร์รูปภาพของ python โดย CMD จะรันคำสั่งที่ไม่ได้สร้างอิมเมจ
Rohit Salecha

8

คำสั่ง RUN: โดยทั่วไปคำสั่ง RUN จะดำเนินการตามคำสั่งเริ่มต้นเมื่อเราสร้างภาพ นอกจากนี้ยังจะทำการเปลี่ยนแปลงรูปภาพในขั้นตอนต่อไป

อาจมีคำสั่ง RUN มากกว่า 1 คำสั่งเพื่อช่วยในการสร้างภาพใหม่

คำสั่ง CMD: คำสั่ง CMD จะตั้งค่าคำสั่งเริ่มต้นสำหรับคอนเทนเนอร์ใหม่ สิ่งนี้จะไม่ถูกดำเนินการในเวลาที่สร้าง

หากไฟล์นักเทียบท่ามีคำสั่งมากกว่า 1 CMD คำสั่งทั้งหมดจะถูกละเว้นยกเว้นคำสั่งสุดท้าย เนื่องจากคำสั่งนี้จะไม่ดำเนินการใด ๆ แต่เพียงตั้งค่าคำสั่งเริ่มต้น


6

หมายเหตุ: อย่าสับสน RUN ด้วย CMD RUN เรียกใช้คำสั่งและยอมรับผลลัพธ์ CMD ไม่ได้ดำเนินการอะไรในเวลาที่สร้าง แต่ระบุคำสั่งที่ตั้งใจไว้สำหรับภาพ

จากการอ้างอิงไฟล์นักเทียบท่า

https://docs.docker.com/engine/reference/builder/#cmd


4

RUN : มีได้มากมายและใช้ในกระบวนการสร้างเช่นติดตั้งหลายไลบรารี

CMD : สามารถมีเพียง 1 ซึ่งเป็นของคุณรันจุดเริ่มต้น (เช่น["npm", "start"], ["node", "app.js"])


2

มีการตอบเพียงพอในRUNและCMD ผมแค่อยากจะเพิ่มคำไม่กี่คำบนจุดเข้าใช้งาน อาร์กิวเมนต์CMDสามารถเขียนทับได้โดยอาร์กิวเมนต์บรรทัดคำสั่งในขณะที่อาร์กิวเมนต์ENTRYPOINTจะใช้เสมอ

บทความนี้เป็นแหล่งข้อมูลที่ดี


2

คำตอบที่มีอยู่ครอบคลุมส่วนใหญ่ของสิ่งที่ทุกคนต้องการดูคำถามนี้ ดังนั้นฉันจะครอบคลุมบางพื้นที่สำหรับ CMD และ RUN

CMD: ซ้ำกันได้รับอนุญาต แต่สิ้นเปลือง

GingerBeer ให้ความสำคัญ: คุณจะไม่ได้รับข้อผิดพลาดใด ๆ หากคุณใส่ CMD มากกว่าหนึ่งรายการ - แต่การทำเช่นนั้นเป็นการสิ้นเปลือง ฉันต้องการทำอย่างละเอียดด้วยตัวอย่าง:

FROM busybox
CMD echo "Executing CMD"
CMD echo "Executing CMD 2"

หากคุณสร้างสิ่งนี้ลงในภาพและเรียกใช้คอนเทนเนอร์ในภาพนี้จากนั้นเมื่อ GingerBeer ระบุเฉพาะ CMD ล่าสุดเท่านั้นที่จะได้รับการเอาใจใส่ ดังนั้นผลลัพธ์ของคอนเทนเนอร์นั้นจะเป็น:

กำลังดำเนินการ CMD 2

วิธีที่ฉันคิดคือ "CMD" ตั้งค่าตัวแปรส่วนกลางเดียวสำหรับรูปภาพทั้งหมดที่กำลังสร้างอยู่ดังนั้นคำสั่ง "CMD" ที่ต่อเนื่องจะเขียนทับตัวแปรใด ๆ ที่เขียนไปยังตัวแปรโกลบอลก่อนหน้านี้และในภาพสุดท้ายที่สร้างขึ้น คนสุดท้ายที่จะเขียนชนะ เนื่องจาก Dockerfile ดำเนินการตามลำดับจากบนลงล่างเรารู้ว่า CMD ที่อยู่ล่างสุดคืออันที่ได้รับ "เขียน" ขั้นสุดท้ายนี้ (พูดเชิงเปรียบเทียบ)

RUN: คำสั่งอาจไม่ทำงานถ้ารูปภาพถูกแคช

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

FROM busybox
RUN echo "Just echo while you work"

ครั้งแรกที่คุณเรียกใช้คุณจะได้รับผลลัพธ์เช่นนี้พร้อมด้วยตัวอักษรและตัวเลขที่แตกต่างกัน:

docker build -t example/run-echo .
Sending build context to Docker daemon  9.216kB
Step 1/2 : FROM busybox
 ---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
 ---> Running in ed37d558c505
Just echo while you work
Removing intermediate container ed37d558c505
 ---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest

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

docker build -t example/run-echo .
Sending build context to Docker daemon  9.216kB
Step 1/2 : FROM busybox
 ---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
 ---> Using cache
 ---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.