Sự khác biệt giữa RUN và CMD trong Dockerfile


293

Tôi đang bối rối về việc khi nào tôi nên sử dụng CMDvs RUN. Ví dụ, để thực thi các lệnh bash / shell (tức là ls -la) tôi sẽ luôn sử dụng CMDhoặc có tình huống nào tôi sẽ sử dụng RUNkhông? Cố gắng để hiểu các thực tiễn tốt nhất về hai Dockerfilechỉ thị tương tự .


Câu trả lời:


425

RUN là một bước xây dựng hình ảnh, trạng thái của container sau khi một RUNlệnh sẽ được cam kết với hình ảnh container. Dockerfile có thể có nhiều RUNbước lớp chồng lên nhau để xây dựng hình ảnh.

CMD là lệnh mà container thực thi theo mặc định khi bạn khởi chạy hình ảnh được xây dựng. Dockerfile sẽ chỉ sử dụng CMDđịnh nghĩa cuối cùng . Có CMDthể được ghi đè khi bắt đầu một container với docker run $image $other_command.

ENTRYPOINT cũng liên quan chặt chẽ CMDvà có thể sửa đổi cách thức một container bắt đầu một hình ảnh.


15
bạn làm tất cả những gì RUNcần thiết để thiết lập môi trường của mình và CMD (chỉ) của bạn khởi chạy quy trình đang chạy trong thùng chứa của bạn, ví dụ, đối với nginx, trích xuất từ github.com/nginxinc/docker-nginx/blob/ tựa bạn thấy dòngCMD ["nginx", "-g", "daemon off;"]
user2915097

"Dockerfile chỉ có thể có một CMD" - không đúng về mặt kỹ thuật, nhưng thực tế tất cả trừ một cái sẽ bị bỏ qua. Xem câu trả lời của GingerBeer.
Colm Bhandal

"Dockerfile sẽ chỉ sử dụng CMD cuối cùng được xác định"? Trên thực tế, CMD cuối cùng được xác định sẽ được sử dụng để khởi chạy hình ảnh dưới dạng một thùng chứa, phải không?
paul cheung

1
Có @paulcheung lệnh cuối cùng trong dockerfile được ghi vào hình ảnh và là lệnh mà container thực thi theo mặc định khi bạn khởi chạy hình ảnh được xây dựng.
Matt

126

RUN - kích hoạt lệnh trong khi chúng tôi xây dựng hình ảnh docker.

CMD - kích hoạt lệnh trong khi chúng tôi khởi chạy hình ảnh docker đã tạo.


67

Tôi tìm thấy này bài viết rất hữu ích để hiểu sự khác biệt giữa chúng:

RUN - hướng dẫn RUN cho phép bạn cài đặt ứng dụng và các gói cần thiết cho nó của bạn. Nó thực thi bất kỳ lệnh nào trên đầu ảnh hiện tại và tạo một lớp mới bằng cách cam kết kết quả. Thường thì bạn sẽ tìm thấy nhiều hướng dẫn RUN trong Dockerfile.

CMD - Lệnh CMD cho phép bạn đặt lệnh mặc định, lệnh này sẽ chỉ được thực thi khi bạn chạy container mà không chỉ định lệnh. Nếu Docker container chạy với một lệnh, lệnh mặc định sẽ bị bỏ qua. Nếu Dockerfile có nhiều hơn một lệnh CMD, thì tất cả trừ các
lệnh CMD cuối cùng đều bị bỏ qua.


13

CHẠY - Cài đặt Python, bộ chứa của bạn hiện có python bị cháy vào hình ảnh của nó
CMD - python hello.py, chạy tập lệnh yêu thích của bạn


CMD - Cài đặt Python, container của tôi bây giờ không làm trăn bị cháy thành hình ảnh của nó?
Carlos Fontes

RUN sẽ tạo một lớp hình ảnh của python, CMD sẽ thực hiện lệnh không tạo hình ảnh
Rohit Salecha

8

Lệnh RUN: Lệnh RUN về cơ bản, sẽ thực thi lệnh mặc định, khi chúng ta đang xây dựng hình ảnh. Nó cũng sẽ cam kết thay đổi hình ảnh cho bước tiếp theo.

Có thể có nhiều hơn 1 lệnh RUN, để hỗ trợ quá trình xây dựng hình ảnh mới.

Lệnh CMD: Các lệnh CMD sẽ chỉ đặt lệnh mặc định cho vùng chứa mới. Điều này sẽ không được thực hiện tại thời điểm xây dựng.

Nếu một tệp docker có nhiều hơn 1 lệnh CMD thì tất cả chúng đều bị bỏ qua ngoại trừ lệnh cuối cùng. Vì lệnh này sẽ không thực thi bất cứ điều gì mà chỉ đặt lệnh mặc định.



4

CHẠY : Có thể nhiều và được sử dụng trong quá trình xây dựng , ví dụ: cài đặt nhiều thư viện

CMD : Chỉ có thể có 1, đó là bạn thực hiện điểm bắt đầu (ví dụ ["npm", "start"], ["node", "app.js"])


2

Các câu trả lời hiện có bao gồm hầu hết những gì bất cứ ai nhìn vào câu hỏi này sẽ cần. Vì vậy, tôi sẽ chỉ bao gồm một số khu vực thích hợp cho CMD và RUN.

CMD: trùng lặp được phép nhưng lãng phí

GingerBeer đưa ra một điểm quan trọng: bạn sẽ không gặp phải bất kỳ lỗi nào nếu bạn đặt nhiều hơn một CMD - nhưng thật lãng phí khi làm như vậy. Tôi muốn giải thích với một ví dụ:

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

Nếu bạn xây dựng hình ảnh này thành một hình ảnh và chạy một thùng chứa trong hình ảnh này, thì như trạng thái của GingerBeer, chỉ có CMD cuối cùng sẽ được chú ý. Vì vậy, đầu ra của container đó sẽ là:

Đang thực hiện CMD 2

Theo cách tôi nghĩ, đó là "CMD" đang thiết lập một biến toàn cục duy nhất cho toàn bộ hình ảnh đang được xây dựng, vì vậy các câu lệnh "CMD" kế tiếp đơn giản ghi đè lên bất kỳ ghi nào trước đó vào biến toàn cục đó và trong hình ảnh cuối cùng được tạo cuối cùng để viết chiến thắng. Vì Dockerfile thực thi theo thứ tự từ trên xuống dưới, chúng tôi biết rằng hầu hết các CMD dưới cùng là cái được "ghi" cuối cùng này (nói một cách ẩn dụ).

CHẠY: Các lệnh có thể không thực thi nếu hình ảnh được lưu trong bộ nhớ cache

Một điểm tinh tế cần chú ý về RUN là nó được coi là một hàm thuần túy ngay cả khi có các tác dụng phụ, và do đó được lưu trữ. Điều này có nghĩa là nếu RUN có một số tác dụng phụ không làm thay đổi hình ảnh kết quả và hình ảnh đó đã được lưu vào bộ nhớ cache, thì RUN sẽ không được thực hiện lại và do đó các tác dụng phụ sẽ không xảy ra đối với các bản dựng tiếp theo. Ví dụ: lấy Dockerfile này:

FROM busybox
RUN echo "Just echo while you work"

Lần đầu tiên bạn chạy nó, bạn sẽ nhận được đầu ra như thế này, với các ID chữ và số khác nhau:

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

Lưu ý rằng câu lệnh echo đã được thực hiện ở trên. Lần thứ hai bạn chạy nó, nó sử dụng bộ đệm và bạn sẽ không thấy bất kỳ tiếng vang nào trong đầu ra của bản dựng:

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

1

Đã có đủ câu trả lời trên RUNCMD . Tôi chỉ muốn thêm một vài từ trên ENTRYPOINT . Các đối số CMD có thể được ghi đè bằng các đối số dòng lệnh, trong khi các đối số ENTRYPOINT luôn được sử dụng.

Bài viết này là một nguồn thông tin tốt.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.