Nhiều lệnh trong Docker HIỆU chỉ thị

Không hiểu những gì đang xảy ra khi tôi cố gắng để thực hiện hai lệnh lúc chạy qua HIỆU chỉ dẫn `Dockerfile. Tôi nghĩ rằng điều này sẽ làm việc:

CMD ["/etc/init.d/nullmailer", "start", ";", "/usr/sbin/php5-fpm"]

Nhưng nó không phải làm việc. Container chưa bắt đầu. Vì vậy, tôi đã làm điều đó như thế này:

CMD ["sh", "-c", "/etc/init.d/nullmailer start ; /usr/sbin/php5-fpm"]

Tôi không hiểu. Tại sao vậy? Tại sao dòng đầu tiên là không đúng cách? Ai đó có thể giải thích cho tôi những "ĐẶT vỏ dạng vs HỆT định dạng, etc" công cụ. Nói một cách đơn giản.

Chỉ cần để ý - cùng với command: chỉ trong docker-compose.yml như mong đợi.

Tôi tin sự khác biệt, có thể là vì lệnh thứ hai không vỏ xử lý trong khi lần đầu tiên không. Mỗi tài liệu chính thức đó là những execshell hình thức. Lần đầu chỉ huy là một exec mẫu. Những exec thức không mở rộng biến môi trường trong khi những shell hình thức nào. Đó có thể là bằng việc sử dụng exec hình thức lệnh là không do của nó phụ thuộc vào vỏ xử lý. Bạn có thể kiểm tra này bằng cách chạy docker logs CONTAINERID

Thứ hai của bạn lệnh, vỏ hình thức là tương đương -

CMD /etc/init.d/nullmailer start ; /usr/sbin/php5-fpm

Đoạn trích từ những tài liệu -

Chú ý: không Giống như vỏ hình thức uống thức không gọi lệnh vỏ. Điều này có nghĩa là bình thường vỏ chế biến không xảy ra. Ví dụ:, CMD [ "echo", "$HOME" ] sẽ không làm biến thay thế vào $HOME. Nếu bạn muốn vỏ xử lý sau đó, hoặc sử dụng vỏ thức hoặc thực hiện một vỏ trực tiếp, ví dụ: CMD [ "sh", "-c", "echo", "$HOME" ].

Đừng làm nó khó khăn với chính mình. Chỉ tạo ra một bash tập tin và sẽ bắt đầu.sh một;:

#!/bin/bash/usr/bin/command2 param1/usr/bin/command1

trong Dockerfile làm:

ADD start.sh /RUN chmod +x /start.shCMD ["/start.sh"]

Các mảng cú pháp CMD (và RUNENTRYPOINT) vượt qua những lập luận cho hạt nhân trực tiếp như executive syscall. Không có tách của các lệnh từ những lập luận của không gian tẩu thoát của trích dẫn, IO chuyển hướng, biến thay thế đường ống giữa lệnh, chạy nhiều lệnh, ... trong sự của syscall. Các syscall chỉ mất thực thi để chạy và danh sách các lập luận để vượt qua mà thực thi, và nó chạy nó.

Giống như nhân vật $ để mở rộng biến, ; để tách lệnh, (không gian) để riêng, lập luận, &&|| để chuỗi các lệnh, > cho ra hướng, | để ống giữa các lệnh ... đang tất cả các chức năng của vỏ và cần một cái gì đó như thế /bin/sh hay /bin/bash để giải thích, và thực hiện chúng.


Nếu bạn chuyển chuỗi cú pháp CMD docker sẽ chạy lệnh của bạn với một vỏ:

CMD /etc/init.d/nullmailer start ; /usr/sbin/php5-fpm

Nếu không, thứ hai của bạn cú pháp làm 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 khuyên bạn không nên chạy nhiều lệnh cách này bên trong một container vì không có xử lý lỗi nếu lần đầu chỉ huy không, đặc biệt là nếu nó chạy trong nền. Bạn cũng để lại một vỏ chạy như giám sát 1 bên trong thùng đó sẽ phá vỡ tín hiệu xử, kết quả là một sự chậm trễ 10 giây và không có vẻ yêu kiều giết container của bạn của docker. Tín hiệu có thể xử lý được giảm nhẹ bằng cách sử dụng các vỏ exec lệnh:

CMD /etc/init.d/nullmailer start ; exec /usr/sbin/php5-fpm

Tuy nhiên, xử lý quá trình âm thầm thất bại trong nền yêu cầu chuyển sang một dạng của đa-quá trình quản lý, giống như supervisord, hoặc tốt hơn là chia tay của bạn ứng dụng vào nhiều hộp và triển khai với một cái gì đó như docker-soạn.

Tôi đoán là lần đầu chỉ huy không, bởi vì trong DOCKER ĐẶT mẫu, chỉ là số đầu tiên là thực hiện phần còn lại được đưa vào lệnh này.

Thứ hai, hình thức hoạt động bởi vì tất cả các lệnh tách ra với", " được đưa vào sh lệnh, mà thực hiện chúng.

Ví dụ, hãy tưởng tượng bạn có hai python lệnh để chạy python init_reset.pypython app.py. Sau đó, sử dụng HIỆU, bạn có thể kết hợp hai lệnh với các chỉ huy duy nhất,

CMD python init_reset.py ; python app.py

Trong Docker soạn, điều này có thể được thực hiện như ví dụ sau:

command: ["sh", "-c", "    apt update && apt install -y libldap-common;    cp /ca.crt /usr/local/share/ca-certificates/;    update-ca-certificates;    exec apache2-foreground  "]

Những exec sẽ chuyển bối cảnh của chính thực thi để apache2-forground.

Tôi không nghĩ rằng các bạn nên đặt bán dấu phẩy sau "bắt đầu"

thay vì sử dụng

CMD ["/etc/init.d/nullmailer", "start", ";", "/usr/sbin/php5-fpm"]

cố gắng

CMD ["/etc/init.d/nullmailer", "start", "/usr/sbin/php5-fpm"]

như docker sử dụng "sh -c", lệnh trên, sẽ được thực hiện như dưới đây,

/etc/init.d/nullmailer start/etc/init.d/nullmailer /usr/sbin/php5-fpm