Cú pháp JSON của CMD
(và RUN
và ENTRYPOINT
) vượt qua các đối số hạt nhân trực tiếp như một syscall exec. Không có sự tách biệt lệnh với các đối số bằng khoảng trắng, thoát dấu ngoặc kép, chuyển hướng IO, thay thế biến đổi, đường ống giữa các lệnh, chạy nhiều lệnh, v.v., trong tòa nhà thực thi. Tòa nhà chỉ có thể thực thi để chạy và liệt kê các đối số để truyền cho thực thi đó và nó chạy nó.
Các ký tự muốn $
mở rộng các biến, ;
tách các lệnh,
(dấu cách) để phân tách các đối số &&
và ||
để chuỗi lệnh, >
để chuyển hướng đầu ra, chuyển đổi |
giữa các lệnh, v.v., là tất cả các tính năng của trình bao và cần một cái gì đó giống như /bin/sh
hoặc /bin/bash
để diễn giải và thực hiện chúng.
Nếu bạn chuyển sang cú pháp chuỗi của CMD
, docker sẽ chạy lệnh của bạn bằng shell:
CMD /etc/init.d/nullmailer start ; /usr/sbin/php5-fpm
Mặt khác, cú pháp thứ hai của bạn thực hiện chính xác điều tương tự:
CMD ["sh", "-c", "/etc/init.d/nullmailer start ; /usr/sbin/php5-fpm"]
Lưu ý rằng tôi không khuyên bạn nên chạy nhiều lệnh theo cách này bên trong một container vì không có xử lý lỗi nếu lệnh đầu tiên của bạn không thành công, đặc biệt là nếu nó chạy trong nền. Bạn cũng để một lớp vỏ chạy dưới dạng 1 trong hộp chứa, điều này sẽ phá vỡ việc xử lý tín hiệu, dẫn đến độ trễ 10 giây và giết chết container của bạn bằng docker. Việc xử lý tín hiệu có thể được giảm thiểu bằng cách sử dụng exec
lệnh shell :
CMD /etc/init.d/nullmailer start ; exec /usr/sbin/php5-fpm
Tuy nhiên, việc xử lý các quá trình âm thầm không thành công trong nền đòi hỏi bạn phải chuyển sang một loại trình quản lý đa quy trình như giám sát viên, hoặc tốt nhất là chia ứng dụng của bạn thành nhiều thùng chứa và triển khai chúng với thứ gì đó như docker-compose.
exec
hình thức này , vì nó là hình thức ưa thích? Tại sao nó được ưa thích? Hoặc tôi nên sử dụngshell
hình thức đơn giản hơn ?