Cara Menjalankan Beberapa Layanan Dalam Satu Kontainer Docker

Diterbitkan: 2022-06-30

Ilustrasi yang menunjukkan logo Docker

Docker adalah teknologi untuk mengemas komponen tumpukan Anda sebagai wadah yang terisolasi. Ini adalah praktik umum untuk menjalankan setiap proses Anda dalam wadahnya sendiri, menciptakan pemisahan yang bersih antar komponen. Ini meningkatkan modularitas dan memungkinkan Anda mengakses manfaat skalabilitas containerisasi.

Masih ada situasi di mana Anda ingin menjalankan beberapa layanan dalam satu wadah. Meskipun ini tidak muncul secara alami di ekosistem Docker, kami akan menunjukkan beberapa pendekatan berbeda yang dapat Anda gunakan untuk membuat container dengan lebih dari satu proses yang berumur panjang.

Mengidentifikasi Masalah

Kontainer Docker menjalankan satu proses latar depan. Ini ditentukan oleh instruksi ENTRYPOINT dan CMD gambar. ENTRYPOINT diatur dalam Dockerfile gambar sementara CMD dapat diganti saat membuat wadah. Kontainer secara otomatis berhenti ketika proses latar depan mereka keluar.

Anda dapat meluncurkan proses lain dari CMD tetapi wadah hanya akan tetap berjalan saat proses latar depan asli masih hidup. Menjaga kontainer tetap beroperasi melalui masa pakai gabungan dari dua layanan independen tidak dapat dilakukan secara langsung menggunakan mekanisme ENTRYPOINT/CMD .

Membungkus Beberapa Proses dalam Satu Titik Masuk

Skrip pembungkus adalah solusi paling sederhana untuk masalah ini. Anda dapat menulis skrip yang memulai semua proses Anda dan menunggu hingga selesai. Menyetel skrip sebagai ENTRYPOINT Docker Anda akan menjalankannya sebagai proses latar depan penampung, menjaga penampung tetap berjalan hingga salah satu skrip yang dibungkus keluar.

 #!/bin/bash

/opt/proses pertama &

/opt/proses kedua &

tunggu -n

keluar $?

Skrip ini memulai binari /opt/first-process dan /opt/second-process di dalam wadah. Penggunaan & memungkinkan skrip untuk melanjutkan tanpa menunggu setiap proses keluar. wait digunakan untuk menangguhkan skrip sampai salah satu proses berhenti. Skrip kemudian keluar dengan kode status yang dikeluarkan oleh skrip yang sudah jadi.

Model ini menghasilkan wadah yang menjalankan first-process second-process hingga salah satunya keluar. Pada saat itu, wadah akan berhenti, meskipun proses lain mungkin masih berjalan.

Untuk menggunakan skrip ini, ubah ENTRYPOINT dan CMD gambar Docker Anda untuk menjadikannya proses latar depan penampung:

 ENTRYPOINT ["/bin/sh"]
CMD ["./path/ke/script.sh"]

Opsi Kontainer --init

Salah satu tantangan dalam mengelola proses container adalah membersihkan secara efektif saat proses tersebut keluar. Docker menjalankan CMD Anda sebagai ID proses 1, membuatnya bertanggung jawab untuk menangani sinyal dan menghilangkan zombie. Jika skrip Anda tidak memiliki kemampuan ini, Anda bisa berakhir dengan proses anak yatim piatu yang bertahan di dalam wadah Anda.

Perintah docker run memiliki flag --init yang memodifikasi entrypoint untuk menggunakan tini sebagai PID 1. Ini adalah implementasi proses init minimal yang menjalankan CMD Anda, menangani penerusan sinyal, dan terus-menerus menuai zombie.

Sebaiknya gunakan --init jika Anda berharap akan menghasilkan banyak proses dan tidak ingin menangani pembersihan secara manual. Tini adalah rasa init ringan yang dirancang untuk wadah. Ini jauh lebih kecil daripada alternatif yang lengkap seperti systemd dan upstart .

Menggunakan Manajer Proses Khusus

Pembuatan skrip manual dengan cepat menjadi kurang optimal ketika Anda memiliki banyak proses untuk dikelola. Mengadopsi manajer proses adalah cara lain untuk menjalankan beberapa layanan di dalam wadah Docker Anda. Manajer proses menjadi ENTRYPOINT Anda dan bertanggung jawab untuk memulai, memelihara, dan membersihkan setelah proses pekerja Anda.

Ada beberapa pilihan yang tersedia ketika menerapkan pendekatan ini. supervisord adalah pilihan populer yang mudah dikonfigurasi melalui file /etc/supervisor/conf.d/supervisord.conf :

 [program:apache2]
command=/usr/sbin/apache2 -DFOREGROUND

[program: mysqld]
perintah=/usr/sbin/mysqld_safe

File konfigurasi ini mengonfigurasi supervisord untuk memulai Apache dan MySQL. Untuk menggunakannya dalam wadah Docker, tambahkan semua paket yang diperlukan ke gambar Anda, lalu salin file konfigurasi supervisord Anda ke lokasi yang benar. Tetapkan supervisord sebagai CMD gambar untuk menjalankannya secara otomatis saat container dimulai.

 DARI ubuntu: terbaru
JALANKAN apt-get install -y apache2 mysql-server supervisor
SALIN supervisord.conf /etc/supervisor/conf.d/supervisord.conf
ENTRYPOINT ["/bin/sh"]
CMD ["/usr/bin/pengawas"]

Karena supervisord berjalan terus-menerus, container tidak dapat dihentikan saat salah satu proses yang dipantau keluar. Opsi alternatif adalah s6-overlay yang memang memiliki kemampuan ini. Ini menggunakan model layanan deklaratif di mana Anda menempatkan skrip layanan langsung ke /etc/services.d :

 # Tambahkan s6-overlay ke gambar Anda
TAMBAHKAN https://github.com/just-containers/s6-overlay/releases/download/v3.1.0.0/s6-overlay-noarch.tar.xz /tmp
JALANKAN tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz

JALANKAN printf "#!/bin/shn/usr/sbin/Apache2 -DFOREGROUND"> /etc/services.d/first-service/run
JALANKAN chmod +x /etc/services.d/first-service/run

# Gunakan s6-overlay sebagai titik masuk gambar Anda
ENTRYPOINT ["/init"]

Anda dapat menambahkan skrip finish yang dapat dieksekusi di dalam direktori layanan Anda untuk menangani penghentian wadah dengan docker stop . s6-overlay akan secara otomatis menjalankan skrip ini ketika prosesnya menerima sinyal TERM karena perintah stop .

Skrip akhir menerima kode keluar dari layanan mereka sebagai argumen pertama mereka. Kode diatur ke 256 ketika layanan dimatikan karena sinyal yang tidak tertangkap. Script perlu menulis kode keluar terakhir ke /run/s6-linux-init-container-results/exitcode ; s6-overlay membaca file ini dan keluar dengan nilai di dalamnya, menyebabkan kode tersebut digunakan sebagai kode stop container Anda.

 #!/bin/sh
echo "$1" > /run/s6-linux-init-container-results/exitcode

Kapan Anda Harus Menjalankan Beberapa Proses Dalam Kontainer?

Teknik ini paling baik digunakan dengan proses yang digabungkan erat yang tidak dapat Anda pisahkan untuk dijalankan sebagai wadah independen. Anda mungkin memiliki program yang bergantung pada utilitas pembantu latar belakang atau aplikasi monolitik yang melakukan manajemen proses individualnya sendiri. Teknik yang ditunjukkan di atas dapat membantu Anda menampung jenis perangkat lunak ini.

Menjalankan beberapa proses dalam sebuah wadah tetap harus dihindari sedapat mungkin. Berpegang teguh pada satu proses latar depan memaksimalkan isolasi, mencegah komponen saling mengganggu, dan meningkatkan kemampuan Anda untuk men-debug dan menguji bagian tertentu. Anda dapat menskalakan komponen satu per satu menggunakan orkestra penampung, yang memberi Anda fleksibilitas untuk menjalankan lebih banyak instans dari proses paling intensif sumber daya Anda.

Kesimpulan

Kontainer biasanya memiliki satu proses latar depan dan berjalan selama masih hidup. Model ini selaras dengan praktik terbaik containerisasi dan memungkinkan Anda memperoleh manfaat maksimal dari teknologi.

Dalam beberapa situasi, Anda mungkin memerlukan beberapa proses untuk dijalankan dalam sebuah wadah. Karena semua gambar pada akhirnya memiliki satu titik masuk, Anda harus menulis skrip pembungkus atau menambahkan manajer proses yang bertanggung jawab untuk memulai binari target Anda.

Pengelola proses memberi Anda semua yang Anda butuhkan tetapi mengasapi gambar Anda dengan paket dan konfigurasi tambahan. Skrip pembungkus lebih sederhana tetapi mungkin perlu dipasangkan dengan flag --init Docker untuk mencegah proliferasi proses zombie.