Sintaks json dari CMD
(dan RUN
dan ENTRYPOINT
) meneruskan argumen ke kernel secara langsung sebagai Exec syscall. Tidak ada pemisahan perintah dari argumen dengan spasi, pelolosan tanda kutip, pengalihan IO, substitusi variabel, perpipaan antar perintah, menjalankan banyak perintah, dll, di Exec syscall. Syscall hanya membutuhkan executable untuk dijalankan dan daftar argumen untuk diteruskan ke executable itu, dan menjalankannya.
Karakter seperti $
untuk memperluas variabel, ;
untuk memisahkan perintah,
(spasi) untuk memisahkan argumen, &&
dan ||
untuk perintah rantai, >
untuk pengalihan keluaran, |
untuk pipa antara perintah, dll, semua fitur dari shell dan perlu sesuatu seperti /bin/sh
atau /bin/bash
untuk menafsirkan dan mengimplementasikannya.
Jika Anda beralih ke sintaks string CMD
, docker akan menjalankan perintah Anda dengan shell:
CMD /etc/init.d/nullmailer start ; /usr/sbin/php5-fpm
Jika tidak, sintaks kedua anda melakukan hal yang sama persis:
CMD ["sh", "-c", "/etc/init.d/nullmailer start ; /usr/sbin/php5-fpm"]
Perhatikan bahwa saya tidak menyarankan menjalankan beberapa perintah dengan cara ini di dalam wadah karena tidak ada penanganan kesalahan jika perintah pertama Anda gagal, terutama jika berjalan di latar belakang. Anda juga membiarkan shell berjalan sebagai pid 1 di dalam wadah yang akan merusak penanganan sinyal, menghasilkan penundaan 10 detik dan pembunuhan kontainer Anda yang tidak menyenangkan oleh buruh pelabuhan. Penanganan sinyal dapat dikurangi dengan menggunakan shell exec
perintah:
CMD /etc/init.d/nullmailer start ; exec /usr/sbin/php5-fpm
Namun, menangani proses yang gagal secara diam-diam di latar belakang mengharuskan Anda beralih ke semacam manajer multi-proses seperti supervisord, atau lebih disukai memecah aplikasi Anda menjadi beberapa wadah dan menerapkannya dengan sesuatu seperti docker-compose.