Tidak mengerti apa yang terjadi ketika saya mencoba menjalankan dua perintah pada saat runtime melalui CMD directive di `Dockerfile. Saya berasumsi bahwa ini akan berhasil:
CMD ["/etc/init.d/nullmailer", "start", ";", "/usr/sbin/php5-fpm"]
Tapi itu tidak berhasil. Kontainer belum dimulai. Jadi saya harus melakukannya seperti ini:
CMD ["sh", "-c", "/etc/init.d/nullmailer start ; /usr/sbin/php5-fpm"]
Saya tidak mengerti. Mengapa demikian? Mengapa baris pertama bukan jalan yang benar? Adakah yang bisa menjelaskan hal-hal "CMD shell format vs JSON, dll" ini. Dengan kata-kata sederhana.
Hanya untuk dicatat - sama dengan command:
direktif docker-compose.yml
, seperti yang diharapkan.
exec
formulir ini , karena ini adalah formulir yang disukai? Mengapa lebih disukai? Atau haruskah saya menggunakanshell
formulir yang lebih sederhana ?CMD [ "sh", "-c", "echo", "$HOME"]
. Kenapa tidakCMD ["sh", "-c", "echo $HOME"]
atau, dalam hal iniCMD ["sh -c echo $HOME"]
,?Jangan menyulitkan diri sendiri. Cukup buat file bash "start.sh":
di Dockerfile Anda lakukan:
sumber
Sintaks json dari
CMD
(danRUN
danENTRYPOINT
) meneruskan argumen ke kernel secara langsung sebagai syscall exec. Tidak ada pemisahan perintah dari argumen dengan spasi, melarikan diri dari kutipan, pengalihan IO, substitusi variabel, perpipaan antara perintah, menjalankan beberapa perintah, dll, dalam syscall exec. Syscall hanya membutuhkan executable untuk dijalankan dan daftar argumen untuk diteruskan ke executable itu, dan menjalankannya.Karakter suka
$
memperluas variabel,;
untuk memisahkan perintah,(spasi) untuk memisahkan argumen,
&&
dan||
untuk rantai perintah,>
untuk pengalihan output,|
untuk menyalurkan antar perintah, dll, semua fitur dari shell dan memerlukan sesuatu seperti/bin/sh
atau/bin/bash
untuk menafsirkan dan mengimplementasikannya.Jika Anda beralih ke sintaks string
CMD
, buruh pelabuhan akan menjalankan perintah Anda dengan sebuah shell:Jika tidak, sintaks kedua Anda melakukan hal yang persis sama:
Perhatikan bahwa saya tidak merekomendasikan menjalankan banyak perintah dengan cara ini di dalam sebuah wadah karena tidak ada kesalahan penanganan jika perintah pertama Anda gagal, terutama jika itu berjalan di latar belakang. Anda juga membiarkan cangkang berjalan sebagai pid 1 di dalam wadah yang akan merusak penanganan sinyal, menghasilkan penundaan 10 detik dan pembunuhan yang tidak berterima terhadap kontainer oleh buruh pelabuhan. Penanganan sinyal dapat dikurangi dengan menggunakan
exec
perintah shell :Namun, proses penanganan gagal secara diam-diam di latar belakang mengharuskan Anda beralih ke beberapa jenis manajer multi-proses seperti pengawas, atau lebih baik memecah aplikasi Anda menjadi beberapa wadah dan menyebarkannya dengan sesuatu seperti komposisi buruh pelabuhan.
sumber
Saya kira perintah pertama gagal karena dalam bentuk DOCKER CMD, hanya parameter pertama yang dieksekusi, sisanya dimasukkan ke dalam perintah ini.
Bentuk kedua berfungsi karena semua perintah dipisahkan dengan ";" dimasukkan ke dalam perintah sh, yang mengeksekusi mereka.
sumber
Saya tidak berpikir Anda harus meletakkan semi koma setelah "mulai"
alih-alih menggunakan
mencoba
karena buruh pelabuhan menggunakan "sh -c", perintah di atas akan dieksekusi seperti di bawah ini
sumber
sh -c
dalam skenario itu.