Mengapa saya tidak dapat menggunakan Docker CMD beberapa kali untuk menjalankan banyak layanan?

97

Saya telah membangun gambar dasar dari Dockerfile bernama centos + ssh. Di Dockerfile centos + ssh, saya menggunakan CMD untuk menjalankan layanan ssh.

Kemudian saya ingin membangun image menjalankan layanan lain bernama rabbitmq, Dockerfile:

FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD /opt/mq/sbin/rabbitmq-server start

Untuk memulai wadah kelinci , jalankan :

docker run -d -p 222:22 -p 4149:4149 rabbitmq

tetapi layanan ssh tidak berfungsi, ini merasakan Dockerfile CMD dari Rabbitmq menggantikan CMD centos.

  1. Bagaimana CMD bekerja di dalam image buruh pelabuhan?
  2. Jika saya ingin menjalankan banyak layanan, bagaimana caranya? Menggunakan supervisor?
edwardsbean
sumber

Jawaban:

63

Meskipun CMD ditulis di Dockerfile, itu sebenarnya adalah informasi runtime. Sama seperti EXPOSE, tetapi bertentangan dengan mis. LARI dan TAMBAH. Maksud saya, Anda dapat menggantinya nanti, dalam Dockerfile yang diperluas, atau sederhana dalam perintah run Anda, yang Anda alami. Setiap saat, hanya ada satu CMD.

Jika ingin menjalankan banyak layanan, saya memang akan menggunakan supervisor. Anda dapat membuat file konfigurasi supervisor untuk setiap layanan, TAMBAHKAN ini di direktori, dan jalankan supervisor dengan supervisord -c /etc/supervisoruntuk menunjuk ke file konfigurasi supervisor yang memuat semua layanan Anda dan tampilannya

[supervisord]
nodaemon=true

[include]
files = /etc/supervisor/conf.d/*.conf

Jika Anda ingin detail lebih lanjut, saya menulis blog tentang subjek ini di sini: http://blog.trifork.com/2014/03/11/using-supervisor-with-docker-to-manage-processes-supporting-image- warisan/

qkrijger.dll
sumber
Terima kasih, supervisor adalah ide yang bagus, tapi saya bertanya-tanya bagaimana cara kerja CMD di dalam gambar buruh pelabuhan
edwardsbean
2
Anda mengajukan dua pertanyaan, 2. tentang menjalankan beberapa layanan. Saat bertanya-tanya bagaimana CMD bekerja, harap jelaskan apa yang ingin Anda ketahui secara spesifik. Saya sudah menyebutkannya sebagai informasi runtime dan ditimpa oleh CMD baru.
qkrijger
119

Anda benar, Dockerfile kedua akan menimpa CMDperintah yang pertama. Docker akan selalu menjalankan satu perintah, tidak lebih. Jadi di akhir Dockerfile Anda, Anda dapat menentukan satu perintah untuk dijalankan. Tidak lebih.

Tetapi Anda dapat menjalankan kedua perintah dalam satu baris:

FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD service sshd start && /opt/mq/sbin/rabbitmq-server start

Apa yang juga dapat Anda lakukan untuk membuat Dockerfile Anda sedikit lebih bersih, Anda dapat meletakkan perintah CMD Anda ke file tambahan:

FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD sh /home/centos/all_your_commands.sh

Dan file seperti ini:

service sshd start &
/opt/mq/sbin/rabbitmq-server start
Thomas Uhrig
sumber
1
terima kasih, saya pikir menggunakan supervisor lebih baik. tetapi mengapa buruh pelabuhan hanya menjalankan satu CMD? apa yang terjadi di dalamnya?
edwardsbean
1
Saya tidak tahu apa yang terjadi di dalam. Tapi saya rasa memang didesain seperti itu. Ketika Anda memiliki gambar dan menjalankan perintah di dalamnya (misalnya dengan CMD), itu memulai sebuah wadah. Penampung berjalan selama perintah dijalankan. Dan segera setelah perintah selesai, penampung juga berhenti. Jadi setiap penampung mewakili satu perintah (berjalan).
Thomas Uhrig
saya pikir mungkin karena lcx atau batas sesuatu
edwardsbean
2
@ Tyguy7 .. karena ................?
StartupGuy
1
&&teknik hanya akan bekerja dengan layanan non-interaktif (yang dapat dimulai di latar belakang) jika tidak, hanya layanan pertama yang akan berjalan.
noraj
26

Sementara saya menghormati jawaban dari qkrijger yang menjelaskan bagaimana Anda dapat mengatasi masalah ini, saya pikir masih banyak lagi yang dapat kita pelajari tentang apa yang terjadi di sini ...

Untuk benar-benar menjawab pertanyaan Anda tentang " mengapa " ... Saya pikir akan sangat membantu bagi Anda untuk memahami cara kerja docker stopperintah dan bahwa semua proses harus dimatikan dengan bersih untuk mencegah masalah ketika Anda mencoba untuk memulai ulang (file korupsi dll).

Masalah: Bagaimana jika buruh pelabuhan benar-benar memulai SSH dari perintahnya dan memulai RabbitMQ dari file Docker Anda? " Perintah docker stop mencoba menghentikan container yang sedang berjalan terlebih dahulu dengan mengirimkan sinyal SIGTERM ke proses root (PID 1) di container. " Proses manakah yang merupakan pelacakan buruh pelabuhan sebagai PID 1 yang akan mendapatkan SIGTERM? Apakah itu SSH atau Rabbit ?? "Menurut model proses Unix, proses init - PID 1 - mewarisi semua proses anak yatim piatu dan harus menuai semuanya. Sebagian besar container Docker tidak memiliki proses init yang melakukan ini dengan benar, dan akibatnya container mereka terisi dengan proses zombie dari waktu ke waktu. "

Jawaban: Docker hanya mengambil bahwa CMD lalu sebagai salah satu yang akan mendapatkan diluncurkan sebagai proses akar dengan PID 1 dan mendapatkan SIGTERM daridocker stop .

Solusi yang disarankan: Anda harus menggunakan (atau membuat) gambar dasar yang khusus dibuat untuk menjalankan lebih dari satu layanan, seperti phusion / baseimage

Penting untuk dicatat bahwa tini ada persis karena alasan ini, dan pada Docker 1.13 dan yang lebih baru, tini secara resmi merupakan bagian dari Docker, yang memberi tahu kita bahwa menjalankan lebih dari satu proses di Docker IS VALID .. bahkan jika seseorang mengklaim menjadi lebih terampil tentang Docker, dan bersikeras bahwa Anda tidak masuk akal karena berpikir untuk melakukan ini, ketahuilah bahwa Anda tidak. Ada situasi yang benar-benar valid untuk melakukannya.

Senang mendengarnya:

StartupGuy
sumber
3

Jawaban buruh pelabuhan resmi untuk Menjalankan beberapa layanan dalam satu wadah .

Ini menjelaskan bagaimana Anda dapat melakukannya dengan sistem init (systemd, sysvinit, pemula), script ( CMD ./my_wrapper_script.sh) atau supervisor sejenisnya supervisord.

The &&solusi dapat bekerja hanya untuk layanan yang dimulai di latar belakang (daemon) atau yang akan mengeksekusi cepat tanpa interaksi dan melepaskan prompt. Melakukan ini dengan layanan interaktif (yang membuat prompt) dan hanya layanan pertama yang akan dimulai.

noraj
sumber
0

Untuk mengatasi mengapa CMD dirancang untuk menjalankan hanya satu layanan per kontainer, mari kita sadari apa yang akan terjadi jika server sekunder yang dijalankan dalam kontainer yang sama bukanlah hal sepele / tambahan tetapi "utama" (misalnya penyimpanan yang dibundel dengan aplikasi frontend). Sebagai permulaan, ini akan memecah beberapa fitur penampungisasi penting seperti penskalaan horizontal (otomatis) dan penjadwalan ulang antar node, keduanya mengasumsikan hanya ada satu aplikasi (sumber beban CPU) per penampung. Lalu ada masalah kerentanan - lebih banyak server yang terekspos dalam satu wadah berarti lebih sering menambal CVE ...

Jadi mari kita akui bahwa ini adalah 'dorongan' dari perancang Docker (dan Kubernetes / Openhift) menuju praktik yang baik dan kami tidak boleh menemukan kembali solusi (SSH tidak diperlukan - kami telah docker exec / kubectl exec / oc rshmerancang untuk menggantinya).

  • Info lebih lanjut

/devops/447/why-it-is-recommended-to-run-only-one-process-in-a-container

mirekphd
sumber