Compose: Apakah ada cara untuk menunda startup kontainer untuk mendukung layanan yang bergantung dengan waktu startup yang lebih lama

Dibuat pada 5 Agu 2014  ·  314Komentar  ·  Sumber: docker/compose

Saya memiliki container MySQL yang membutuhkan sedikit waktu untuk memulai karena perlu mengimpor data.

Saya memiliki container Alfresco yang bergantung pada container MySQL.

Saat ini, ketika saya menggunakan ara, layanan Alfresco di dalam wadah Alfresco gagal ketika mencoba untuk menyambung ke wadah MySQL ... seolah-olah karena layanan MySQL belum mendengarkan.

Apakah ada cara untuk menangani masalah seperti ini di Fig?

Komentar yang paling membantu

Ya, saya akan tertarik dengan hal seperti ini - dimaksudkan untuk mempostingnya lebih awal.

Pola dampak terkecil yang dapat saya pikirkan yang akan memperbaiki kasus penggunaan ini bagi kita adalah sebagai berikut:

Tambahkan "tunggu" sebagai kunci baru di fig.yml, dengan semantik nilai yang sama sebagai link. Docker akan memperlakukan ini sebagai prasyarat dan menunggu sampai kontainer ini keluar sebelum melanjutkan.

Jadi, file buruh pelabuhan saya akan terlihat seperti ini:

db:
  image: tutum/mysql:5.6

initdb:
  build: /path/to/db
  link:
    - db:db
  command: /usr/local/bin/init_db

app:
  link:
    - db:db
  wait:
    - initdb

Saat menjalankan aplikasi, itu akan memulai semua penampung tautan, lalu menjalankan penampung tunggu dan hanya melanjutkan ke penampung aplikasi yang sebenarnya setelah penampung tunggu (initdb) telah keluar. initdb akan menjalankan skrip yang menunggu database tersedia, lalu menjalankan inisialisasi / migrasi / apa pun, lalu keluar.

Itu adalah pikiranku.

Semua 314 komentar

Di tempat kerja kami membungkus layanan dependen kami dalam skrip yang memeriksa apakah tautannya sudah habis. Saya tahu salah satu rekan saya akan tertarik dengan ini juga! Secara pribadi saya merasa menunggu layanan tersedia adalah masalah tingkat kontainer, tetapi saya mungkin salah :)

Kami melakukan hal yang sama dengan membungkus. Anda dapat melihat contohnya di sini: https://github.com/dominionentertures/tol-api-php/blob/master/tests/provisioning/set-env.sh

Akan berguna untuk memiliki skrip entrypoint yang mengulang semua tautan dan menunggu sampai mereka berfungsi sebelum memulai perintah yang diteruskan ke sana.

Ini harus dibangun ke Docker itu sendiri, tetapi solusinya adalah jalan keluar. Penampung tidak boleh dianggap dimulai sampai link yang ditampilkannya telah dibuka.

@bfirsh itu lebih dari yang saya bayangkan, tetapi akan sangat baik.

Penampung tidak boleh dianggap dimulai sampai link yang ditampilkannya telah dibuka.

Saya pikir itulah yang dibutuhkan orang.

Untuk saat ini, saya akan menggunakan variasi di https://github.com/aanand/docker-wait

Ya, saya akan tertarik dengan hal seperti ini - dimaksudkan untuk mempostingnya lebih awal.

Pola dampak terkecil yang dapat saya pikirkan yang akan memperbaiki kasus penggunaan ini bagi kita adalah sebagai berikut:

Tambahkan "tunggu" sebagai kunci baru di fig.yml, dengan semantik nilai yang sama sebagai link. Docker akan memperlakukan ini sebagai prasyarat dan menunggu sampai kontainer ini keluar sebelum melanjutkan.

Jadi, file buruh pelabuhan saya akan terlihat seperti ini:

db:
  image: tutum/mysql:5.6

initdb:
  build: /path/to/db
  link:
    - db:db
  command: /usr/local/bin/init_db

app:
  link:
    - db:db
  wait:
    - initdb

Saat menjalankan aplikasi, itu akan memulai semua penampung tautan, lalu menjalankan penampung tunggu dan hanya melanjutkan ke penampung aplikasi yang sebenarnya setelah penampung tunggu (initdb) telah keluar. initdb akan menjalankan skrip yang menunggu database tersedia, lalu menjalankan inisialisasi / migrasi / apa pun, lalu keluar.

Itu adalah pikiranku.

(direvisi, lihat di bawah)

+1 di sini juga. Tidak terlalu menarik untuk melakukan ini dalam perintah itu sendiri.

+1 juga. Baru saja mengalami masalah ini. Alat hebat btw, membuat hidup saya jauh lebih mudah!

+1 akan sangat bagus untuk memiliki ini.

+1 juga. Baru-baru ini mengalami serangkaian masalah yang sama

+1 juga. ada pernyataan dari dockerguys?

Saya sedang menulis skrip pembungkus sebagai titik masuk untuk disinkronkan saat ini, tidak yakin apakah memiliki mekanisme dalam ara adalah bijaksana jika Anda memiliki target lain untuk penampung Anda yang melakukan orkestrasi dengan cara yang berbeda. Tampaknya aplikasi sangat spesifik bagi saya, seperti tanggung jawab container yang melakukan pekerjaan.

Setelah beberapa pemikiran dan eksperimen, saya agak setuju dengan ini.

Seperti aplikasi yang saya bangun pada dasarnya memiliki sinkronisasi
fungsi waitfor (host, port) yang memungkinkan saya menunggu layanan aplikasi
bergantung pada (baik dideteksi melalui lingkungan atau secara eksplisit
konfigurasi melalui opsi cli).

Bersulang
James

James Mills / prologic

E: [email protected]
W: prologic.shortcircuit.net.au

Pada hari Jumat, 22 Agustus 2014 pukul 18.34, Mark Stuart [email protected]
menulis:

Saya sedang menulis skrip pembungkus sebagai titik masuk untuk disinkronkan saat ini,
tidak yakin apakah memiliki mekanisme dalam ara adalah bijaksana jika Anda memiliki target lain
penampung Anda yang melakukan orkestrasi dengan cara yang berbeda. Sepertinya sangat
aplikasi khusus untuk saya seperti tanggung jawab kontainer
melakukan pekerjaan.

-
Balas email ini secara langsung atau lihat di GitHub
https://github.com/docker/fig/issues/374#issuecomment -53036154.

Ya, beberapa dasar "bergantung pada" diperlukan di sini ...
jadi jika Anda memiliki 20 kontainer, Anda tidak ingin menjalankannya dan semuanya dimulai dengan urutan yang benar ...
Namun itu juga memiliki beberapa opsi batas waktu atau mekanisme penangkapan kegagalan lainnya

+1 lainnya di sini. Saya memiliki Postgres yang membutuhkan waktu lebih lama daripada Django untuk memulai sehingga DB tidak ada di sana untuk perintah migrasi tanpa peretasan.

@ahknight menarik, mengapa migrasi berjalan selama run ?

Tidakkah Anda ingin benar-benar menjalankan migrasi selama fase build ? Dengan begitu, Anda dapat memulai gambar baru dengan lebih cepat.

Sayangnya, ada skrip startup yang lebih besar untuk aplikasi yang dimaksud. Untuk saat ini, kami melakukan pekerjaan non-DB terlebih dahulu, menggunakan nc -w 1 dalam satu putaran untuk menunggu DB, kemudian melakukan tindakan DB. Berhasil, tapi membuatku merasa kotor (er).

Saya telah banyak berhasil melakukan pekerjaan ini selama fase fig build . Saya punya satu contoh tentang ini dengan proyek django (masih dalam proses): https://github.com/dnephin/readthedocs.org/blob/fig-demo/dockerfiles/database/Dockerfile#L21

Tidak perlu polling untuk memulai. Meskipun saya telah melakukan sesuatu yang mirip dengan mysql, di mana saya harus melakukan polling untuk memulai karena skrip mysqld init belum melakukannya. Skrip init postgres ini tampaknya jauh lebih baik.

Inilah yang saya pikirkan:

Menggunakan ide buruh pelabuhan / buruh pelabuhan # 7445 kita bisa mengimplementasikan atribut "wait_for_helth_check" ini di gbr?
Jadi itu akan menjadi ara bukan masalah Docker?

apakah ada cara untuk membuat ara memeriksa status tcp pada penampung yang ditautkan, jika demikian maka saya pikir ini adalah cara untuk pergi. =)

@dnephin dapatkah Anda menjelaskan lebih banyak lagi apa yang Anda lakukan di Dockerfiles untuk membantu ini?
Bukankah fase build tidak dapat memengaruhi runtime?

@docteurlein saya bisa. Saya memperbaiki tautan dari atas (https://github.com/dnephin/readthedocs.org/blob/fig-demo/dockerfiles/database/Dockerfile#L21)

Idenya adalah Anda melakukan semua operasi "penyiapan" yang lebih lambat selama pembuatan, jadi Anda tidak perlu menunggu apa pun selama memulai penampung. Dalam kasus database atau indeks pencarian, Anda akan:

  1. memulai layanan
  2. membuat pengguna, database, tabel, dan data fixture
  3. matikan layanan

semuanya sebagai satu langkah pembuatan. Kemudian ketika Anda fig up kontainer database, pada dasarnya siap untuk segera dijalankan, dan Anda juga bisa memanfaatkan cache build buruh pelabuhan untuk operasi yang lebih lambat ini.

bagus! terima kasih :)

@dnephin bagus, belum memikirkan itu.

+1 Ini pasti dibutuhkan.
Peretasan penundaan waktu yang buruk dalam banyak kasus sudah cukup, tetapi solusi _real_ akan diterima.

Bisakah Anda memberi contoh mengapa / kapan itu dibutuhkan?

Dalam kasus penggunaan yang saya miliki, saya memiliki server Elasticsearch, lalu server aplikasi yang terhubung ke Elasticsearch. Elasticsearch membutuhkan beberapa detik untuk berputar, jadi saya tidak bisa begitu saja melakukan fig up -d karena server aplikasi akan segera gagal saat menghubungkan ke server Elasticsearch.

Katakanlah satu penampung memulai MySQL dan yang lainnya memulai aplikasi yang membutuhkan MySQL dan ternyata aplikasi lain mulai lebih cepat. Kami mengalami kegagalan fig up karena itu.

crane memiliki cara untuk mengatasi hal ini dengan memungkinkan Anda membuat grup yang dapat dimulai secara individual. Jadi Anda dapat memulai grup MySQL, tunggu 5 detik dan kemudian mulai hal-hal lain yang bergantung padanya.
Bekerja dalam skala kecil, tetapi bukan solusi nyata.

@oskarhane tidak yakin apakah "tunggu 5 detik" ini membantu, dalam beberapa kasus mungkin perlu menunggu lebih lama (atau tidak bisa memastikan tidak akan melebihi 5 detik) ... tidak terlalu aman untuk mengandalkan waktu menunggu.
Anda juga harus melakukan ini secara manual menunggu dan memuat grup lain, dan itu agak payah, fig harus melakukannya untuk Anda = /

@oskarhane , @dacort , @ddossot : Perlu diingat bahwa, di dunia nyata, banyak hal macet dan dimulai ulang, koneksi jaringan datang dan pergi, dll. Apakah Fig memperkenalkan kemudahan untuk menunggu di soket TCP atau tidak, container Anda harus tahan terhadap kegagalan koneksi. Dengan begitu, mereka akan bekerja dengan baik di mana saja.

Anda benar, tetapi sampai kami memperbaiki semua aplikasi yang sudah ada untuk melakukan hal-hal seperti memulihkan dengan anggun dari tidak adanya sumber daya kritisnya (seperti DB) saat memulai (yang merupakan Hal yang Hebat ™ tetapi sayangnya jarang didukung oleh kerangka kerja), kita harus menggunakan fig start untuk memulai penampung individu dalam urutan tertentu, dengan penundaan, bukan fig up .

Saya dapat melihat skrip shell datang untuk mengontrol ara untuk mengontrol buruh pelabuhan: wink:

Saya baik-baik saja dengan ini tidak dibangun untuk ara tetapi beberapa saran tentang praktik terbaik untuk menunggu kesiapan akan baik

Saya melihat di beberapa kode yang ditautkan dari komentar sebelumnya, ini dilakukan:

while ! exec 6<>/dev/tcp/${MONGO_1_PORT_27017_TCP_ADDR}/${MONGO_1_PORT_27017_TCP_PORT}; do
    echo "$(date) - still trying to connect to mongo at ${TESTING_MONGO_URL}"
    sleep 1
done

Dalam kasus saya tidak ada /dev/tcp path, mungkin itu distro linux yang berbeda (?) - Saya menggunakan Ubuntu

Saya malah menemukan metode ini yang tampaknya berfungsi dengan baik:

until nc -z postgres 5432; do
    echo "$(date) - waiting for postgres..."
    sleep 1
done

Ini tampaknya berfungsi tetapi saya tidak cukup tahu tentang hal-hal seperti itu untuk mengetahui apakah itu kuat ... apakah ada yang tahu jika ada kemungkinan kondisi balapan antara port yang muncul hingga nc dan server postgres _really_ dapat menerima perintah?

Saya akan lebih senang jika dimungkinkan untuk membalikkan cek - daripada melakukan polling dari container dependen, apakah mungkin mengirim sinyal dari container target (yaitu server postgres) ke semua dependen?

Mungkin itu ide yang konyol, ada yang punya pemikiran?

Tautan Docker

apakah ada yang tahu jika ada kemungkinan kondisi balapan antara port yang muncul ke nc dan server postgres benar-benar dapat menerima perintah?

Tidak ada cara untuk mengetahui dalam kasus umum - mungkin benar untuk postgres, mungkin salah untuk layanan lain - yang merupakan argumen lain untuk tidak melakukannya pada Gambar.

@aanand Saya mencoba menggunakan pendekatan gambar buruh pelabuhan / tunggu tetapi saya tidak yakin apa yang terjadi. Jadi pada dasarnya saya memiliki wadah "Orientdb" ini yang ditautkan ke banyak wadah aplikasi NodeJS lainnya. Kontainer orientdb ini membutuhkan beberapa waktu untuk mulai mendengarkan pada port TCP dan ini membuat kontainer lain mendapatkan kesalahan "Connection Refused".

Saya berharap dengan menautkan wadah tunggu ke Orientdb saya tidak akan melihat kesalahan ini. Tapi sayangnya saya masih mendapatkannya secara acak. Ini adalah pengaturan saya (Docker versi 1.4.1, fig 1.0.1 pada Ubuntu 14.04 Box):

orientdb:
    build: ./Docker/orientdb
    ports:
        -   "2424:2424"
        -   "2480:2480"
wait:
    build: ./Docker/wait
    links:
        - orientdb:orientdb
....
core:
    build:  ./Docker/core
    ports:
        -   "3000:3000"
    links:
        -   orientdb:orientdb
        -   nsqd:nsqd

Bantuan apa pun dihargai. Terima kasih.

@mindnuts gambar wait lebih merupakan demonstrasi; itu tidak cocok untuk digunakan dalam fig.yml . Anda harus menggunakan teknik yang sama (polling berulang) dalam container core untuk menunggu container orientdb dimulai sebelum memulai proses utama.

+1 baru saja mulai menjalankan ini saat saya menarik gambar yang dibuat khusus vs membangunnya di fig.yml. Aplikasi node gagal karena mongodb belum siap ...

Saya baru saja menghabiskan berjam-jam men-debug mengapa MySQL dapat dijangkau saat memulai WordPress secara manual dengan Docker, dan mengapa offline saat memulai dengan Fig. Baru sekarang saya menyadari bahwa Fig selalu me-restart container MySQL setiap kali saya memulai aplikasi, sehingga entrypoint.sh WordPress mati belum dapat terhubung ke MySQL.

Saya menambahkan entrypoint.sh saya yang telah diganti yang menunggu selama 5 detik sebelum mengeksekusi entrypoint.sh yang sebenarnya. Tapi yang jelas ini adalah kasus penggunaan yang membutuhkan solusi umum, jika seharusnya mudah meluncurkan kombinasi container MySQL + WordPress dengan Docker / Fig.

sehingga entrypoint.sh WordPress mati karena belum dapat terhubung ke MySQL.

Saya pikir ini adalah masalah dengan penampung WordPress.

Meskipun awalnya saya adalah penggemar ide ini, setelah membaca https://github.com/docker/docker/issues/7445#issuecomment -56391294, saya pikir fitur seperti itu akan menjadi pendekatan yang salah, dan sebenarnya mendorong praktik yang buruk.

Tampaknya ada dua kasus yang ingin ditangani oleh masalah ini:

Layanan ketergantungan harus tersedia untuk melakukan beberapa inisialisasi.

Inisialisasi kontainer apa pun harus benar-benar dilakukan selama build . Dengan cara itu gambar tersebut di-cache, dan pekerjaan tersebut tidak perlu diulangi oleh setiap pengguna gambar.

Layanan ketergantungan harus tersedia agar koneksi dapat dibuka

Aplikasi harus benar-benar tahan terhadap kegagalan koneksi dan mencoba kembali koneksi.

Saya kira akar masalahnya adalah tidak ada aturan dasar tentang tanggung jawab siapa menunggu layanan siap. Tetapi bahkan jika ada, saya pikir agak tidak realistis untuk mengharapkan bahwa pengembang akan menambahkan koneksi database yang mencoba ulang ke setiap skrip inisialisasi. Skrip semacam itu sering kali diperlukan untuk menyiapkan volume data kosong yang baru saja dipasang (misalnya membuat database).

Masalah sebenarnya akan jauh lebih tidak menonjol jika Fig tidak selalu me-restart container yang terhubung (yaitu server database) saat me-restart container aplikasi. Saya tidak begitu tahu mengapa hal itu terjadi.

Masalah sebenarnya akan jauh lebih tidak menonjol jika Fig tidak selalu me-restart container yang terhubung (yaitu server database) saat me-restart container aplikasi. Saya tidak begitu tahu mengapa hal itu terjadi.

Sebenarnya itu tidak hanya _restart_ kontainer, itu _destroys dan membuat ulang_ mereka, karena ini adalah cara termudah untuk memastikan perubahan ke fig.yml diambil. Pada akhirnya kita harus menerapkan solusi yang lebih cerdas yang dapat membandingkan "konfigurasi saat ini" dengan "konfigurasi yang diinginkan" dan hanya membuat ulang apa yang telah berubah.

Kembali ke masalah awal, menurut saya tidak realistis mengharapkan container memiliki logika coba lagi koneksi - sangat penting untuk merancang sistem terdistribusi yang berfungsi. Jika skrip yang berbeda perlu membagikannya, itu harus difaktorkan menjadi executable (atau modul khusus bahasa jika Anda tidak menggunakan shell), jadi setiap skrip dapat memanggil waitfor db di bagian atas.

@kennu bagaimana dengan --no-recreate ? / cc @aanand

@aanand maksud saya komentar unrealisme dari sudut pandang Docker Hub sudah penuh dengan gambar yang diterbitkan yang mungkin tidak menangani koneksi ulang yang mencoba kembali dalam skrip inisialisasi mereka, dan itu akan menjadi usaha yang cukup untuk membuat semua orang menambahkannya. Tapi saya rasa itu bisa dilakukan jika Docker Inc menerbitkan semacam pedoman / persyaratan resmi.

Secara pribadi, saya lebih suka menjaga container / gambar tetap sederhana dan membiarkan sistem yang mendasarinya khawatir tentang menyelesaikan dependensi. Faktanya, kebijakan restart Docker mungkin sudah menyelesaikan semuanya (jika wadah aplikasi gagal terhubung ke database, itu akan restart dan mencoba lagi sampai database tersedia).

Tetapi mengandalkan kebijakan restart berarti itu harus diaktifkan secara default, atau jika tidak, orang menghabiskan berjam-jam untuk men-debug masalah (seperti yang baru saja saya lakukan). Misalnya, Kubernetes secara default menggunakan RestartPolicyAlways untuk pod.

ada kemajuan dalam hal ini? Saya ingin menggemakan bahwa mengharapkan semua gambar buruh pelabuhan berubah dan seluruh komunitas menerapkan praktik coba lagi koneksi tidak masuk akal. Fig adalah alat orkestrasi Docker dan masalahnya terletak pada urutan yang dilakukannya sehingga perubahan perlu dilakukan pada Fig, bukan Docker atau komunitas.

mengharapkan semua gambar pekerja galangan berubah dan seluruh komunitas menerapkan praktik coba lagi koneksi tidak wajar

Ini tidak berarti bahwa aplikasi perlu mencoba lagi karena buruh pelabuhan atau ara. Aplikasi harus tahan terhadap koneksi yang terputus karena jaringan tidak dapat diandalkan . Aplikasi apa pun seharusnya sudah dibuat dengan cara ini.

Saya pribadi tidak perlu menerapkan percobaan ulang di salah satu penampung saya, dan saya juga tidak memerlukan penundaan atau menunggu saat memulai. Saya percaya sebagian besar kasus masalah ini termasuk dalam dua kategori ini (penggunaan "coba lagi" saya mungkin tidak bagus di sini, maksud saya lebih dari itu akan membuat kembali koneksi jika koneksi ditutup, belum tentu polling untuk beberapa periode mencoba beberapa waktu).

Jika Anda memastikan bahwa semua inisialisasi terjadi selama fase "build", dan koneksi dibuat kembali pada permintaan berikutnya, Anda tidak perlu mencoba lagi (atau menunggu container lain untuk memulai). Jika koneksi dibuka dengan malas (ketika permintaan pertama dibuat), alih-alih dengan bersemangat (selama startup), saya curiga Anda tidak perlu mencoba lagi sama sekali.

masalahnya terletak pada urutan [ara] melakukan sesuatu

Saya tidak melihat ada penyebutan itu dalam diskusi ini sejauh ini. Fig memesan startup berdasarkan tautan yang ditentukan dalam konfigurasi, jadi itu harus selalu memulai kontainer dengan urutan yang benar. Dapatkah Anda memberikan kasus uji jika urutannya salah?

Saya harus setuju dengan @dnephin di sini. Tentu, akan lebih mudah jika compose / fig dapat melakukan sihir dan memeriksa ketersediaan layanan, namun, bagaimana perilaku yang diharapkan jika layanan tidak merespons? _Really_ itu bergantung pada persyaratan aplikasi / stack Anda. Dalam beberapa kasus, seluruh tumpukan harus dihancurkan dan diganti dengan yang baru, dalam kasus lain tumpukan failover harus digunakan. Banyak skenario lain yang bisa dipikirkan.

Compose / Fig tidak dapat membuat keputusan ini, dan layanan pemantauan harus menjadi tanggung jawab aplikasi yang berjalan di dalam container.

Saya ingin menunjukkan bahwa @dnephin hanya beruntung. Jika Anda membagi dua proses secara paralel, salah satunya akan terhubung ke port yang akan didengarkan oleh yang lain, pada dasarnya Anda memperkenalkan kondisi balapan; lotere untuk melihat proses mana yang menginisialisasi lebih cepat.

Saya juga ingin mengulangi contoh inisialisasi WordPress: Ini menjalankan skrip shell startup yang membuat database baru jika container MySQL belum memilikinya (ini tidak dapat dilakukan saat membangun image Docker, karena bergantung pada volume data yang dipasang secara eksternal). Skrip seperti itu menjadi jauh lebih kompleks jika harus membedakan kesalahan database umum dari kesalahan "database belum siap" dan menerapkan logika coba ulang yang waras dalam skrip shell. Saya menganggap kemungkinan besar penulis gambar tidak akan pernah benar-benar menguji skrip startup terhadap kondisi balapan tersebut.

Namun, kebijakan restart bawaan Docker menyediakan solusi untuk ini, jika Anda siap menerima bahwa kontainer secara sporadis gagal untuk memulai dan secara teratur mencetak kesalahan dalam log. (Dan jika Anda ingat untuk menyalakannya.)

Secara pribadi, saya akan membuat Things Just Work, dengan membuat Fig mendeteksi secara otomatis port kontainer mana yang terpapar ke kontainer yang ditautkan, melakukan ping sebelum memulai kontainer tertaut (dengan batas waktu yang waras), dan pada akhirnya memberikan pengaturan konfigurasi untuk mengganti / menonaktifkan fungsi ini.

ini tidak dapat dilakukan saat membangun image Docker, karena ini bergantung pada volume data yang dipasang secara eksternal

Benar. Pendekatan di sini adalah memulai hanya wadah database satu kali (jika diperlukan, dengan entrypoint / perintah yang berbeda), untuk menginisialisasi database, atau menggunakan wadah khusus data untuk database, yang dibuat dari gambar yang sama dengan wadah database itu sendiri.

Skrip seperti itu menjadi jauh lebih kompleks jika harus membedakan kesalahan database umum dari kesalahan "database belum siap"

Tulis / Gambar akan mengalami masalah yang sama di sana; Bagaimana cara memeriksa apakah MySQL sudah aktif, dan _accepting_ koneksi? (dan PostgreSQL, dan (_masukkan layanan Anda di sini_)). Juga, _di mana_ seharusnya "ping" dijalankan? Di dalam wadah Anda mulai, dari tuan rumah?

Sejauh yang saya tahu, gambar resmi WordPress menyertakan cek untuk melihat apakah MySQL menerima koneksi di docker-entrypoint.sh

@thaJeztah "Tambahkan beberapa logika coba lagi sederhana di PHP untuk kesalahan koneksi MySQL" yang dibuat oleh tianon 2 hari yang lalu - Bagus. :-) Siapa tahu, mungkin ini akan menjadi pendekatan standar, tapi saya masih ragu, terutama tentang penerapan coba ulang semacam ini yang sebenarnya telah diuji oleh semua pembuat gambar.

Tentang port ping - Saya tidak bisa mengatakan begitu saja implementasi yang optimal. Saya kira mungkin pemeriksaan koneksi sederhana dari penampung tertaut sementara dan mencoba lagi sambil mendapatkan ECONNREFUSED. Apa pun yang menyelesaikan 80% (atau mungkin 99%) masalah, sehingga pengguna tidak perlu menyelesaikannya sendiri lagi dan lagi setiap saat.

@kennu Ah! Terima kasih, tidak sadar itu baru saja ditambahkan, baru saja memeriksa skrip sekarang karena diskusi ini.

Untuk lebih jelasnya, saya memahami masalah yang Anda hadapi, tetapi saya tidak yakin Compose / Fig akan dapat menyelesaikannya dengan cara yang bersih yang bekerja untuk semua orang (dan andal). Saya memahami banyak gambar di registri tidak memiliki "perlindungan" untuk menangani masalah ini, tetapi saya ragu itu adalah tanggung jawab Compose / Fig untuk memperbaikinya.

Dengan demikian; Menurut saya _do_ akan menjadi hal yang baik untuk mendokumentasikan ini di bagian praktik terbaik Dockerfile .

Orang-orang harus diberi tahu tentang hal ini dan beberapa contoh harus ditambahkan untuk menggambarkan bagaimana menangani "pemadaman" layanan. Menyertakan tautan ke artikel WikiPedia yang disebutkan @dnephin (dan mungkin sumber lain) sebagai referensi.

Saya mengalami masalah yang sama dan menyukai ide ini dari @kennu

Personally, I would make Things Just Work, by making Fig autodetect which container ports are exposed to a linked container, ping them before starting the linked container (with a sane timeout), and ultimately provide a configuration setting to override/disable this functionality.

Saya pikir ini akan menyelesaikan banyak kasus penggunaan umum, seperti bagi saya ketika bergantung pada wadah mongodb resmi.

Saya setuju dengan @soupdiver. Saya juga mengalami masalah dalam hubungannya dengan penampung mongo, dan meskipun saya membuatnya berfungsi dengan skrip start.sh, skrip tersebut tidak terlalu dinamis dan menambahkan file lain yang perlu saya simpan di repo saya (saya hanya ingin memiliki Dockerfile dan docker-compose.yml di repo node saya). Alangkah baiknya jika ada beberapa cara untuk membuatnya Bekerja, tetapi saya pikir sesuatu yang sederhana seperti pengatur waktu tunggu tidak akan memotongnya dalam banyak kasus.

Ping IMO tidak cukup, karena koneksi jaringan dasar mungkin tersedia, tetapi layanan itu sendiri masih belum siap.
Ini terjadi pada gambar MySQL misalnya, menggunakan curl atau telnet untuk pemeriksaan koneksi pada port yang terbuka akan lebih aman, meskipun saya tidak tahu apakah itu cukup. Tetapi sebagian besar container tidak menginstal alat ini secara default.

Bisakah buruh pelabuhan atau ara menangani pemeriksaan ini?

Bisakah buruh pelabuhan atau ara menangani pemeriksaan ini?

Singkatnya: _no_. Untuk berbagai alasan;

  • Melakukan "ping" dari dalam penampung berarti menjalankan proses kedua. Fig / Compose tidak dapat secara otomatis memulai proses seperti itu, dan saya rasa Anda tidak ingin Fig / Compose memodifikasi container Anda dengan _installing_ software (seperti curl atau telnet) di dalamnya.
  • (Seperti yang saya sebutkan di komentar sebelumnya), setiap layanan memerlukan cara berbeda untuk memeriksa apakah menerima koneksi / siap digunakan. Beberapa layanan mungkin memerlukan kredensial atau sertifikat untuk _membangun_ koneksi. Fig / Compose tidak dapat secara otomatis menemukan cara melakukan itu.

dan saya rasa Anda tidak ingin Fig / Compose memodifikasi container Anda dengan menginstal software (seperti curl atau telnet) di dalamnya.

Tidak, tentu tidak.

Fig / Compose tidak dapat secara otomatis menemukan cara melakukan itu.

Bukan penemuan. Saya berpikir lebih banyak tentang instruksi untuk ara atau buruh pelabuhan, bagaimana memeriksanya, mis.

web:
    image: nginx
    link: db
db:
   is_available: "curl DB_TCP_ADDR:DB_TCP_PORT"

Perintah telnet akan dijalankan pada host-docker, bukan dalam wadah.
Tetapi saya hanya berpikir keras, saya tahu ini bukanlah solusi yang tepat. Tetapi cara saat ini menggunakan skrip pemeriksaan khusus untuk penampung dapat ditingkatkan.

Perintah telnet akan dijalankan di host-buruh pelabuhan, bukan di dalam wadah.

Kemudian curl atau <name a tool that's needed> harus diinstal pada host. Ini bahkan dapat memiliki masalah keamanan yang besar (mis. Seseorang ingin menjadi lucu dan menggunakan is_available: "rm -rf /" ). Selain itu, bisa mengakses database dari _host_ bukan jaminan bahwa database juga bisa diakses dari dalam container.

Tapi saya hanya berpikir keras, ...

Saya tahu, dan saya menghargainya. Bayangkan tidak ada cara yang dapat diandalkan untuk mengotomatiskan ini, atau akan melayani sebagian besar kasus penggunaan. Dalam banyak kasus, Anda akan berakhir dengan sesuatu yang kompleks (ambil contoh curl ; berapa lama harus mencoba untuk terhubung? Coba lagi?). Kompleksitas seperti itu lebih baik untuk dipindahkan ke dalam container, yang juga berguna jika container dimulai dengan Docker, bukan Fig / Compose.

@ thaJeztah Saya setuju dengan Anda. Dan kemungkinan besar tidak akan ada solusi yang 100%.

Saya akan mengulangi saran yang saya buat sebelumnya: Ini akan cukup bagi saya jika saya dapat menyatakan di fig.yml "tunggu kontainer ini keluar sebelum menjalankan kontainer lain ini".

Ini akan memungkinkan saya untuk membuat wadah yang tahu bagaimana menunggu semua dependensinya - periksa port, inisialisasi database, apa pun - dan akan membutuhkan pengetahuan ara sesedikit mungkin.

Saya akan melihatnya dikonfigurasi sebagai sesuatu seperti:

“” "
aplikasi:
tautan:
- db: db
prasyarat:
- runthisfirst

runthisfirst:
tautan:
- db: db
"" "

runthisfirst memiliki tautan yang berarti database dimulai sehingga dapat memeriksa akses. aplikasi hanya akan berjalan setelah runthisfirst telah keluar (poin bonus jika runthisfirst harus berhasil keluar).

Apakah ini layak sebagai jawaban?

KJL

Pada 10 Feb 2015, pada 05:28, Tobias Munk [email protected] menulis:

@thaJeztah https://github.com/thaJeztah Saya sangat setuju dengan Anda. Dan kemungkinan besar tidak akan ada solusi yang 100%.

-
Balas email ini secara langsung atau lihat di GitHub https://github.com/docker/fig/issues/374#issuecomment -73561930.

Saya baru saja mencoba memigrasi peluncur skrip shell saya dan mengalami masalah ini. Akan lebih baik meskipun hanya menambahkan tombol tidur / tunggu sederhana yang hanya tidur selama beberapa detik sebelum meluncurkan penampung berikutnya.

db:
  image: tutum/mysql:5.6
  sleep: 10
app:
  link:
    - db:db

Saya benar-benar tidak suka ini karena sejumlah alasan.

a) Saya pikir itu tempat yang salah untuk ini
b) Berapa lama Anda tidur?
c) Bagaimana jika batas waktu tidak cukup lama?

Selain dari masalah yang sudah jelas, saya benar-benar tidak berpikir
infrastruktur harus peduli apa aplikasinya
adalah dan sebaliknya. IHMO aplikasi harus ditulis
lebih toleran dan / atau lebih pintar tentang persyaratannya sendiri.

Itu dikatakan aplikasi yang ada dan aplikasi warisan
akan membutuhkan sesuatu - Tapi itu mungkin harus lebih lama
baris dari:

a docker-compose.yml :

db:
  image: tutum/mysql:5.6
app:
  wait: db
  link:
    - db:db

Di mana wait menunggu layanan "terekspos" di db tersedia.

Masalahnya adalah bagaimana Anda menentukannya?

Dalam kasus yang paling sederhana Anda menunggu sampai Anda berhasil membuka
koneksi tcp atau udp ke layanan yang diekspos.

Ini mungkin berlebihan untuk masalah ini tetapi apa yang akan menjadi solusi yang bagus adalah jika buruh pelabuhan menyediakan sistem pemicu peristiwa di mana Anda dapat memulai pemicu dari satu wadah yang menghasilkan semacam callback di wadah lain. Dalam kasus menunggu mengimpor data ke database MySQL sebelum memulai layanan lain, hanya memantau apakah port tersedia tidak cukup.

Memiliki skrip titik entri menyetel peringatan ke Docker dari dalam wadah (setel variabel lingkungan yang telah ditentukan sebelumnya misalnya) yang memicu peristiwa di wadah lain (mungkin pengaturan variabel lingkungan tersinkronisasi yang sama) akan memungkinkan skrip di kedua sisi untuk mengetahui kapan tugas selesai.

Tentu saja kami dapat menyiapkan server soket kami sendiri atau cara lain, tetapi itu membosankan untuk menyelesaikan masalah orkestrasi kontainer.

@aandan saya _almost_ memiliki sesuatu yang berfungsi menggunakan pendekatan menunggu Anda sebagai titik awal. Namun, ada hal lain yang terjadi antara docker-compose run dan docker run di mana yang pertama tampak menggantung sementara yang kemudian berfungsi dengan baik.

contoh docker-compose.yml:

db:
  image: postgres
  ports:
    - "5432"
es:
  image: dockerfile/elasticsearch
  ports:
    - "9200"
wait:
  image: n3llyb0y/wait
  environment:
    PORTS: "5432 9200"
  links:
    - es
    - db

lalu gunakan ...

docker-compose run wait

Namun ini tidak akan terjadi. Layanan tertaut mulai dan sepertinya kita akan menunggu hanya untuk tersedak (setidaknya di dalam virtualbox env saya. Saya mendapatkan loop nc dan kami mendapatkan satu titik lalu ... tidak ada).

Namun, dengan layanan tertaut yang berjalan, saya dapat menggunakan metode ini (yang pada dasarnya adalah apa yang telah saya lakukan untuk build CI kami)

docker run -e PORTS="5432 9200" --links service_db_1:wait1 --links service_es_1:wait2 n3llyb0y/wait

Rasanya docker-compose run harus bekerja dengan cara yang sama. Perbedaannya adalah ketika menggunakan docker-compose run dengan detach flag -d Anda tidak mendapatkan keuntungan menunggu karena latar belakang kontainer menunggu dan saya pikir (saat ini) bahwa tidak menggunakan bendera menyebabkan menunggu untuk tersedak layanan non-latar belakang lainnya. Saya akan melihat lebih dekat

Setelah sedikit coba-coba, tampaknya pendekatan di atas berhasil! Hanya saja basis busybox tidak memiliki utilitas netcat yang berfungsi dengan baik. Versi saya yang dimodifikasi dari utilitas @aanand wait tidak berfungsi melawan docker-compose 1.1.0 saat menggunakan docker-compose run <util label> alih-alih docker-compose up . Contoh penggunaan di link.

Tidak yakin apakah itu dapat menangani situasi rantai sesuai pertanyaan aslinya. Mungkin tidak.

Biarkan aku tahu apa yang Anda pikirkan.

Ini adalah masalah yang sangat menarik. Saya pikir akan sangat menarik untuk memiliki cara satu wadah menunggu sampai yang lain siap. Tapi seperti yang dikatakan semua orang, apa artinya siap? Dalam kasus saya, saya memiliki wadah untuk MySQL, wadah lain yang mengelola cadangannya dan juga bertanggung jawab untuk mengimpor basis data awal, dan kemudian wadah untuk setiap aplikasi yang membutuhkan basis data. Jelas bahwa menunggu port dibuka tidaklah cukup. Pertama, wadah mysql harus dijalankan dan selanjutnya harus menunggu hingga layanan mysql siap digunakan, bukan sebelumnya. Untuk mendapatkannya, saya perlu mengimplementasikan skrip sederhana untuk dieksekusi saat reboot yang menggunakan fungsionalitas docker exec . Pada dasarnya, pseudo-code akan menjadi seperti ini:

run mysql
waitUntil "docker exec -t mysql mysql -u root -prootpass database -e \"show tables\""
run mysql-backup
waitUntil "docker exec -t mysql mysql -u root -prootpass database -e \"describe my_table\""
run web1
waitUntil "dexec web1 curl localhost:9000 | grep '<h1>Home</h1>'"
run web2
waitUntil "dexec web2 curl localhost:9000 | grep '<h1>Home</h1>'"
run nginx

Di mana waitUntil function memiliki loop dengan batas waktu yang sama dengan perintah docker exec … dan memeriksa apakah kode keluarnya 0.

Dengan itu saya yakinkan bahwa setiap container menunggu hingga dependensinya siap digunakan.

Jadi saya pikir ini bisa menjadi opsi untuk diintegrasikan dalam utilitas compose. Mungkin sesuatu seperti itu, di mana wait_until mendeklarasikan daftar dependensi lain (container) dan menunggu masing-masing sampai mereka merespon perintah yang sesuai (atau mungkin dengan pola opsional atau regex untuk memeriksa apakah hasilnya cocok dengan sesuatu yang Anda harapkan, meskipun menggunakan perintah grep sudah cukup).

mysql:
  image: mysql
  ...
mysql-backup:
  links:
   - mysql
  wait_until:
   - mysql: mysql -u root -prootpass database -e "show tables"
  ...
web1:
  links:
   - mysql
  wait_until:
   - mysql: mysql -u root -prootpass database -e "describe my_table"
  ...
web2:
  links:
   - mysql
  wait_until:
   - mysql: mysql -u root -prootpass database -e "describe my_table"
  ...
nginx:
  links:
   - web1
   - web2
  wait_until:
   - web1: curl localhost:9000 | grep '<h1>Home</h1>'
   - web2: curl localhost:9000 | grep '<h1>Home</h1>'
  ...

Apa bukan cara yang sederhana untuk menunggu pelabuhan seperti itu?
http://docs.azk.io/en/azkfilejs/wait.html#

@robsonpeixoto : Menunggu port tidaklah cukup untuk banyak kasus penggunaan. Misalnya, Anda melakukan seeding database dengan data saat pembuatan dan tidak ingin server web memulai dan menyambungkannya hingga operasi data selesai. Porta akan terbuka sepanjang waktu sehingga tidak akan memblokir server web untuk memulai.

Sesuatu seperti WaitCondition AWS CloudFormation akan menyenangkan. http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-waitcondition.html

+1 Saya mengalami masalah yang sama saat menggunakan Docker untuk menguji aplikasi Rails saya yang bergantung pada MySQL

+1 Saya juga memiliki masalah ini. Saya suka ide @adrianhurt , di mana Anda benar-benar menyediakan kondisi untuk dievaluasi untuk menentukan apakah penantiannya sudah selesai. Dengan cara itu Anda masih memiliki deklaratif yml yang bagus, dan Anda tidak perlu memiliki definisi sembarangan tentang "ready".

+1

Saya telah membuka tab ini untuk sementara waktu: http://crosbymichael.com/docker-events.html ... sepertinya relevan

+1

1 untuk batas waktu sederhana

1 untuk kondisi siap

+1

Saya menyelesaikan ini dengan sangat andal pada level aplikasi sejak beberapa saat, seperti yang direkomendasikan di utas ini.

Hanya untuk memberi Anda gambaran bagaimana ini dapat diterapkan untuk MySQL + PHP, inilah kode saya.

Dari igorw / retry :)

Karena jaringan dapat diandalkan, segala sesuatunya harus selalu berfungsi. Apakah saya benar? Untuk kasus yang tidak terjadi, coba lagi.

+1

@ schmunk42 Bagus - Saya suka itu adalah contoh yang baik untuk membangun koneksi dan melakukan operasi pengaturan database idempoten.

Mungkin bagus untuk membuat (beberapa) contoh dasar untuk dimasukkan dalam dokumen, untuk kasus yang berbeda, misalnya NodeJS, Ruby, PHP.

+1, setidaknya harus memberikan beberapa opsi untuk menambahkan beberapa penundaan sebelum penampung berhasil dimulai.

+1

Cara mengatasi masalah saat Anda mencoba menghubungkan layanan yang bukan kode Anda.
Misalnya, jika a memiliki layanan Service dan database InfluxDB . Services membutuhkan InfluxDB dan InfluxDB memiliki startup yang lambat.

Bagaimana docker-compose menunggu InfluxDB siap?

Saya kodenya adalah milik saya, saya bisa menyelesaikannya dengan mencoba lagi. Tapi untuk aplikasi ketiga saya tidak bisa mengubah kodenya.

@robsonpeixoto ada beberapa contoh di tiket ini dengan netcat atau cara serupa. Anda dapat melihat contoh MySQL saya di tiket lain: https://github.com/docker/docker/issues/7445#issuecomment -101523662

Itulah alasan saya pikir setiap wadah harus memiliki kemampuan opsional untuk menunjukkan kesiapannya sendiri. Untuk DB, misalnya, saya ingin menunggu hingga layanan benar-benar siap, bukan saat proses dibuat. Saya menyelesaikan ini dengan pemeriksaan khusus dengan docker exec dan memeriksa apakah itu dapat menyelesaikan kueri sederhana, misalnya.

Beberapa tanda opsional untuk docker run untuk menunjukkan perintah pemeriksaan internal akan bagus untuk nanti menautkannya dari penampung lain menggunakan tanda khusus untuk tautan tersebut.

Sesuatu seperti:

$ sudo docker run -d --name db training/postgres --readiness-check /bin/sh -c "is_ready.sh"
$ sudo docker run -d -P --name web --link db:db --wait-for-readiness db training/webapp python app.py

Dimana is_ready.sh adalah tes boolean sederhana yang bertanggung jawab atas keputusan kapan wadah dianggap siap.

+1

@ schmunk42 kutipan yang bagus!

+1

+1

+1

+1

+1

+1

+1

+1

+1

Sebenarnya saya berubah pikiran tentang ini, jadi -1

Lebih masuk akal bagi penampung Anda untuk memeriksa apakah layanan pihak ketiga tersedia, dan ini mudah dilakukan dengan skrip bash wrapper kecil yang menggunakan nc misalnya.

Mengandalkan penundaan memang menggoda, tetapi ini solusi yang buruk karena:

  • Penampung Anda akan _selalu_ menunggu X detik sebelum siap.
  • X detik mungkin masih tidak cukup dalam beberapa kasus (mis. I / O atau CPU yang berat pada host), jadi penampung Anda masih belum aman dari kegagalan.
  • Tidak ada strategi yang gagal.

Lebih baik mengandalkan penulisan skrip bash wrapper karena:

  • Wadah Anda siap sesegera mungkin.
  • Anda dapat menerapkan strategi kegagalan apa pun, misalnya mencoba 10 kali kemudian gagal, mencoba selamanya, dll. Anda bahkan dapat menerapkan penundaan itu sendiri dengan tidur sebelum mencoba!

Membaca melalui pemikiran ini saya melihat bahwa tidak ada yang menyebutkan rahasia. Saya mencoba menggunakan container khusus data yang meminta rahasia setelah dijalankan. Masalah yang saya miliki: Jika rahasia saya membutuhkan waktu terlalu lama untuk dikirim / didekripsi, maka container dependen saya gagal karena data yang diharapkan tidak ada. Saya tidak dapat benar-benar menggunakan metode "letakkan semuanya dengan baik di wadah sebelum Anda menjalankannya" karena itu adalah rahasia.

Saya tahu ada beberapa ambiguitas seputar penampung khusus data dalam penulisan karena konteks kode pengembalian, tetapi adakah cara yang lebih baik untuk melakukan ini?

Demikian pula mengubah pikiran saya tentang ini, -1. Pendekatan @dnephin sepenuhnya benar. Jika _application_ Anda bergantung pada _service_, aplikasi itu sendiri harus mampu menangani tidak tersedianya layanan itu dengan baik (mis. Membangun kembali koneksi). Seharusnya tidak berupa skrip bash wrapper atau logika di Compose atau Docker, ini adalah tanggung jawab aplikasi itu sendiri. Apa pun yang tidak ada di level aplikasi juga hanya akan berfungsi saat inisialisasi; jika layanan itu mati, skrip pembungkus atau sesuatu tidak akan dijalankan.

Sekarang jika kita bisa membuat pengembang aplikasi / perpustakaan / kerangka kerja menyadari dan mendukung tanggung jawab ini, itu akan luar biasa.

Sulit untuk dilakukan mengingat pendekatan yang akan Anda ambil melibatkan sideload daemon lain yang tidak disarankan. Untuk contoh saya di mana saya memiliki aplikasi rel yang mencoba untuk terhubung ke database MySQL sementara aplikasi rel lain sedang bermigrasi dan melakukan seeding DB pada startup awal, bagi saya untuk membuat aplikasi rel tahu untuk tidak mencoba menggunakan DB, saya juga akan harus memodifikasi pustaka ActiveRecord (tidak akan terjadi) atau menjalankan skrip yang terus memeriksa untuk melihat apakah DB telah dimigrasi dan di-seed. Tetapi bagaimana saya tahu pasti tanpa mengetahui data apa yang seharusnya ada di sana dan / atau memiliki beberapa skrip yang berjalan pada sistem yang menyemai DB untuk memberi tahu yang lain untuk terhubung dengannya.

Mungkin saya kehilangan solusi yang jelas, tetapi jawaban Anda tentang "pengembang harus dapat menangani ini dalam kode mereka sendiri" rusak saat Anda menggunakan pustaka dari rak dan saat Anda tidak "seharusnya" memasukkan daemon ke dalam sebuah wadah.

@mattwallington Saya bahkan tidak yakin bagaimana Compose akan memberikan solusi untuk situasi itu ...
Itu juga sangat spesifik yang akan membuatnya semakin sulit untuk dibuat oleh Compose. Saya akan membaca beberapa tip @dnephin di atas tentang inisialisasi / migrasi / penyemaian karena itu dapat membantu kasus Anda.

Saya pikir Anda melewatkan poin dari baris terakhir saya, banyak perpustakaan di luar rak tidak berfungsi _ tepat_ karena belum dibangun dengan kokoh. Tidak ada solusi ajaib yang dapat menyelesaikan semua ini yang dapat diterapkan oleh Compose.

Dimengerti. Saran saya sebelumnya yang akan bekerja untuk banyak kasus penggunaan ini adalah memiliki variabel lingkungan bersama antar kontainer. Satu sisi dapat mengunci polling variabel dan sisi lain dapat melakukan tindakan dan kemudian mengatur variabel.

+1 Ide @mattwallington tentang variabel lingkungan bersama antar kontainer

Terima kasih. Ini sederhana (di tingkat produk. Saya tidak tahu apa yang akan diambil dari sisi pengembangan karena saya belum melihat kodenya) tetapi itu akan menyelesaikan banyak masalah ini dan mungkin banyak masalah lainnya karena tidak spesifik untuk masalah ini.

Tetapi bagaimana saya tahu pasti tanpa mengetahui data apa yang seharusnya ada di sana dan / atau memiliki beberapa skrip yang berjalan pada sistem yang menyemai DB untuk memberi tahu yang lain untuk terhubung dengannya.

@mattwallington : periksa nomor migrasi di tabel skema. Jika nomornya benar, Anda tahu migrasi berjalan.

Seharusnya tidak berupa skrip bash wrapper atau logika di Compose atau Docker, ini adalah tanggung jawab aplikasi itu sendiri. Apa pun yang tidak ada di level aplikasi juga hanya akan berfungsi saat inisialisasi; jika layanan itu mati, skrip pembungkus atau sesuatu tidak akan dijalankan.

@ agilgur5 : ya Saya setuju ini akan ditangani oleh aplikasi, tetapi skrip bash adalah solusi sederhana untuk menangani aplikasi yang tidak dikodekan dengan cara itu, misalnya dengan memulai ulang aplikasi ketika layanan tidak tersedia.

Argumen dapat dibuat sepanjang hari tentang apa yang harus atau dapat dilakukan pada tingkat aplikasi, tetapi daripada mengharapkan setiap aplikasi di pasar untuk menangani hal ini dan menjadi luar biasa dalam pemulihan diri (tidak mungkin) mengapa kita begitu menentang penambahan beberapa fitur yang dapat menyelesaikannya masalah ini untuk aplikasi yang berjalan di buruh pelabuhan terlepas dari bagaimana aplikasi pihak ketiga ditulis atau apa yang HARUS mereka lakukan tetapi tidak akan dilakukan. Inilah yang kami kendalikan. Mari kita selesaikan masalah daripada memutuskan siapa yang harus menyelesaikannya karena kita tidak memiliki kendali atas itu.

Saya setuju dengan @mattwallington. Anda dapat memerlukan upaya ekstra ini untuk pemulihan mandiri tingkat aplikasi dari setiap developer dari setiap gambar container, tetapi sebagian besar dari mereka terlalu cuek atau terlalu sibuk untuk menerapkan dan mengujinya dengan hati-hati. Hasil akhirnya adalah beberapa kontainer tahu bagaimana memulihkan diri sementara banyak yang tidak. Dan sebagai pengguna, Anda tidak akan memiliki alat apa pun untuk mengelola yang tidak.

Sebuah Ide yang baru saja terlintas di benak saya: Daripada menyelesaikan masalah dengan menunda startup container, Compose dapat mencoba memulihkan container yang gagal.

Sesuatu seperti recover: auto akan memulai ulang penampung yang gagal sebanyak 5 kali dalam 2, 4, 8, 16 dan 32 detik dan kemudian menyerah sepenuhnya.

Adakah orang yang _pikir_ tentang gagasan wadah ketergantungan wadah?

Sebagai contoh:

`` #! yml
db:
gambar: mysql

tunggu:
tautan:
- db
volume:
- /var/lib/docker.sock:/docker.sock
- $ {PWD} /docker-compose.yml:/docker-compose.yml
perintah: aplikasi docker-compose up -d

aplikasi:
gambar: myuser / myapp
tautan:
- db
``

Ide dasarnya di sini adalah Anda _menyelesaikan_ masalah container yang tidak memiliki mekanisme pemulihan sendiri dengan membuat layanan khusus yang dapat digunakan kembali yang dapat dipublikasikan ke Docker Hub yang kemudian dapat dimasukkan semua orang ke dalam komposisinya.

Saya _bahkan bersedia untuk membuat prototipe layanan / wadah / gambar semacam itu dan membiarkan orang lain bermain dengan ini untuk melihat bagaimana tarifnya ...

@prologic Masalah dengan ketergantungan adalah, bagaimana cara memastikan bahwa layanan yang ingin Anda

Container db mungkin merespons ke ping tetapi melakukan pembersihan pra peluncuran / menginisialisasi database sebelum tersedia untuk perintah mysql / psql .

Dapatkah pengujian tersebut didefinisikan dengan cara yang dapat dikonfigurasi dan / atau disertakan dalam skrip ke layanan tipe waitfor dapat digunakan kembali?

IMHO, ini adalah masalah yang sangat umum dan setiap orang memiliki persyaratan khusus masing-masing. Seperti yang dikomentari sebelumnya dalam masalah ini, saya pikir buruh pelabuhan dapat (dan harus) menyediakan cara bagi wadah untuk menentukan perintah sederhana untuk memeriksa kesiapannya sendiri. Tentunya kita sebagai developer harus secara spesifik menunjukkan bagaimana cara mengecek kesiapan tiap container.

Beberapa flag opsional untuk menjalankan buruh pelabuhan untuk menunjukkan perintah pemeriksaan internal akan bagus untuk nanti menautkannya dari penampung lain menggunakan tanda khusus untuk tautan tersebut.

Sesuatu seperti:

$ sudo docker run -d --name db training/postgres --readiness-check /bin/sh -c "is_ready.sh"
$ sudo docker run -d -P --name web --link db:db --wait-for-readiness db training/webapp python 

Di mana is_ready.sh adalah pengujian boolean sederhana yang bertanggung jawab atas keputusan kapan container dianggap siap.

Ini juga bisa menjadi perintah bagi container untuk memeriksa kesiapannya secara manual.

Di mana is_ready.sh adalah pengujian boolean sederhana yang bertanggung jawab atas keputusan kapan container dianggap siap.

yang berarti bahwa setiap pengembang harus menyiapkan gambar / penampungnya untuk menyertakan _something_ yang dapat digunakan untuk memeriksa apakah penampung sudah siap.

Yang membawa kita kembali ke kotak 1; developer adalah orang yang bertanggung jawab untuk membuat container mereka tahan terhadap waktu mati / startup layanan, karena hanya merekalah yang dapat mengetahui "apa" artinya bagi situasi mereka?

Atau saya sedang melihat sesuatu di sini?

Saya setuju. Tanggung jawab terletak pada pengembang / wadah / layanan

Pada hari Kamis, 30 Juli 2015, Sebastiaan van Stijn [email protected]
menulis:

Di mana is_ready.sh adalah pengujian boolean sederhana yang bertanggung jawab atas
keputusan kapan wadah dianggap siap.

yang berarti bahwa setiap pengembang harus menyiapkan gambar / wadahnya
sertakan _something_ yang dapat digunakan untuk memeriksa apakah wadahnya
siap.

Yang membawa kita kembali ke kotak 1; pengembang adalah yang bertanggung jawab
membuat penampung mereka tahan terhadap pemadaman layanan / waktu mulai, karena
mereka adalah satu-satunya yang bisa mengatakan "apa" artinya bagi situasi mereka?

Atau saya sedang melihat sesuatu di sini?

-
Balas email ini secara langsung atau lihat di GitHub
https://github.com/docker/compose/issues/374#issuecomment -126278215.

James Mills / prologic

E: [email protected]
W: prologic.shortcircuit.net.au

Ya tentu saja. Bagi saya, satu-satunya yang benar-benar tahu kapan wadahnya siap adalah wadahnya sendiri. Docker tidak tahu apa-apa tentang konten sebuah kontainer. Ini kotak hitam. Satu-satunya hal yang dapat dilakukan adalah meminta penampung (dengan tindakan kustom yang ditentukan saat Anda ingin menjalankan, seperti yang saya usulkan, atau cara umum lainnya untuk mengujinya). Dan jelas pengembang adalah satu-satunya yang tahu apa yang dia butuhkan dan isi kotak hitam itu.

Ya itu benar!

Pada hari Kamis, 30 Juli 2015, adrianhurt [email protected] menulis:

Ya tentu saja. Bagi saya, satu-satunya yang benar-benar tahu kapan wadah itu
siap adalah wadahnya sendiri. Docker tidak tahu apa-apa tentang konten
sebuah wadah. Ini kotak hitam. Satu-satunya hal yang dapat dilakukannya adalah menanyakan
container (dengan tindakan kustom yang ditentukan saat Anda ingin menjalankannya, seperti I
diusulkan, atau cara umum lainnya untuk mengujinya). Dan jelas pengembangnya
adalah satu-satunya yang tahu apa yang dia butuhkan dan isi kotak hitam itu.

-
Balas email ini secara langsung atau lihat di GitHub
https://github.com/docker/compose/issues/374#issuecomment -126285056.

James Mills / prologic

E: [email protected]
W: prologic.shortcircuit.net.au

Oke - demi semua perangkat lunak dalam pengembangan atau warisan di luar sana yang tidak dapat menangani kegagalan jaringan, anggap saja kita ingin menyelesaikan masalah ini. Saya tidak mengatakan kami melakukannya, saya hanya ingin merasakan sintaks, semantik, dan kompleksitas.

Seperangkat persyaratan minimal tampaknya adalah:

  • Saya ingin Compose menunggu untuk memulai layanan hingga layanan lain "siap".
  • Saya ingin mendefinisikan "siap" karena "menerima koneksi TCP pada port X", atau yang lainnya.

Anggap juga bahwa health check tidak akan berhasil masuk ke Docker untuk sementara waktu.

Saya ingin tahu apakah ini bisa diselesaikan dalam kasus umum dengan memungkinkan untuk _menunggu kontainer layanan lain untuk keluar_. Anda kemudian dapat menulis cek kesehatan Anda hanya sebagai layanan lain.

web:
  image: mywebapp
  links: ["db"]
  wait_for: ["db_wait"]

db_wait:
  image: netcat
  links: ["db"]
  command: sh -c "while ! nc -w 1 -z db 5432; do sleep 1; done"

db:
  image: postgres

Jika Anda menginginkan semacam health check kustom, tentukan di layanan "tunggu". Di sini, db_wait hanya akan keluar setelah mytable ada di database mydb :

db_wait:
  image: postgres
  links: ["db"]
  command: sh -c "while ! psql --host db --dbname mydb -c "\d mytable"; do sleep 1; done"

Jika Anda memiliki skrip persiapan db untuk dijalankan terlebih dahulu, Anda dapat membuat hal itu menunggu:

web:
  image: mywebapp
  links: ["db"]
  wait_for: ["prepare_db"]

prepare_db:
  image: prepare_db
  links: ["db"]
  command: ./prepare.sh

db:
  image: postgres

Kasus pertama (tunggu hingga penampung menerima koneksi TCP) mungkin cukup umum sehingga layak untuk didukung secara langsung.

web:
  image: mywebapp
  links: ["db"]
  wait_for_tcp: ["db:5432"]

db:
  image: postgres

Ada implikasi tersembunyi dalam semua ini: docker-compose up -d harus diblokir saat pemeriksaan kesehatan perantara atau layanan persiapan sedang berjalan, sehingga dapat memulai layanan konsumen setelah selesai.

Iya. Namun, menurut saya, buruh pelabuhan itu sendiri harus menyediakan cara untuk menentukan kapan sebuah wadah siap, dan kemudian bisa mengelolanya. Kami kemudian dapat mengangkat masalah baru langsung di buruh pelabuhan. Bagi saya, itu bisa seperti:

web:
  image: mywebapp
  links: ["db"]
  wait_for: ["db"]

db:
  image: postgres
  ready_when: sh -c "while ! psql --host db --dbname mydb -c "\d mytable"; do sleep 1; done"

Kemudian, tidak perlu membuat layanan baru sebagai solusinya

Sepakat. Berikan fleksibilitas kepada pengembang. Selain itu, menjeda penampung mungkin bukan hal yang dibutuhkan oleh pengembang untuk dilakukan penampung itu sementara mereka menunggu. Mungkin ada beberapa initnya sendiri yang perlu terjadi tetapi kemudian menunggu db siap untuk koneksi. Jadi jika itu adalah variabel env bersama yang sederhana, ini memungkinkan pengembang untuk menggunakannya sesuai kebutuhan.

Bagaimana variabel lingkungan bersama diperbarui? Sejauh yang saya tahu, Anda tidak dapat membuat perubahan pada serangkaian proses variabel lingkungan setelah dimulai.

Anda dapat mengubahnya di mis. Sesi bash, tetapi mereka tidak akan disebarluaskan di semua lapisan lainnya.

Untuk melakukan itu, perubahan harus dilakukan dan penampung dimulai ulang. Ini sangat tidak berguna dalam skenario ini.

Terlebih lagi, bahkan jika variabel dapat berubah, proses dalam penampung perlu mengetahui untuk melakukan polling, yang menjadikan ini bukan solusi untuk perangkat lunak lama tempat fitur ini berpura-pura.

Karena kita benar-benar hanya berbicara tentang menyelesaikan masalah ini untuk kontainer lama di lingkungan pengembangan, saya pikir ini dapat diselesaikan sebagai alat yang berada di atas menulis docker-compose ps -s (daftar layanan dalam urutan ketergantungan, # 1077).

Dengan dua perintah ini, alat dapat ditulis yang melakukan hal seperti ini:

  1. Jalankan docker-compose ps -s untuk mendapatkan daftar nama layanan dalam urutan ketergantungan
  2. Jalankan docker-compose up -d --no-recreate <first service from the list>
  3. Jalankan perintah "healthcheck" untuk layanan tersebut hingga layanan tersebut berfungsi atau mencapai batas waktu. Ini bisa berupa permintaan HTTP, atau panggilan docker exec
  4. Ulangi 2 dan 3 untuk setiap layanan dalam daftar
  5. Jalankan docker-compose logs (atau jangan jika -d sudah lewat)

Dengan cara ini, konfigurasi "healthcheck" dan "wait for" dapat bersifat eksternal untuk dibuat, tetapi menurut saya developer tidak diwajibkan untuk memberikan apa pun di atas yang diperlukan jika itu diterapkan sebagai bagian dari penulisan itu sendiri.

Ada alasan mengapa ini tidak berhasil?

Saya senang kami telah membatasi cakupan ke penampung lama, itu jauh lebih masuk akal: +1:

@dnephin Saya pikir itu bagus dari perspektif langsung bahwa itu fleksibel dan bahwa Compose tidak harus memiliki dukungan bawaan untuk kontainer lama, tetapi saya melihat masalah langsung yang mirip dengan apa yang dijelaskan

+1

untuk dapat menentukan dependensi dalam file tulis-galangan ...

... tidak menggunakan tautan (karena tidak kompatibel dengan net = host). Saya akan mengira itu adalah pekerjaan atau setidaknya perhatian dari alat manajemen multi-kontainer untuk mengetahui urutan apa yang harus dimulai, seperti boneka memiliki pohon ketergantungannya sendiri, tetapi terkadang pengguna tahu yang terbaik dan dapat menimpa. Membaca semua hal di atas, menurut saya, satu-satunya kesulitan adalah memutuskan kapan wadah "naik" sehingga wadah berikutnya dalam rantai ketergantungan dapat dimulai. Ini bisa menjadi mekanisme yang persis sama dengan mekanisme tautan (untuk saat ini) - apa pun lebih baik daripada tidak sama sekali. Nanti, klarifikasi tentang "memenuhi ketergantungan" dapat ditentukan oleh file tulis-buruh pelabuhan, misalnya - ketergantungan ini penting bahwa penampung sedang berjalan

depends_on:
  container: foo
  requires: running

atau ketergantungan ini penting bahwa wadah port TCP mendengarkan.

depends_on:
  container: foo
  requires: listening

Mengatakan itu adalah tugas dari beberapa alat atau skrip eksternal di atas docker-compose sama saja dengan mengatakan bahwa docker-compose tidak memiliki kepentingan atau tanggung jawab nyata untuk orkestrasi menjalankan 2 atau lebih kontainer pada mesin yang sama. Jadi apa tujuannya?

Saya akan mengira itu adalah pekerjaan atau setidaknya perhatian dari alat manajemen multi-kontainer untuk mengetahui pesanan apa yang harus dimulai

Tidak, belum tentu. Untuk alasan yang sudah dijelaskan beberapa kali di utas ini, saya yakin hanya ada dua alasan untuk menyerahkan pekerjaan ini ke alat manajemen kontainer:

  1. Anda menjalankan gambar container off-the-shelf yang tidak tahan terhadap tidak tersedianya layanan upstream tempat mereka bergantung, dan untuk alasan teknis atau bisnis Anda tidak dapat mengubah atau memperluasnya.
  2. Anda menjalankan perangkat lunak murni dalam lingkungan pengembangan, bukan produksi, dan Anda memiliki hal-hal yang lebih baik untuk dihabiskan daripada menerapkan ketahanan.

Namun, jika Anda memiliki kendali atas perangkat lunak Anda dan Anda berencana untuk menerapkannya ke produksi, Anda tidak dapat berharap untuk mengandalkan alat eksternal yang hanya memulai hal-hal dalam urutan yang benar, bahkan jika Anda telah menentukan kondisi kesiapan Anda dengan cermat. Ini bukan solusi untuk masalah mendasar, dan sistem Anda akan gagal saat ada gangguan jaringan. Paling banter, Anda harus secara otomatis memulai ulang semua penampung antarmuka web Anda setiap kali itu terjadi, dan saya tidak dapat melihat bahwa jumlah waktu henti yang dapat diterima untuk siapa pun.

Setuju dengan Anda bahwa perangkat lunak yang ditulis dengan baik akan mengatasi pemadaman jaringan. Saya pikir kami berdua setuju bahwa tidak semua perangkat lunak ditulis dengan baik, dan pengembang tidak selalu memikirkan semua kemungkinan penggunaan.

Mungkin saya ingin menjalankan wadah klien yang menjalankan JVM, dan alat pemantauan lain untuk dilampirkan, baik di ruang nama PID host sehingga satu dapat memantau yang lain dan saya hanya didukung dan dilisensikan untuk menjalankan alat seperti itu dengan gambar resmi vendor . Jika alat pemantauan memantau JVM yang ada, maka penting untuk memulai dengan urutan mana (jelas). Mungkin ada ratusan kasus penggunaan yang urutannya penting, beberapa melibatkan jaringan (mysql, elasticsearch, cluster penemuan layanan semuanya telah disebutkan), tetapi beberapa melibatkan hal-hal lain yang dapat digunakan bersama dengan menggunakan namespace yang berbeda secara efektif.

Jadi saya pasti setuju dengan usecase (1), dalam beberapa keadaan Anda tidak bisa mengganti wadah

Tetapi juga begitu suatu alat menyangkut dirinya sendiri dengan banyak hal, itu segera menentang pemesanan. Jika memesan itu penting dan satu-satunya cara untuk menjamin pesanan adalah dengan menulis skrip bash di sekitar docker-compose untuk terlebih dahulu membuat sesuatu, dan kemudian membuat sesuatu yang lain, docker-compose mungkin juga tidak ada di rantai, selain fakta JSON / YAML lebih cantik dari argumen cmdline.

IMHO Akhirnya sebuah alat berguna atau tidak untuk sekumpulan kasus penggunaan. Docker-compose jelas berguna untuk startup tidak berurutan dari beberapa container di host yang sama. Jika cukup banyak orang dan cukup kasus penggunaan tentang memesan dan alat tidak menangani mereka, orang akan pergi ke tempat lain untuk kasus penggunaan yang memalukan.

Pokoknya saya lihat saya hanya mengulangi argumen lama, jadi saya akan mengeluarkan dari utas ini sekarang ..

Ini adalah argumen yang sama yang dinyatakan di ribuan utas pada begitu banyak topik pengembangan yang berbeda "Jika semua kode ditulis dengan benar oleh semua orang, tidak akan perlu seperti ini, jadi jangan lakukan itu". Itu sama dengan mengatakan: jika semua orang di dunia berhenti membakar bahan bakar fosil atau menggunakan listrik, kita bisa memperbaiki masalah yang kita sebabkan di planet kita. Anda benar. Jika semua aplikasi melakukan apa yang seharusnya, kami tidak akan membicarakan hal ini. Tapi kita hidup di bumi. Tempat yang memiliki ketidaksempurnaan besar dengan spesies makhluk yang cenderung harus belajar banyak hal dengan cara yang sulit. Orang yang sama yang hanya membuat perusahaan mulai berkembang karena mereka membangun "produk yang layak minimum" untuk berdoa agar mereka dapat mencapai pendanaan berikutnya atau pelanggan berikutnya yang mungkin suatu hari nanti memungkinkan mereka untuk membangun versi yang mereka inginkan. .

Dunia ini tidak dan tidak akan pernah sempurna sehingga kita hanya dapat melakukan apa yang kita miliki dalam kendali kita sendiri. Dan dalam hal ini satu-satunya hal yang saya miliki dalam kendali saya adalah mencoba meyakinkan Anda semua (alias Orang-orang yang mengembangkan alat yang sangat saya sukai dan akan gunakan dengan gila-gilaan jika hanya memiliki satu fitur ini) untuk membangunnya cara yang dapat digunakan untuk menangani perangkat lunak yang ada di dunia tempat kita tinggal. Bukan yang kita inginkan.

Pada tanggal 31 Juli 2015, pada jam 3:42, Aanand Prasad [email protected] menulis:

Saya akan mengira itu adalah pekerjaan atau setidaknya perhatian dari alat manajemen multi-kontainer untuk mengetahui pesanan apa yang harus dimulai

Tidak, belum tentu. Untuk alasan yang sudah dijelaskan beberapa kali di utas ini, saya yakin hanya ada dua alasan untuk menyerahkan pekerjaan ini ke alat manajemen kontainer:

Anda menjalankan gambar container off-the-shelf yang tidak tahan terhadap tidak tersedianya layanan upstream tempat mereka bergantung, dan untuk alasan teknis atau bisnis Anda tidak dapat mengubah atau memperluasnya.

Anda menjalankan perangkat lunak murni dalam lingkungan pengembangan, bukan produksi, dan Anda memiliki hal-hal yang lebih baik untuk dihabiskan daripada menerapkan ketahanan.

Namun, jika Anda memiliki kendali atas perangkat lunak Anda dan Anda berencana untuk menerapkannya ke produksi, Anda tidak dapat berharap untuk mengandalkan alat eksternal yang hanya memulai hal-hal dalam urutan yang benar, bahkan jika Anda telah menentukan kondisi kesiapan Anda dengan cermat. Ini bukan solusi untuk masalah mendasar, dan sistem Anda akan gagal saat ada gangguan jaringan. Paling banter, Anda harus secara otomatis memulai ulang semua penampung antarmuka web Anda setiap kali itu terjadi, dan saya tidak dapat melihat bahwa jumlah waktu henti yang dapat diterima untuk siapa pun.

-
Balas email ini secara langsung atau lihat di GitHub.

+1 @aanand. Ini bukanlah sesuatu yang dapat Anda batasi cakupannya. Fitur tersebut, jika sudah selesai, perlu menjadi sesuatu yang dapat diandalkan orang. Mereka telah membuat kode untuk infrastruktur yang "tahan lama" dan butuh waktu lama untuk mengonversi massa. Mereka _akan_ menggunakan ini untuk waktu yang lama.

Saya ingin menegaskan kembali bahwa kami belum mengesampingkan penerapan sesuatu untuk mengurangi masalah ketergantungan waktu startup antar kontainer - Saya membuat sketsa satu solusi yang mungkin baru saja kemarin, di utas ini .

Tapi saya ingin kita berada di halaman yang sama tentang untuk siapa fitur ini, masalah apa yang akan dipecahkan, masalah apa yang _ tidak akan_ pecahkan dan sampai sejauh mana fitur ini dapat diandalkan. Itulah yang saya coba rasakan.

Selain itu, mengingat beberapa definisi kesiapan yang ada ("container telah dimulai" vs "container menerima koneksi TCP" vs "custom health check pass"), dan kompleksitas penerapan yang berbeda dari masing-masing, saya ingin mendapatkan perbandingan gagasan tentang berapa banyak orang yang akan mendapat manfaat dari dukungan out-of-the-box untuk masing-masing.

Teknik umum untuk menyinkronkan layanan adalah sesuatu seperti "registri layanan" menggunakan etcd atau serupa. Bagaimana dengan wait_for_service:

web:
  image: mywebapp
  links: ["db"]
  wait_for_service:
    type: etcd (or consul, or zk)    -- or use swarm type notation
    addr: http://my.etcd.com/
    path: postgres.service

db:
  image: postgres

compose tidak tahu apakah layanan benar-benar siap tetapi dapat mencari data di registri dan memulai penampung dependen berdasarkan itu. Merupakan tanggung jawab layanan (seperti postgres) untuk mempublikasikan ketersediaan mereka ke registri sehingga untuk aplikasi lama semacam skrip pembungkus akan melakukan itu: memulai aplikasi, perhatikan port untuk ditayangkan, lalu publikasikan ke registri.

Hai @aanand.

Saya membahas hal ini hari ini dengan @bfirsh di Twitter karena itu adalah sesuatu yang saya temui.

Secara khusus, ketika membangun sistem terdistribusi dari banyak komponen kecil yang mengalami docker, saya menemukan kebutuhan untuk memiliki tes integrasi yang memutar semua aplikasi antarmuka utama dan dependensinya, kemudian menjalankan berbagai tes terhadap mereka sebelum menghancurkan semuanya lagi.

Hal ini menyebabkan masalah misalnya Riak membutuhkan waktu lama untuk memulai dibandingkan dengan apa pun yang menggunakannya.

Saya tidak akan menentang secara khusus jika Anda mengatakan "kontainer mulai asinkron, tangani saja", tetapi merancang di sekitar setiap layanan yang mengekspos healthcheck yang konsisten setidaknya akan berisi "menangani" untuk satu implementasi per layanan daripada memiliki kode untuk menangani mencoba kembali koneksi di setiap aplikasi yang mengandalkan layanan.

Layanan yang menentukan pemeriksaan kesehatan mereka sendiri juga bermanfaat untuk tujuan pemantauan.

@elliotcm Setuju pada kedua poin.

Untuk menguji CI kami, kami membuat utilitas kecil yang dapat digunakan dalam container Docker untuk menunggu layanan tertaut siap. Ini secara otomatis menemukan semua layanan TCP terkait dari variabel lingkungan mereka dan berulang kali dan secara bersamaan mencoba untuk membuat koneksi TCP sampai berhasil atau habis waktu.

Kami juga menulis entri blog yang menjelaskan mengapa kami membuatnya dan bagaimana kami menggunakannya .

@meeee itu terlihat sangat bagus dan berguna! Dapatkah Anda menunjukkan kepada kami contoh bagaimana itu berputar; khususnya digunakan dengan buruh pelabuhan-menulis?

Saya memiliki kasus yang lebih rumit hari ini, di mana saya memulai wadah mysql untuk pertama kalinya. Container melakukan bootstraps sendiri saat pertama kali dijalankan, dan memulai ulang daemon database saat dikonfigurasi. Hal ini menyebabkan pemeriksaan ketersediaan port saya dipicu sebelum waktunya, dan container yang bergantung dimulai tetapi gagal terhubung. Ini terjadi di lingkungan CI, di mana kami ingin semuanya diatur sepenuhnya dari awal.

Saya sangat tertarik untuk menulis untuk mendukung semacam perilaku tunggu / periksa, tetapi ada beberapa kasus yang menipu dan menipu di luar sana. Saya senang berpartisipasi dalam diskusi.

@prologic Yang harus Anda lakukan adalah menjalankan perintah waitforservices dalam kontainer Docker tergantung pada layanan / kontainer lain sebelum menjalankan aplikasi atau pengujian Anda. Ia menemukan semua layanan yang ditautkan dan berjalan hingga dapat terhubung dengannya atau waktu tertentu telah berlalu (60 detik secara default). Jalankan saja semua kode yang bergantung pada layanan lain setelah biner berhenti (Anda mungkin ingin memeriksa status keluar).

@pugnascotia Server database Anda hanya dapat mendengarkan di localhost saat di-bootstrap - Anda harus mengekspos beberapa jenis indikator apakah container sudah siap. Kami tidak menggunakan MySQL, tetapi layanan tunggu berfungsi sempurna dengan gambar postgres resmi .

@aanand Postgres adalah contoh yang sangat baik untuk dipilih sebenarnya, karena menunggu port TCP terbuka adalah _tidak_ cukup - jika Anda melakukannya dalam skenario jenis (buruh pelabuhan) ini maka Anda terkadang akan terkena kesalahan seperti FATAL: the database system is starting up. jika penampung Anda yang lain menyambung terlalu cepat setelah sambungan TCP terbuka. Jadi oleh karena itu psql tampaknya perlu jika Anda ingin memastikan bahwa postgres sudah siap - saya menggunakan select version() tetapi mungkin ada alternatif yang lebih ringan.

Ada plugin buruh pelabuhan Maven tertentu yang memiliki implementasi menunggu yang menarik. Saat ini saya menggunakan bash wrapper untuk memulai setiap layanan, yang agak mengalahkan tujuan penggunaan compose.

Menggunakan ini sebagai solusi (tidak yakin ini antipeluru):

db:
  image: postgres:9.3
  ports:
    - "5432:5432"
createdbs:
  image: postgres:9.3
  links:
    - db
  command: >
    /bin/bash -c "
      while ! psql --host=db --username=postgres; do sleep 1; done;
      psql --host=db --username=postgres -c 'CREATE DATABASE \"somedatabase\";';
    "

Saya telah menggunakan metode yang mirip dengan @olalonde. Saat menggunakan tanda kutip tunggal untuk perintah yang dijalankan setelah /bin/bash -c , saya juga dapat memanfaatkan variabel lingkungan yang digunakan kembali dari tautan saat aplikasi lain sehingga saya dapat menggunakan nama pengguna dan kata sandi tanpa harus menjaganya menjadi dua tempat. Ini berfungsi dengan baik untuk situasi di mana saya memiliki layanan, seperti API, yang memerlukan database untuk diaktifkan, dan memiliki data yang tepat di-bootstrap dengan menjalankan kueri yang memeriksa untuk melihat apakah ada tabel atau rekaman tertentu. Ini juga berarti bahwa saya perlu memiliki semacam klien yang diinstal di wadah untuk meminta database dengan benar tetapi berfungsi.

+1 Saya sangat tertarik dengan fungsi ini

+1 untuk dependensi. Saya setuju bahwa pada prinsipnya arsitektur harus cukup kuat untuk mendukung setiap tatanan start up. TAPI, sering kali, melakukan hal itu tidaklah praktis.

Rasanya seperti dorongan balik untuk fitur ini berasal dari orang lain yang mencoba mendikte arsitektur dari jauh; dimana mereka benar-benar tidak memiliki hak untuk melakukannya. Fitur ini akan memungkinkan untuk bekerja di sekitar refactors yang memakan waktu; dengan sedikit nilai jangka panjang. (Refactoring untuk kepentingan refactoring).

Ya, saya berkata "bekerja di sekitar"; dan saya merasa kotor. Tapi menenangkan saya adalah tentang memungkinkan orang lain menjadi produktif. Konfigurasi sederhana ini memungkinkannya.

Jika fitur ini ada di toolest, saya dapat menyelesaikan masalah saya dalam satu menit dan melanjutkan untuk menambahkan nilai nyata. Sebagai gantinya, saya membenturkan kepala saya ke dinding mencoba untuk mengatasi masalah pesanan start up dengan dependensi eksternal.

@beardface , dan semua orang: Fitur mana, khususnya, yang memungkinkan Anda untuk melanjutkan mengembangkan aplikasi?

  1. Kemampuan untuk menentukan bahwa layanan A harus menunggu untuk memulai hingga layanan B dimulai? (yang, perlu diingat, masih tidak akan menyelesaikan kondisi balapan saat wadah dimulai tetapi tidak siap untuk menerima koneksi)
  2. Kemampuan untuk menentukan bahwa layanan A harus menunggu untuk memulai hingga layanan B menerima koneksi? (yang, perlu diingat, masih tidak akan menyelesaikan kondisi balapan ketika penampung mendengarkan tetapi belum selesai menginisialisasi - misalnya penampung postgres membuat database saat memulai, untuk menggunakan contoh @rarkins )
  3. Kemampuan untuk menentukan health check pada layanan B, dan untuk menentukan bahwa layanan A harus menunggu untuk memulai hingga health check layanan B berhasil?

@aanand Nomor 3 adalah pilihan saya. Ini memberikan fleksibilitas kepada pengembang untuk memilih logika health check alih-alih mengandalkan layanan untuk memutuskan kapan waktunya. Untuk kasus penggunaan khusus ini, lebih banyak kebebasan pengembang lebih baik. Tidak mungkin untuk mengantisipasi semua jenis aplikasi yang akan dipasang di kontainer.

+3

Akan menyenangkan untuk memiliki beberapa pemeriksaan kesehatan dasar yang disertakan. Sesuatu seperti _http 200 ok di port 80_ sangat umum sehingga mungkin sepadan dengan usaha.

Alangkah baiknya memiliki "termasuk baterai" nomor 3 (jadi beranikah saya mengatakan semua hal di atas?)

Yaitu kemampuan bawaan untuk "container is up", "file is present" dan "port is open" jenis menunggu dan kemudian cara untuk membiarkan orang mendefinisikan pemeriksaan "application layer" mereka sendiri.

3 mendapatkan suara saya

3 adalah lebih umum 2 lebih umum 1. Setiap orang akan memilih 3, tetapi 2 atau 1 sudah cukup baik untuk beberapa.

Beri suara untuk 3

Jelas pilihan ke-3. Ada banyak kasus hanya dalam diskusi ini. Jadi, opsi pertama dan kedua akan bagus dan banyak orang akan senang, tetapi masalah akan tetap terbuka.

Beri suara untuk 3

Beri suara untuk 3

Pilih 3. Tertarik untuk menguji beta juga.

Beri suara untuk 3.

Pilih 3. Tertarik untuk menguji beta juga.

Beri suara untuk 3

3

Terimakasih semuanya. Anda dapat berhenti memberikan suara sekarang - menurut saya pesannya jelas.

Saya tertarik dengan masukan tentang desain yang saya usulkan di https://github.com/docker/compose/issues/374#issuecomment -126312313 - proposal desain alternatif apa pun, bersama dengan diskusi tentang kekuatan / kelemahannya.

Metode kenyamanan wait_for_tcp akan berguna, tetapi tidak jelas bagi saya bagaimana memiliki wadah terpisah untuk melakukan pemeriksaan kesehatan lebih mudah daripada melakukannya di wadah yang sama seperti yang dijelaskan oleh @olalonde dan @mbentley di atas .

Bagaimana dengan melakukan sesuatu seperti yang dilakukan alexec di docker-maven-plugin? Dia secara eksplisit merancang konfigurasinya agar mirip dengan docker-compse / fig dan sejauh ini, itu berfungsi dengan baik untuk proyek saya.

healthChecks:
  pings:
     # check this URL for 200 OK
     - https://localhost:8446/info
     # check another URL with non-default time out, with a pattern, and non checking SSL certificates
     - url: https://localhost:8446/info
       timeout: 60000
       pattern: pattern that must be in the body of the return value
       sslVerify: false
  logPatterns:
     - pattern that must be in log file
     - pattern: another pattern with non-default timeout
       timeout: 30000

Sumber: https://github.com/alexec/docker-maven-plugin/blob/master/USAGE.md

Memeriksa bahwa koneksi tcp sudah habis tidak cukup untuk mengetahui bahwa database dimulai. Saya pikir lebih baik memiliki beberapa perintah yang memeriksa kesehatan database.

@ceagan Seperti itu. Perintah khusus juga akan berguna. misalnya

healthChecks:
  custom:
    # retry this command until it returns success exit code
    - cmd: psql --host=localhost --username=postgres
      sleep: 1s

Saya juga berpikir checks akan lebih baik daripada healthChecks karena tidak perlu mengingat konvensi kasus. Mungkin juga berguna untuk memiliki wait (berapa detik menunggu sebelum mulai menjalankan pemeriksaan kesehatan), attempts (berapa kali kesehatan harus diperiksa sebelum menyerah), retire (berapa detik untuk menunggu sebelum menyerah sepenuhnya) parameter.

ini sesuai dengan cara kerangka maraton menyelesaikannya. dependensi dasar ditambah healthcheck . karena sangat populer untuk memulai kontainer buruh pelabuhan, ada baiknya untuk memeriksa opsinya (batas waktu, interval, kode respons, dll.) untuk mengadopsi mereka untuk penulisan.

Sama di sini, opsi 3.

+1

+1

+1

Saya akan tetap menggunakan skrip tunggu khusus, namun, itu akan sangat menyenangkan.

+1

+1

Opsi 3-healthChecks terdengar bagus.

+1

+1

+1

+3.
Untuk menambahkan beberapa pemikiran lain ke diskusi, pilihan @aanand diusulkan benar-benar mengatakan: status kontainer adalah tanggung jawab buruh pelabuhan, bukan buruh pelabuhan-menulis. Docker-compose dapat mengimplementasikan semua kasus penggunaan ini dengan cara yang bersih dan elegan, jika buruh pelabuhan memberikan informasi status. Tapi buruh pelabuhan tidak. Tampaknya tetap berpegang pada visi wadah langsung tanpa kewarganegaraan, diluncurkan begitu cepat sehingga masalah sinkronisasi semacam ini tidak penting.
Dalam kasus saya, saya mengejar ide untuk dapat memilih arsitektur terbaik untuk layanan saya, untuk setiap kasus. Misalnya, terkadang saya ingin beberapa instance MariaDB, masing-masing melayani satu aplikasi. Di lain waktu saya ingin satu contoh MariaDB, melayani banyak aplikasi. Saya tidak ingin Docker memberi tahu saya apa yang terbaik, atau apa yang seharusnya saya lakukan. Docker sepertinya selalu memiliki godaan semacam ini;).
Saya pikir solusi terbaik adalah meyakinkan Docker untuk membiarkan kontainer mendeklarasikan metadata sewenang-wenang tentang diri mereka sendiri, dan menggunakan fitur itu untuk membiarkan pembuat galangan-pembuat mengetahui apakah sebuah kontainer dianggap "siap" sehingga orang lain dapat mengandalkannya.
Sedangkan untuk pendekatan "satu db-banyak aplikasi", saya menginginkan definisi seperti:

db:
  image: postgres:9.3
  ports:
    - "5432:5432"
app1:
  image: wordpress
  links:
    - db [WP]
app2:
  image: ghost
  links:
    - db [GST]

Docker Compose akan meluncurkan "db", dan menanyakan tentang metadatanya (relevan dengan Docker Compose). Dari file yml, ia tahu "app1" mengharapkan "db" menjadi "wordpress ready" (artinya tidak hanya menerima koneksi, tetapi juga dengan objek yang diperlukan).

Saya tidak punya solusi sederhana untuk mengatasi situasi ini. Saat ini saya melakukannya secara manual, dalam dua langkah: gambar custom postgresql-bootstrap, di mana saya membuat db dan pengguna database untuk mengaksesnya; dan gambar liquibase-postgresql kustom, untuk menghasilkan objek database dari DDL yang disediakan oleh (atau diekstrak dari) container Wordpress. Hanya dengan begitu, saya dapat meluncurkan "app1".
Hal itu memaksa saya untuk memisahkan container dalam grup "infrastruktur" dan "apps", jika container "infrastruktur" melayani aplikasi yang berbeda.

Docker Compose ingin menjadi stateless seperti Docker itu sendiri. Saya tidak tahu apakah itu mungkin jika ingin benar-benar berguna.

1 untuk opsi 3

+1

1 untuk opsi 3.

1 untuk opsi 3

1 untuk opsi 3

Masalah ini sudah ada cukup lama, apa solusinya?

@ bweston92 Saya pikir statusnya adalah @aanand mengusulkan solusi sebelumnya di utas ini dan sedang dicari

proposal desain alternatif apa pun, bersama dengan diskusi tentang kekuatan / kelemahannya.

Secara pribadi, menurut saya solusi yang diusulkan @aanand sangat masuk akal. Tampaknya sangat eksplisit bagi saya, sekaligus juga fleksibel. Ini akan menutupi kebutuhan saya atau menunggu port TCP terbuka atau hanya menunggu waktu yang tetap.

Kasus penggunaan saya hanya untuk pengujian. Pengujian saya akan gagal jika dimulai sebelum database dibuat, jadi saya mengubah perintah mereka menjadi bash -c "sleep 2; python manage.py test --keepdb" , seperti ini:

db:
    image: postgres:9.5
test:
    build: .
    command: bash -c "sleep 2; python manage.py test --keepdb"
    volumes:
        - ./test_project:/app
    links:
        - db
        - selenium
    environment:
        - EXTERNAL_TEST_SERVER=http://testserver:8000/
        - SELENIUM_HOST=http://selenium:4444/wd/hub
selenium:
    image: selenium/standalone-chrome:2.48.2
    links:
        - testserver
testserver:
    build: .
    command: bash -c "sleep 5; python manage.py testserver 8000 --static"
    volumes:
        - ./test_project:/app
    ports:
      - "8000:8000"
    links:
        - db

sehingga saya dapat menjalankan docker-compose run test tanpa memulai database terlebih dahulu dan menunggu.

Sulit untuk mengatakan masalah mana saat ini yang merupakan tempat yang "tepat" untuk memilih fungsionalitas penulisan buruh pelabuhan baru yang memungkinkan dependensi eksplisit untuk diumumkan, tetapi anggap saya pilihan yang kuat. Dengan fungsionalitas jaringan Docker 1.9 yang baru, dan penghentian tautan kontainer yang membayangi yang mendukungnya, sekarang tidak ada cara yang bagus untuk memastikan bahwa kontainer A dijalankan sebelum kontainer B - karena jika Anda menggunakan jaringan yang ditentukan pengguna Docker 1.9, Anda dapat tidak lagi menentukan tautan penampung. Itu ... rusak.

Saya setuju. Apakah ada jadwal untuk mendapatkan opsi 3? Akan sangat bagus jika ini dipercepat.

Perlu dicatat bahwa pengurutan ketergantungan sebenarnya tidak memperbaiki masalah ini. Masalah ini juga berlaku untuk tautan. Dalam banyak kasus, penampung mulai cukup cepat sehingga Anda tidak menyadari masalahnya, tetapi masalahnya masih ada.

Apa yang diperlukan untuk mengatasi masalah ini adalah pemeriksaan kesehatan yang sadar-aplikasi. Healthcheck pada dasarnya adalah perulangan yang mencoba ulang beberapa operasi hingga: operasi berhasil, atau batas waktu tercapai. Dalam kasus layanan HTTP, ini mungkin membuat permintaan http sampai Anda mendapatkan kode 2xx. Untuk database mungkin menghubungkan dan memilih dari tabel.

Apapun masalahnya, itu khusus aplikasi, jadi perlu ditentukan oleh pengembang. Jika kami akan menerapkan opsi 3 dari https://github.com/docker/compose/issues/374#issuecomment -135090543, Anda masih perlu menerapkan logika healthcheck ini.

Sudah disebutkan beberapa kali dalam masalah ini (https://github.com/docker/compose/issues/374#issuecomment-53036154, https://github.com/docker/compose/issues/374#issuecomment-71342299 ), tetapi untuk mengulang, Anda dapat menyelesaikan masalah ini sekarang dengan membuat aplikasi Anda tahan terhadap kegagalan dengan mencoba kembali koneksi. Anda tetap perlu melakukan ini untuk sistem produksi apa pun.

Ternyata fungsi untuk membuat aplikasi Anda tahan terhadap kegagalan secara efektif memiliki logika yang sama dengan healthcheck. Jadi, bagaimanapun, Anda masih perlu menerapkan logika yang sama. Satu-satunya perbedaan adalah di mana Anda memasukkannya. Sekarang Anda dapat memasukkannya ke dalam aplikasi Anda, atau skrip entrypoint. Dengan perubahan yang diusulkan, Anda akan dapat menentukannya di file Tulis. Apa pun itu, Anda masih harus menerapkan healthcheck untuk setiap layanan.

Apakah ada keuntungan yang signifikan untuk menyertakannya dalam file Tulis alih-alih skrip entrypoint? Itu mungkin masih diperdebatkan.

Keuntungan_besar dari memasukkannya ke dalam file Tulis adalah membuat up secara signifikan lebih lambat.

Dengan jaringan baru kita dapat membuat up terjadi secara paralel (seperti yang kita lakukan untuk stop, rm, dan skala). Setiap penampung dapat memulai sekaligus, melakukan beberapa inisialisasi, lalu menunggu dependensinya tersedia untuk melanjutkan. Ini membuat lingkungan memulai dengan sangat cepat.

Jika Tulis harus menunggu healthcheck selesai, startup secara efektif berurutan. Memulai container dan inisialisasi aplikasi tidak terjadi secara paralel, dan semuanya menjadi lebih lambat.

Sebagian besar aplikasi akan memiliki pemeriksaan kesehatan karena di belakang LB, dipantau secara eksternal, dll. Untuk membuka yang baru tidaklah sulit. Jadi, jika compose mendukungnya maka itu adalah pilihan yang bisa digunakan orang-orang. Itu tidak wajib. Di dunia nyata, orang harus berurusan dengan berbagai aplikasi dan anggapan bahwa tiba-tiba semua aplikasi dapat dibuat cerdas adalah tidak realistis dan tidak praktis. Dan logika pembungkus di titik masuk sangat buruk. Saya pikir sudah cukup banyak permintaan di komunitas untuk sebuah fitur dan seperti yang Anda lihat, opsi 3 mendapat banyak suara.

dikirim dari iPhone saya

Pada 18 November 2015, pukul 11:01, Daniel Nephin [email protected] menulis:

Perlu dicatat bahwa pengurutan ketergantungan sebenarnya tidak memperbaiki masalah ini. Masalah ini juga berlaku untuk tautan. Dalam banyak kasus, penampung mulai cukup cepat sehingga Anda tidak menyadari masalahnya, tetapi masalahnya masih ada.

Apa yang diperlukan untuk mengatasi masalah ini adalah pemeriksaan kesehatan yang sadar-aplikasi. Healthcheck pada dasarnya adalah perulangan yang mencoba ulang beberapa operasi hingga: operasi berhasil, atau batas waktu tercapai. Dalam kasus layanan HTTP, ini mungkin membuat permintaan http sampai Anda mendapatkan kode 2xx. Untuk database mungkin menghubungkan dan memilih dari tabel.

Apapun masalahnya, itu khusus aplikasi, jadi perlu ditentukan oleh pengembang. Jika kami menerapkan opsi 3 dari # 374 (komentar), Anda masih perlu menerapkan logika pemeriksaan kesehatan ini.

Sudah disebutkan beberapa kali dalam masalah ini (# 374 (komentar), # 374 (komentar)), tetapi untuk mengulanginya, Anda dapat menyelesaikan masalah ini hari ini dengan membuat aplikasi Anda tahan terhadap kegagalan dengan mencoba kembali sambungan. Anda tetap perlu melakukan ini untuk sistem produksi apa pun.

Ternyata fungsi untuk membuat aplikasi Anda tahan terhadap kegagalan secara efektif memiliki logika yang sama dengan healthcheck. Jadi, bagaimanapun, Anda masih perlu menerapkan logika yang sama. Satu-satunya perbedaan adalah di mana Anda memasukkannya. Sekarang Anda dapat memasukkannya ke dalam aplikasi Anda, atau skrip entrypoint. Dengan perubahan yang diusulkan, Anda akan dapat menentukannya di file Tulis. Apa pun itu, Anda masih harus menerapkan healthcheck untuk setiap layanan.

Apakah ada keuntungan yang signifikan untuk menyertakannya dalam file Tulis alih-alih skrip entrypoint? Itu mungkin masih diperdebatkan.

Kerugian besar untuk memasukkannya ke dalam file Tulis adalah membuatnya jauh lebih lambat.

Dengan jaringan baru ini kita dapat mewujudkannya secara paralel (seperti yang kita lakukan untuk stop, rm, dan skala). Setiap penampung dapat memulai sekaligus, melakukan beberapa inisialisasi, lalu menunggu dependensinya tersedia untuk melanjutkan. Ini membuat lingkungan memulai dengan sangat cepat.

Jika Tulis harus menunggu healthcheck selesai, startup secara efektif berurutan. Memulai container dan inisialisasi aplikasi tidak terjadi secara paralel, dan semuanya menjadi lebih lambat.

-
Balas email ini secara langsung atau lihat di GitHub.

@dnephin Hasil akhirnya adalah Anda memiliki skrip pembungkus yang sama untuk setiap layanan. Maksud saya adalah ada beberapa hal yang sangat umum (seperti HTTP 200 pada 80 dan 443 atau TCP pada 5432) sehingga merupakan ide yang baik untuk mengirimkannya dengan menulis.

Tentu, akan menyenangkan untuk menyelesaikan semua ini di tingkat aplikasi tetapi pada kenyataannya Anda hanya memiliki kendali atas aplikasi Anda sendiri dan tidak semua bagian bergerak lainnya seperti database, cache, atau antrian pijat.

Saya setuju dengan @mbdas dan @jayfk , dan hanya akan menambahkan: jika resistensi terhadap hal ini adalah bahwa bahkan dengan spesifikasi ketergantungan dan urutan startup kontainer yang dihasilkan, akan ada kegagalan, maka penggunaan tautan kontainer dan volume-dari ke mengontrol urutan startup kontainer seharusnya tidak pernah terjadi - semua yang kami minta adalah bahwa sekarang model jaringan baru berarti tautan sudah tidak digunakan lagi (dan model jaringan baru benar-benar tidak dapat hidup berdampingan dengan tautan), startup yang sama Fungsionalitas -pesanan yang memungkinkan tautan diberikan kembali kepada kami dengan cara tertentu. Tentu, setiap kasus kegagalan yang mungkin terjadi dengan pengurutan penampung berbasis tautan mungkin masih terjadi dengan model jaringan baru dan ketergantungan penampung, tetapi kita semua telah belajar untuk mengatasinya.

@delfuego : dapatkah Anda menjelaskan tentang bagaimana tautan tidak digunakan lagi, dan terutama dengan apa yang diganti? tautan ke beberapa dokumen / contoh sudah cukup

@Silex https://docs.docker.com/compose/networking. apakah itu yang kamu maksud

@ h17liner : ya, menarik! Terima kasih

Sementara saya setuju dengan @dnephin itu

Ini sudah disebutkan beberapa kali dalam masalah ini, tetapi untuk mengulanginya, Anda dapat menyelesaikan masalah ini hari ini dengan membuat aplikasi Anda tahan terhadap kegagalan dengan mencoba kembali koneksi. Anda tetap perlu melakukan ini untuk sistem produksi apa pun.

Saya tidak melihat ini membuat karena untuk sesuatu seperti menjalankan tes. Jika saya hanya menguji apakah sebuah model menyimpan dengan benar dalam aplikasi Django, saya tidak yakin seberapa masuk akal untuk menambahkan ketahanan ke koneksi database.

@delfuego Awalnya saya pikir Anda berada di tempat yang tepat (# 686) untuk masalah itu. Masalah ini bukan tentang pemesanan, ini tentang penundaan buatan dalam startup (ketika pesanan sudah ada). Meskipun hal-hal ini terkait, mereka adalah masalah yang terpisah.

Saya tidak setuju dengan tautan yang tidak didukung di jaringan jembatan buatan pengguna dan didokumentasikan menjadi usang secara umum tidak ada pemesanan. Jadi, opsi 3 menangani pemesanan dan kapan harus memulai masalah.

dikirim dari iPhone saya

Pada 19 November 2015, pukul 8:14, Daniel Nephin [email protected] menulis:

@delfuego Awalnya saya pikir Anda berada di tempat yang tepat (# 686) untuk masalah itu. Masalah ini bukan tentang pemesanan, ini tentang penundaan buatan dalam startup (ketika pesanan sudah ada). Meskipun hal-hal ini terkait, mereka adalah masalah yang terpisah.

-
Balas email ini secara langsung atau lihat di GitHub.

Saya ingin mengusulkan opsi 4 (beberapa mungkin mengatakan itu sebenarnya adalah variasi dari 3)
Penampung tidak siap sampai semua perintah startup diselesaikan dengan 0 kode keluar. Perintah startup ini harus dapat ditentukan dalam file yml untuk setiap penampung. Perintah ini dijalankan seperti yang Anda lakukan dengan "docker exec" terhadap container yang sedang berjalan. Pikirkan metode setUp () dan tearDown () dalam pengujian unit klasik. Ya, kita juga bisa memiliki perintah "shutdown".
Jelas penampung berikutnya dalam hierarki tidak diluncurkan sampai semua penampung yang bergantung padanya siap.
PS Terima kasih untuk DockerCon.Eu 2015 yang hebat

Perintah HEALTHCHECK jauh lebih fleksibel (yaitu dapat digunakan di lain waktu) dan membantu. Setup harus dilakukan dalam skrip CMD atau (lebih baik lagi) ENTRYPOINT , pembongkaran dengan menangani sinyal proses.

Saya pikir inti dari masalah di sini adalah bahwa orang ingin satu perintah docker-compose up untuk memunculkan tumpukan dan semuanya bekerja secara ajaib.

Berdasarkan semua umpan balik, jelas ada banyak solusi untuk kasus penggunaan yang berbeda tetapi tidak ada "satu ukuran cocok untuk semua".

Anda dapat menjalankan tugas "inisialisasi" dengan mudah dengan menjalankan beberapa perintah docker-compose - dan menurut saya pendekatan ini adalah pendekatan yang paling umum dan fleksibel.

Misalnya saya menjalankan buku pedoman yang mungkin dalam wadah "agen" dengan satu tugas yang menunggu wadah database saya (MySQL) berjalan pada port 3306. Wadah "agen" ini terhubung ke wadah "db" saya jadi secara otomatis memulainya ketika berikut ini dijalankan:

$ docker-compose run --rm agent
Creating db_1

PLAY [Probe Host] *************************************************************

TASK: [Set facts] *************************************************************
ok: [localhost]

TASK: [Message] ***************************************************************
ok: [localhost] => {
    "msg": "Probing db:3306 with delay=0s and timeout=180s"
}

TASK: [Waiting for host to respond...] ****************************************
ok: [localhost -> 127.0.0.1]

PLAY RECAP ********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0

Setelah itu saya dapat menjalankan docker-compose up mengetahui bahwa wadah db beroperasi penuh.

Berikut adalah file docker-compose.yml sederhana yang mendukung ini:

...
...
db:
  image: mysql
  hostname: db
  expose:
    - "3306"
  environment:
    MYSQL_DATABASE: xxx
    MYSQL_USER: xxx
    MYSQL_PASSWORD: xxx
    MYSQL_ROOT_PASSWORD: xxx

agent:
  image: cloudhotspot/ansible
  links:
    - db
  volumes:
    - ../../ansible/probe:/ansible
  environment:
    PROBE_HOST: "db"
    PROBE_PORT: "3306"

Wadah "agen" menjalankan buku pedoman bernama site.yml dalam volume terpasang /ansible yang ditunjukkan di bawah ini:

- name: Probe Host
  hosts: localhost
  connection: local
  gather_facts: no
  tasks: 
    - name: Set facts
      set_fact: 
        probe_host: "{{ lookup('env','PROBE_HOST') }}"
        probe_port: "{{ lookup('env','PROBE_PORT') }}"
        probe_delay: "{{ lookup('env','PROBE_DELAY') | default(0, true) }}"
        probe_timeout: "{{ lookup('env','PROBE_TIMEOUT') | default (180, true) }}"
    - name: Message
      debug: msg="Probing {{ probe_host }}:{{ probe_port }} with delay={{ probe_delay }}s and timeout={{ probe_timeout}}s"
    - name: Waiting for host to respond...
      local_action: >
        wait_for host={{ probe_host }}
        port={{ probe_port }}
        delay={{ probe_delay }}
        timeout={{ probe_timeout }}
      sudo: false

Salah satu solusi untuk tujuan tunggal docker-compose up mungkin adalah memperkenalkan fitur "alur kerja" untuk pembuatan buruh pelabuhan dan menyertakan file spesifikasi alur kerja opsional yang memungkinkan skenario orkestrasi yang lebih kompleks dan terkontrol dengan menetapkan satu atau lebih perintah penulisan buruh pelabuhan sebagai "tugas" yang harus dijalankan:

# The default workflow, specified tasks will be run before docker-compose up
# The "up" task is implicit and automatically invoked for the default workflow
# The "up" task is explicit for custom workflows as some workflows may not want docker-compose up
default:
  tasks:
    - run --rm agent
    - up

# Custom workflows that can be invoked via a new docker-compose command option
# This example:
# 1. Runs agent container that waits until database container is up on port 3306
# 2. Runs Django database migrations from app container
# 3. Runs Django collect static task from app container
# 4. Runs test container that runs acceptance tests against linked app container
# Does not execute a docker-compose up afterwards

test:
  tasks:
    - run --rm agent 
    - run --rm app manage.py migrate
    - run --rm app manage.py collectstatic --noinput
    - run --rm test

Hari ini saya mencapai hal di atas menggunakan Makefiles, yang memberikan kemampuan tingkat tinggi untuk menentukan alur kerja saya sendiri untuk skenario yang berbeda.

Akan sangat bagus jika fitur "alur kerja" atau yang serupa dapat dimasukkan ke dalam penulisan galangan, yang akan memberikan solusi yang sangat umum dan fleksibel untuk masalah khusus ini dan banyak lagi.

Setuju, masalahnya adalah orang-orang mengharapkan docker-compose memadai untuk penerapan produksi. Secara pribadi, saya pikir itu akan menjadi waktu yang lama sebelum itu menjadi mungkin dan Kubernetes / Helm tampaknya lebih dekat dengan tujuan itu.

@olalonde , tentu kami ingin menulis agar siap produksi ... tetapi kami akan MENGAMBILnya mendukung fungsi penting dan yang ada yang, mengingat penghentian tautan penampung, akan hilang kecuali direplikasi ke pengguna baru model jaringan -created. (Sekali lagi, mungkin permintaan ini tidak selaras secara sempurna dengan masalah khusus ini - bagi saya tetap tidak jelas apakah hanya mendapatkan startup container yang memesan "milik" di sini atau dalam masalah # 686 ...)

Dengan direktif HEALTCHECK Docker, fungsionalitas depends_on dapat menunggu startup kontainer (tanpa pemeriksaan kesehatan) atau skrip pemeriksaan kesehatan berhasil keluar (kode keluar 0 ). Ini sefleksibel yang didapat (Anda dapat mendefinisikan logika arbitrer) dan menyimpan logika healthcheck di tempatnya (dalam container yang dicentang).

@delfuego bahkan untuk pengembangan dan pengujian, fungsi ini akan berguna. Secara pribadi, saya ingin dapat melakukan docker-compose run test dan membuatnya berfungsi tanpa memunculkan layanan sebelumnya dan menunggu secara manual. Meskipun hal ini dimungkinkan, itu hanya membuatnya sedikit lebih menyakitkan untuk memulai proyek dan menambahkan lebih banyak cara pengujian dapat gagal.

+1

Saya pikir resolusi membutuhkan jalan tengah - menulis tidak akan pernah dapat menjelaskan semua cara berbeda di mana aplikasi dapat dianggap tersedia atau tidak. Gagasan tentang pemeriksaan kesehatan akan memiliki arti yang berbeda bagi orang yang berbeda, dan mungkin tidak sesederhana "terserah atau tidak". Dalam produksi, Anda mungkin menghapus container jika container menunjukkan waktu respons yang sangat lama, meskipun container melewati pemeriksaan HTTP apa pun.

Oleh karena itu, saya merasa bahwa dukungan dasar untuk respons HTTP, port terbuka, file yang dibuat, atau baris log yang dikeluarkan sudah cukup untuk pengembangan. Apa pun yang lebih maju dari itu akan segera menjadi spesifik aplikasi. Saya juga menyukai ide untuk mendorong pengembang untuk membuat bagian individu dari tumpukan aplikasi mereka lebih kuat.

@pugnascotia terima kasih, itu adalah komentar yang membangun, dan pendekatan yang masuk akal ("terbaik dari kedua dunia"?)

Solusi yang saat ini dibahas tampaknya tidak benar-benar mengatasi masalah _originally report_ yang jauh lebih sederhana ... yang TIDAK menunggu layanan tersedia, tetapi menunggu layanan KELUAR.

Saya memiliki kasus penggunaan di mana saya memiliki dua kontainer yang mengekspos port yang sama. Yang pertama berjalan selama 15-60 detik, lalu keluar. Kemudian layanan kedua harus dimulai. Tidak ada cara (jelas?) Untuk melakukan ini di compose hari ini karena ini akan mendeteksi konflik port dan akan keluar; bahkan 'restart: always' bukanlah solusi.

Ya, Tulis tidak dirancang untuk kasus penggunaan itu. Penulisan difokuskan di sekitar lingkungan waktu proses, bukan membangun pipeline. Saya tidak berpikir tentang itulah masalah asli yang dilaporkan.

Ada beberapa permintaan untuk fitur yang lebih berorientasi pada build, tetapi menurut saya itu tidak masuk akal untuk menulis. Kedua fungsi tersebut sangat berbeda dan mencoba menyesuaikannya dalam format konfigurasi yang sama kemungkinan besar akan menimbulkan banyak kebingungan dan pengalaman pengguna yang buruk.

@ewindisch kasus penggunaan Anda dapat digeneralisasi untuk menjalankan rantai pekerjaan batch. Compose berguna untuk kasus itu (meskipun tidak dirancang untuk itu) karena ia memelihara ketergantungan antar layanan - misalnya rantai tersebut. Tapi itu tidak menangani pengurutan dan IMHO seharusnya tidak karena Compose adalah _outside_ dari penampung dan tidak tahu apa proses _inside_ penampung yang akan dilakukan.

Bagian dari dokumentasi Compose ini mencakup pertanyaan mengapa Compose tidak memiliki kemampuan ini:

https://docs.docker.com/compose/faq/#how -do-i-get-compose-to-wait-for-my-database-to-be-ready-before-starting-my-application

Namun halaman berikut tidak menyebutkan masalah sama sekali:

https://docs.docker.com/compose/django/
https://docs.docker.com/compose/rails/
https://docs.docker.com/compose/wordpress/

Setidaknya, halaman ini harus menyertakan pengakuan bahwa Compose tidak akan menunggu container database siap. Mereka juga dapat memasukkan contoh cara menghadapinya.

@ewindisch Sebenarnya, itulah yang saya usulkan di https://github.com/docker/compose/issues/374#issuecomment -126312313 - dengan hipotesis bahwa menyelesaikan masalah _that_ juga memberi pengguna alat untuk memecahkan masalah pemesanan startup ( jika bukan masalah ketahanan jangka panjang).

Saya masih tertarik untuk menjelajahi ruang solusi itu, jika ada orang lain yang tertarik.

Saya.

Saya juga.

+1

+3

+1

+1 untuk mengimplementasikan solusi https://github.com/docker/compose/issues/374#issuecomment -126312313.

Upvoting besar-besaran!
Saat ini efek ini menggunakan alat yang berjalan di container, tetapi bergantung pada event docker (mis. Jwilder / nginx-proxy). Cara saya melakukannya adalah hanya buruh pelabuhan-menyusun pendengar secara manual dan menjalankan semua wadah lain sesudahnya (yang merusak semua keindahan buruh pelabuhan-menulis sebagai titik masuk tunggal).

@meetmatt sudahkah Anda mencoba menjalankan jwilder / nginx-proxy sesudahnya? Urutan awal seharusnya tidak menjadi masalah untuk itu, itu akan mengambil kontainer yang ada (berjalan) saat dimulai

+1

+1

Saya sangat ingin melihat solusi berbasis saluran yang transparan. Pada dasarnya seperti libchan. Dengan cara itu jika saya membuat kueri database, permintaan tersebut di-buffer hingga database siap.

Saya benar-benar tidak berpikir urutan pemuatan adalah solusi yang cukup dalam sistem terdistribusi. Bagaimana jika, misalnya, Anda perlu memulai ulang database Anda tetapi layanan lain mungkin macet sebagai akibatnya? Solusi nyata akan menangani kasus penggunaan ini juga.

Hitung saya, karena prediksi jalur eksekusi adalah hal utama untuk apa yang kami lakukan di tempat kerja. +1

+1

Saya pasti melewatkan sesuatu.

Mengapa tidak ada yang menganjurkan menambahkan "tunggu sampai" ke dalam menjalankan buruh pelabuhan (mesin buruh pelabuhan itu sendiri). Dalam semua kasus yang dapat saya pikirkan, container dependen tahu kapan ia "siap" tetapi buruh pelabuhan tidak menghargai itu.

Dalam kasus asli (mysql memuat kumpulan data besar dan tempat terbuka), wadah mysql dapat kembali atau memberi sinyal ketika sudah siap dan wadah alfresco tidak akan mulai sampai saat itu.

Saya ingin menjalankan logika dan sinyal sewenang-wenang ke buruh pelabuhan ketika saya siap seperti yang saya putuskan (misalnya ketika pesan tertentu di log muncul -> sinyal CONTAINER_UP).

net: "container:[name or id]" mengapa tidak memesan startup wadah saya? Saya harus menjatuhkan links karena itu akan usang dan saya ingin seluruh tumpukan menggunakan jaringan net: "host" . Sayangnya ini tidak diperbolehkan dengan links . Apakah ada cara lain untuk mengubah urutan boot container atau saya harus membagikan volume yang tidak berguna di antara mereka?

Memperbarui:

Saya baru saja melakukan pemesanan ulang dengan volume yang tidak berguna, bukan links :

base:
  build: ./base
  net: "host"
  volumes:
    - /root/lemp_base
phpmyadmin:
  build: ./phpmyadmin
  net: "host"
  volumes_from:
    - base
  volumes:
    - /root/lemp_phpmyadmin
ffmpeg:
  build: ./ffmpeg
  net: "host"
  volumes_from:
    - phpmyadmin
  volumes:
    - /root/lemp_ffmpeg
mariadb:
  build: ./mariadb
  net: "host"
  volumes_from:
    - ffmpeg
  volumes:
    - /root/lemp_mariadb
php:
  build: ./php
  net: "host"
  volumes_from:
    - mariadb
  volumes:
    - /root/lemp_php
nginx:
  build: ./nginx
  net: "host"
  volumes_from:
    - php
  volumes:
    - /root/lemp_nginx

(Saya membersihkan volume bersama lainnya dari tumpukan dan info lain seperti container_name, port agar terlihat sederhana.)

Jika saya ingin menggunakan dengan net: "container:base , saya mendapat pesan kesalahan pada perintah docker-compose build .

ERROR: Service "mariadb" is trying to use the network of "lemp_base", which is not the name of a service or container.

Yang tidak saya sukai dari solusi ini adalah bahwa setiap penampung lain akan mendapatkan file server web di folder /var/www dari base .

EDIT:
Untuk beberapa alasan tumpukan ini menghapus seluruh folder /var/www saat startup.

Pendapat saya yang sederhana adalah bahwa mekanisme apa pun yang berakhir dengan Docker Compose mengetahui tentang ketergantungan antar container bertentangan dengan Pemisahan Kekhawatiran. Docker Compose bertanggung jawab menjalankan container A dan B. Container A dan B bertanggung jawab atas layanannya sendiri. Jika B bergantung pada A untuk bekerja dengan benar, maka tanggung jawab B untuk menunggu A dalam kondisi kerja. Seperti yang telah dikatakan dalam diskusi, ini dapat dilakukan melalui waktu tunggu, coba lagi atau apa pun, tetapi ini adalah masalah B, bukan Docker Compose atau A. SoC yang sangat penting untuk independensi layanan dan penskalaan yang tepat.

Apakah ada upaya untuk ide Anda 3 @aanand ? Akan lebih baik untuk mengetahui jika ada kemajuan, kedengarannya seperti awal yang menjanjikan yang akan membantu beberapa kasus penggunaan yang sangat umum bahkan jika bukan solusi yang sempurna.

+1

+1

Mungkin saya salah tapi args: buildno: dapat memesan wadah di docker-compose.yml versi 2?

Saya cenderung setuju bahwa ini adalah masalah yang tidak termasuk dalam Compose. Dockerize @jwilder yang sangat baik baru saja mendapat dukungan untuk menunggu kontainer dependen dan Anda dapat menentukan protokol / port yang Anda tunggu. Saya akan menyarankan ini sesuai dengan sebagian besar kasus penggunaan yang dijelaskan di sini:

api:
  build: .
  ports:
   - "8000:80"
  expose:
  - "80"

test:
  build: test
  command: dockerize -wait http://api:80 -wait tcp://db:5432 somecommand -some arg -another arg2
  links:
    - api:api

Idealnya kami menggunakan Docker Events API untuk secara otomatis mendeteksi ini, tetapi itu berarti setiap kontainer juga memerlukan akses ke runtime Docker yang mungkin tidak layak / sesuatu yang kami inginkan.

Menurut saya, penantian harus dilakukan di luar penulisan. Dalam dev saya, saya akan menggunakan hybrid dari apa yang @mefellows disarankan dan timercheck.io halaman status. Saya pikir itu akan memberi saya apa yang saya butuhkan tanpa terburu-buru menggunakan RabbitMQ atau yang serupa.

Kami menggunakan entrypoint skrip shell yang menunggu port terbuka, dengan batas waktu 15 detik:

#!/usr/bin/env bash

# wait for db to come up before starting tests, as shown in https://github.com/docker/compose/issues/374#issuecomment-126312313
# uses bash instead of netcat, because netcat is less likely to be installed
# strategy from http://superuser.com/a/806331/98716
set -e

echoerr() { echo "$@" 1>&2; }

echoerr wait-for-db: waiting for db:5432

timeout 15 bash <<EOT
while ! (echo > /dev/tcp/db/5432) >/dev/null 2>&1;
    do sleep 1;
done;
EOT
RESULT=$?

if [ $RESULT -eq 0 ]; then
  # sleep another second for so that we don't get a "the database system is starting up" error
  sleep 1
  echoerr wait-for-db: done
else
  echoerr wait-for-db: timeout out after 15 seconds waiting for db:5432
fi

exec "$@"

Ini harus diselesaikan dengan yang akan datang (dan tampaknya segera dengan dokumen diperbarui) depend_on , ya?

Nggak. depends_on hanya memesan. Untuk benar-benar menunda dimulainya penampung lain, perlu ada beberapa cara untuk mendeteksi ketika suatu proses selesai menginisialisasi dirinya sendiri.

Ah, terima kasih atas klarifikasinya. =)

Saya telah menulis utilitas baris perintah bash murni yang disebut tunggu untuk itu yang dapat disertakan dalam penerapan buruh pelabuhan untuk membantu menyinkronkan penerapan layanan.

Bagi saya, bukanlah ide yang baik untuk melakukan hard-code pada kumpulan "pemeriksaan ketersediaan" yang sewenang-wenang. Ada banyak situasi yang khusus untuk satu jenis penerapan dan Anda tidak akan pernah bisa mencakup semuanya. Sebagai contoh, di aplikasi multi-penampung saya, saya perlu menunggu pesan log tertentu muncul di file log tertentu - setelah itu layanan penampung akan siap.
Sebaliknya yang dibutuhkan adalah SPI yang bisa saya implementasikan. Jika Docker menyediakan beberapa contoh implementasi untuk kasus penggunaan yang paling sering (misalnya koneksi TCP), tidak apa-apa. Tetapi perlu ada cara bagi saya untuk menyambungkan fungsionalitas saya sendiri dan meminta Docker menyebutnya.
Docker Compose sangat tidak berguna bagi saya sebagai produk secara keseluruhan, jika saya tidak dapat menjalankan container saya dengan andal. Sehingga dibutuhkan "kesiapan SPI" yang stabil dan seragam. Dan "siap" tidak boleh berupa boolean, karena mungkin ada lebih banyak tingkat kesiapan (seperti: "sekarang Anda bisa membaca" dan "sekarang Anda bisa menulis").

@realulim Tulisan yang bagus. Saya sepenuhnya setuju dengan gagasan untuk membiarkan kami mendefinisikan apa arti status "siap" layanan melalui plugin. Saya juga berpikir itu ide yang baik untuk memiliki default untuk plugin yang hanya memeriksa bahwa layanan mendengarkan koneksi http / tcp. Itu akan mencakup sebagian besar kasus di sana.

Inilah yang saya dapatkan, dalam file entrypoint;

until netcat -z -w 2 database 5432; do sleep 1; done
# do the job here, database host on port 5432 accepts connections

@bayu_joo
Saya melakukan sesuatu yang sangat mirip dengan MySQL. "database" dalam hal ini adalah link dalam file tulis.

if [[ "$APP_ENV" == "local" ]]; then
    while ! mysqladmin ping -h database --silent; do
        sleep 1
    done
    # Load in the schema or whatever else is needed here.
fi

Ada beberapa komentar di utas ini yang mengklaim bahwa pengurutan permulaan hanyalah sebagian dari pemulihan kesalahan tingkat aplikasi, yang harus ditangani oleh aplikasi Anda. Saya ingin memberikan satu contoh untuk mengilustrasikan di mana hal ini mungkin tidak selalu terjadi. Pertimbangkan jika beberapa layanan bergantung pada database berkerumun, dan setiap kali kuorum hilang karena crash dll, Anda _not_ ingin mencoba kembali secara otomatis dari aplikasi. Ini bisa menjadi kasus misalnya jika pemulihan database memerlukan beberapa langkah manual, dan Anda memerlukan layanan untuk tetap turun sampai langkah-langkah tersebut dilakukan.

Sekarang logika penanganan kesalahan aplikasi mungkin sangat berbeda dari logika startup:

  • Jika db turun karena kita baru memulai, tunggu sampai tersedia.
  • Jika db turun karena macet, catat kesalahan kritis dan mati.

Ini mungkin bukan skenario yang paling umum, tetapi Anda terkadang melihat pola ini. Dalam kasus ini, pengelompokan digunakan untuk menyelesaikan masalah "jaringan tidak dapat diandalkan" dalam kasus umum, yang mengubah beberapa ekspektasi seputar kondisi kesalahan yang harus dicoba ulang dalam aplikasi. Cluster crash cukup jarang, dan secara otomatis memulai ulang bisa cukup berisiko, bahwa restart layanan secara manual lebih disukai daripada mencoba kembali dalam aplikasi. Saya menduga ada skenario lain juga yang mungkin menantang asumsi tentang kapan harus mencoba lagi.

Secara lebih umum, saya mengklaim bahwa pengurutan startup dan penanganan error tidak selalu setara, dan kerangka kerja menyediakan fitur (opsional) untuk mengelola urutan startup. Saya bertanya-tanya apakah ini termasuk dalam mesin galangan, daripada menulis. Ini bisa dibutuhkan kapan saja buruh pelabuhan dimulai, terlepas dari apakah penulisan digunakan.

Ada diskusi yang dimulai pada repo mesin buruh pelabuhan dalam proposal https://github.com/docker/docker/issues/21142 untuk menambahkan dukungan untuk pemeriksaan kesehatan. Setelah dukungan ini tersedia, Compose dapat menyediakan cara untuk mengkonfigurasinya, dan menggunakannya untuk start up yang tertunda.

Bagaimana dengan menggunakan sistem file untuk memeriksa keberadaan file?

ready_on: /tmp/this_container_is_up_and_ready

Dengan cara itu, terserah developer container untuk memutuskan kapan semuanya NAIK, tetapi penulisan dapat menunggu hingga container menyatakan dirinya siap. Ini adalah konvensi eksplisit, tetapi dapat dengan mudah ditambahkan sebagai lapisan tambahan ke gambar yang tidak memiliki perilaku itu ..

Dukungan bawaan untuk pemeriksaan kesehatan akan baik; Sementara itu, inilah peretasan yang saya lakukan di penyiapan penulisan buruh pelabuhan lokal:

    nginx:
        image: nginx:latest
        command: /bin/bash -c "sleep 2 && echo starting && nginx -g 'daemon off;'"
        ...

(Dalam produksi, aplikasi saya proksi ke beberapa server upstream yang sudah berjalan menggunakan proxy_pass ; dalam dev dan pengujian lokal, saya memulai instance docker ini, dan nginx perlu menunggu sebentar untuk memulai, kalau tidak crash dan mati. Hal daemon off menjaga nginx dalam satu proses, jika tidak buruh pelabuhan akan menghentikan kontainer segera setelah proses induk memunculkan anak daemonnya.)

Hanya untuk menambahkan dua sen saya, jika Anda kebetulan menggunakan alat build ANT itu datang dengan dukungan bawaan untuk menunda eksekusi sampai soket tertentu terbuka.

Server CI Jenkins kami memutar kontainer proyek dengan Docker Compose lalu menjalankan ANT dari dalam kontainer utama, seperti ini:

docker-compose up -d
docker exec -it projectx-fpm-jenkins ant -f /var/www/projectX/build.xml

Ini adalah bagian konfigurasi yang relevan dari file docker-compose.yml. Perhatikan bahwa, seperti dibahas di atas, membuat fpm bergantung pada mysql tidak cukup untuk menjamin bahwa layanan MySQL akan siap saat dibutuhkan.

version: '2'
services:
  nginx:
    build: ./docker/nginx
    depends_on:
      - fpm
  fpm:
    build: ./docker/fpm
    depends_on:
      - mysql
  mysql:
    image: mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=projectx
      - MYSQL_DATABASE=projectx

Tapi Anda bisa menunggu selama tugas ANT:

<!-- other targets... -->

<target name="setup db">
    <!-- wait until the 3306 TCP port in the "mysql" host is open -->
    <waitfor>
        <socket server="mysql" port="3306"/>
    </waitfor>

    <exec executable="php">
        <arg value="${consoledir}/console"/>
        <arg value="doctrine:database:create"/>
        <arg value="--no-interaction"/>
    </exec>
</target>

@kulbida Itu berhasil, terima kasih. Sesuatu yang sedikit lebih cepat:

while ! nc -w 1 -z db 5432; do sleep 0.1; done

_depends_on_ mungkin menyelesaikan masalah.
Dari dokumentasi docker-compose .
Ketergantungan ekspres antar layanan, yang memiliki dua efek:

  1. buruh pelabuhan-menulis akan memulai layanan dalam urutan ketergantungan. Dalam contoh berikut, db dan redis akan dimulai sebelum web.
  2. SERVICE docker-compose up akan secara otomatis menyertakan dependensi SERVICE. Dalam contoh berikut, web pembuat galangan-galangan juga akan membuat dan memulai db dan redis.

versi: '2'
jasa:
web:
membangun:.
tergantung pada:
- db
- redis
redis:
gambar: redis
db:
gambar: postgres

@alexch : pada uji kinerja sisi pelanggan (layanan mikro yang dirutekan melalui nginx +). Uji nginx Dockerized - penurunan beban dari sangat tinggi ke mendekati nol rendah diulang setiap 1-2 menit. Akhirnya memutuskan untuk menggunakan Nginx non-docker yang dijalankan sebagai VM (hanya karena perbedaan kinerja yang besar), mungkin masalah plugin driver jaringan / libNetwork.

@syamsathyan depends_on tampaknya tidak membantu.

@skorokithakis , @kulbida ini adalah solusi yang bagus. Sayangnya, netcat tidak tersedia secara default di salah satu layanan yang saya perlukan untuk terhubung ke database saya (termasuk postgres ). Apakah Anda mengetahui metode alternatif?

@nottrobin Saya khawatir tidak, saya baru saja menginstalnya di gambar saya: /

@nottrobin tim saya sedang mengerjakan ini, akan memberi tahu Anda dalam satu atau dua hari!

Bagi mereka yang memiliki pesta baru-baru ini, ada solusi bebas netcat (terinspirasi oleh: http://stackoverflow.com/a/19866239/1581069):

while ! timeout 1 bash -c 'cat < /dev/null > /dev/tcp/db/5432'; do sleep 0.1; done

atau versi yang lebih pendek:

while ! timeout 1 bash -c 'cat < /dev/null > /dev/tcp/db/5432' >/dev/null 2>/dev/null; do sleep 0.1; done

@typekpb yang bekerja dengan sempurna. Terima kasih!

Sekarang HEALTHCHECK dukungan digabungkan ke hulu sesuai https://github.com/docker/docker/pull/23218 - ini dapat dianggap untuk menentukan kapan wadah sehat sebelum memulai berikutnya dalam urutan. Setengah dari teka-teki terpecahkan :)

Sekarang setelah dukungan HEALTHCHECK digabungkan ke hulu sesuai dengan buruh pelabuhan / buruh pelabuhan # 23218 - ini dapat dipertimbangkan untuk menentukan kapan wadah sehat sebelum memulai pesanan berikutnya. Setengah dari teka-teki terpecahkan :)

Kelihatan bagus. Bagaimana cara menerapkannya di docker-compose.yml ?

Kelihatan bagus. Bagaimana cara menerapkannya di docker-compose.yml?

Bagian lain dari teka-teki tersebut adalah memiliki jam tangan tulis-buruh pelabuhan untuk wadah yang sehat, dan menggunakan sesuatu seperti sintaks depend_on yang disebutkan lebih lanjut dalam masalah ini. Akan membutuhkan tambalan untuk menulis galangan agar semuanya bekerja.

Perhatikan juga bahwa fitur pemeriksaan kesehatan di Docker saat ini belum dirilis, jadi mungkin perlu menyelaraskan dengan siklus rilis Docker / Docker Compose.

Saya menulis perpustakaan js yang memiliki metode .waitForPort() . Sama seperti yang disebutkan sebelumnya, ini mungkin tidak berfungsi untuk semua situasi, tetapi dapat berfungsi dengan baik untuk sebagian besar kasus penggunaan.
Lihat blog saya .

Penggabungan HEALTHCHECK adalah berita bagus.

Sementara itu, dokumen ini menjelaskan masalah tersebut dan beberapa solusi.

@pablofmorales Tidak, karena depends_on hanya memeriksa bahwa container sudah habis.

Beberapa daemon memerlukan waktu ekstra untuk bootstrap sendiri dan mulai mendengarkan port dan alamat yang ditetapkan, terutama MySQL.

Saya masih berpikir deklarasi "READY_ON" masih yang terbaik secara keseluruhan. Ini meninggalkan keputusan tentang kapan sesuatu siap untuk penampung itu sendiri, apa pun gambarnya, itu eksplisit dalam keikutsertaan dan fungsi sumber daya (dalam penampung) di Docker Remote API memastikan perubahan minimal yang diperlukan.

Perilaku saat container "naik" adalah satu-satunya pengaruh yang seharusnya dimiliki. Ini hanya akan melaporkan sebagai "naik" jika file READY_ON ada.

Saya pikir ini adalah 90% dari perilaku yang dibicarakan semua orang. Saya pikir "healthcheck" di sini digabungkan menjadi 2 peristiwa berbeda, tetapi mencoba menjejalkannya menjadi satu. Yang satu "siap" untuk rangkaian peristiwa saat menjalankan infrastruktur, yang lainnya adalah "kesehatan" sehingga infrastruktur dapat dipertahankan.

"Siap" benar-benar merupakan tempat yang tepat bagi buruh pelabuhan untuk membantu. Adapun "kesehatan", itu sangat bervariasi dalam hal sistem, saya pikir itu tergantung pada wadah untuk mengatasinya.

Untuk alternatif yang lebih baik untuk healthcheck, Anda mungkin ingin melihat sesuatu seperti containerpilot yang tidak hanya mencakup kesehatan, tetapi juga penemuan dan pemantauan layanan. https://github.com/joyent/containerpilot

Ya, ini adalah perbedaan yang akurat dan penting. Namun, bagaimana container menulis file itu tanpa gambar menjadi jauh lebih rumit? Tampaknya bagi saya itu akan membutuhkan skrip pembungkus untuk setiap wadah yang ingin menggunakan ini.

Nah, Anda harus memulai skrip untuk menginisialisasi instance ... hal terakhir yang perlu dilakukan skrip adalah menyentuh file. Bagi saya, itu tampak jauh lebih mudah daripada mencoba menjalankan eksekutif di mesin jarak jauh untuk melakukan pemeriksaan kesehatan. Setidaknya dengan file sentuh, itu bisa ditonton, dll sepenuhnya melalui API secara pasif tanpa perlu masuk ke konteks penampung.

Saya setuju, tetapi banyak wadah tidak menggunakan skrip, mereka hanya menginstal layanan seperti Postgres atau Redis dan membiarkannya mulai tanpa menontonnya.

Dalam kasus saya, saya menggunakan Kong API Gateway

Sebelum menjalankan wadah kong saya hanya memeriksa apakah Cassandra sedang bekerja dengan skrip ini

while true; do
    CHECK=`kong-database/check`
    if [[ $CHECK =~ "system.dateof" ]]; then
        break
    fi
    sleep 1;
done

file cek berisi ini

#!/bin/bash
docker cp cassandra-checker kong-database:/root/
docker exec -i kong-database cqlsh -f /root/cassandra-checker

cassandra-checker hanyalah pertanyaan sederhana

SELECT dateof(now()) FROM system.local ;

Tentu, tetapi alternatifnya adalah healthcheck, yang membutuhkan skrip yang harus Anda tulis, jadi tidak ada perbedaan overhead. Ini juga merupakan keikutsertaan eksplisit, yang berarti Anda menyatakan menginginkan perilaku ini. Adapun sesuatu yang tidak menjalankan skrip, Anda selalu dapat memiliki jalur ready_on untuk memeriksa file pid atau soket unix; yang tidak membutuhkan skrip.

Itu benar, kamu benar.

Memeriksa keberadaan file mungkin baik-baik saja untuk banyak kasus, tetapi memaksa container untuk menggunakan skrip startup ketika mereka tidak membutuhkannya adalah gangguan. Mengapa tidak ada pemeriksaan untuk kondisi lain yang sangat sederhana? Terutama berguna akan menunggu sampai proses mendengarkan pada port tcp tertentu.

Ide ini ikut serta, jadi tidak ada pemaksaan apa pun. Faktanya, Anda secara eksplisit mengatakan apa yang seharusnya diharapkan.

Sebuah port tcp yang mendengarkan mungkin tidak cukup untuk memberi tahu ketika sebuah kontainer telah diinisialisasi karena mungkin ada banyak data pengaturan yang perlu dijalankan. Sial, jika Anda terhubung ke penampung postgres terlalu cepat, bahkan melalui tcp, Anda akan mendapatkan kesalahan yang menyatakan bahwa db belum siap.

Jika saya memahami Anda dengan benar, itu "ikut serta, atau Anda tidak dapat menggunakan fitur ini". Ergo, jika saya membutuhkan fitur ini dan aplikasi saya tidak menggunakan file pid, saya terpaksa menggunakan skrip startup.

Untuk MySQL (kasus OP), setelah mendengarkan, itu siap. Mereka bersusah payah untuk memastikan itu benar, mungkin untuk kasus seperti ini. Pendapat saya adalah bahwa mungkin ada daftar singkat kondisi yang dapat disebutkan sedemikian rupa sehingga Anda dapat "ikut serta" mengonfigurasi pemeriksaan siap terhadap salah satu dari kondisi tersebut. Saya tidak melihat alasan itu harus dilakukan dengan satu dan hanya satu cara.

Untuk mysql, setelah mendengarkan, itu belum siap. Dalam kasus satu node sederhana itu akan siap, tetapi jika Anda memiliki lebih dari satu node, maka itu pasti belum siap. Saya mengerti apa yang Anda maksud dengan "satu dan hanya satu cara", tapi saya pikir sebagai abstraksi dasar itu sempurna. Saya melihatnya lebih sebagai tempat di mana Anda dapat menerapkan perkakas apa pun yang Anda inginkan. Heck, skrip Anda bahkan dapat berkomunikasi dengan layanan eksternal dan meminta mereka memverifikasi penampungnya, dalam hal ini layanan eksternal Anda dapat memberi tanda kepada agen penampung Anda untuk menulis file. Fleksibilitas ftw.

Jika Anda mencoba sesuatu dalam daftar "kondisi" ini, SELALU akan ada kasus yang tidak berhasil. Namun menyentuh file akan selalu berfungsi, karena gambar tahu kapan ia yakin sudah siap (oh, saya harus menunggu di host lain, saya perlu file untuk diunduh, saya perlu memastikan $ external_service juga tersedia, saya rentangkan benar, tetapi untuk beberapa alasan saya tidak memiliki izin yang benar ke database, mengapa gambar ini hanya dapat dibaca ... dll. dll.

Skrip semacam ini sudah ada di mana-mana ... memang sudah diperlukan untuk menulis skrip ini karena kami belum memiliki fungsi seperti ini sebelumnya. Jadi memasukkan skrip seperti ini minimal, karena kemungkinan skrip sudah ada.

Kasus lain yang mungkin terjadi, adalah Anda memiliki sesuatu seperti chef atau kemungkinan melawan host itu dan kemudian menulis file.

Jika ini adalah pertanyaan tentang pemeriksaan sisi Docker, maka sesuatu seperti;

UPCHECK --port=7474 --interval=0.5s --response="Please log in"

Sebagai catatan, saya pikir solusi file memiliki banyak manfaat, tetapi juga memperkenalkan kompleksitas.
80% dari waktu, memverifikasi respons tcp akan berfungsi dengan baik.

baik ... saya kira:

UPCHECK --file=/tmp/container_is_ready --interval=0.5s --timeout=2m

Sama saja.

Saya sebenarnya sedang mengerjakan implementasi ulang docker-compose yang menambahkan fungsionalitas untuk menunggu kondisi tertentu. Ini menggunakan libcompose (jadi saya tidak perlu membangun kembali interaksi buruh pelabuhan) dan menambahkan banyak perintah konfigurasi untuk ini. Lihat di sini: https://github.com/dansteen/controlled-compose

Perhatikan, bahwa kode sudah selesai, tetapi saya menunggu beberapa masalah upstream diselesaikan sebelum ini benar-benar dapat digunakan.

Goss dapat digunakan sebagai shim yang cukup fleksibel untuk menunda startup kontainer, saya telah menulis posting blog yang menjelaskan bagaimana ini dapat dilakukan dengan sedikit perubahan pada gambar Anda di sini:

Kubernetes memiliki konsep init-containers. Saya ingin tahu apakah compose / swarm akan mendapat manfaat dari konsep serupa.

+1

Saya pikir lebih baik membiarkan layanan yang Anda tampilkan pada sebuah wadah memutuskan apakah itu siap atau mampu mengekspos layanannya atau tidak.

Misalnya untuk aplikasi PHP mungkin bergantung pada koneksi MySQL. Jadi pada ENTRYPOINT PHP Container, saya menulis sesuatu seperti ini.

#!/bin/bash
cat << EOF > /tmp/wait_for_mysql.php
<?php
\$connected = false;
while(!\$connected) {
    try{
        \$dbh = new pdo( 
            'mysql:host=mysql:3306;dbname=db_name', 'db_user', 'db_pass',
            array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
        );
        \$connected = true;
    }
    catch(PDOException \$ex){
        error_log("Could not connect to MySQL");
        error_log(\$ex->getMessage());
        error_log("Waiting for MySQL Connection.");
        sleep(5);
    }
}
EOF
php /tmp/wait_for_mysql.php
# Rest of entry point bootstrapping

Dengan cara ini, saya dapat menambahkan logika apa pun untuk memastikan bahwa dependensi layanan yang saya ungkapkan, yaitu php telah diselesaikan.

Nabin Nepal schrieb:

Saya pikir lebih baik membiarkan layanan yang Anda tampilkan pada sebuah wadah memutuskan apakah itu siap atau mampu mengekspos layanannya atau tidak.

Anda tentu saja dapat melakukan hardcode perilaku ini ke dalam setiap container yang menggunakan file
Wadah MySql. Tetapi jika sesuatu di layanan MySql Anda berubah, maka Anda berubah
mengubah semua container dependen, belum lagi pengodean berulang
dibutuhkan di masing-masing. Ini tidak KERING, tidak ada kontrak yang stabil dan dengan demikian akan terjadi
menyebabkan sistem rapuh.

Dari sudut pandang pengerjaan perangkat lunak harus ada semacam
"Container Readiness SPI", yang dapat diterapkan oleh pengembang container. Di
sisi lain harus ada "Container Readiness API", yaitu
layanan dapat bergantung.

Ulrich

@realulim Saya setuju bahwa setiap perubahan dalam wadah MySQL harus direplikasi atau disebarkan ke semua wadah yang terpengaruh atau tertaut.

Namun, jika yang diubah adalah tentang parameter seperti DB_HOST, DB_NAME, DB_USER dan DB_PASSWORD. Ini bisa dikirimkan sebagai ARG (argumen) dan dibagikan oleh semua wadah terkait. Jika Anda menggunakan file docker-compose.yml , perubahan terjadi pada satu file.

Dan setuju sepenuhnya bahwa memiliki API untuk memeriksa kesiapan wadah menjadi cara nyata untuk menyelesaikan ini, tetapi saya masih percaya bahwa layanan yang diekspos akan menjadi kandidat yang lebih baik untuk menyatakan ini.

solusi until nc -z localhost 27017; do echo Waiting for MongoDB; sleep 1; done

@ piotr-s-brainhub Dari komentar di atas disebutkan bahwa memiliki open port tidak berarti layanan sudah siap.

Bisakah kita memiliki kondisi kesiapan opsional yang dapat dipicu oleh log, pembukaan port, atau penundaan waktu? Sesuatu seperti:

ready_when:
  in_logs: `MySQL init process done`
  ports_open:
  - 3306

Saya baru menyadari bahwa menunggu wadah ketergantungan siap dapat dengan mudah diimplementasikan dengan alat seperti ansible. Apakah ada yang menggunakan pendekatan itu? Bisakah Anda dengan mudah mengganti buruh pelabuhan dengan ansible / chef / puppet? Adakah proyek di github yang mendemonstrasikan pendekatan ini?

Catatan: Saya memahami pentingnya menulis layanan tangguh yang dapat berjalan bahkan ketika dependensinya tidak tersedia saat ini. Bukan itu pertanyaannya.

Saya menyelesaikan ini saat ini dengan alat yang saya tulis: https://github.com/betalo-sweden/await

Itu bisa menunggu sampai daftar sumber daya tertentu tersedia, dan melanjutkan dengan apa yang ingin Anda lanjutkan, baik dengan membuka perintah berikutnya secara implisit atau memanggilnya secara eksplisit.

@ djui , apa yang dilakukan await saat menunggu sumber daya tertentu?

@derekmahar Itu polling. Ini memiliki batas waktu default 60 detik. Setiap kali tidak dapat melihat sumber daya, itu hanya akan mencoba lagi dalam interval 1 detik. Saat ini itu tidak melakukan deteksi sumber daya secara bersamaan, jadi itu berurutan, tetapi itu ternyata cukup bagus dan bisa diperbaiki.

Saya menggunakannya dalam skenario berikut:

Saya menjalankan infrastruktur pembuat pelabuhan dan kemudian menjalankan driver uji integrasi. Layanan driver akan dimulai hanya setelah semua komponen di infrastruktur tersedia, menggunakan await; jadi tunggu akhirnya memanggil perintah run driver.

Berikut cara untuk melakukan ini dengan direktif Docker HEALTHCHECK baru menggunakan make:

https://gist.github.com/mixja/1ed1314525ba4a04807303dad229f2e1

[PEMBARUAN: inti yang diperbarui untuk menangani jika container keluar dengan kode kesalahan, karena Docker 1.12 dengan agak bodoh melaporkan status Healthcheck pada container yang dihentikan sebagai "mulai"]

Terima kasih @mixja , solusi bagus.

@mixja , solusi bagus! Itulah fungsionalitas yang saya harapkan keluar dari kotak. Tapi sekarang pertanyaannya adalah jika Anda memulai container Anda secara manual, mengapa Anda membutuhkan docker-compose sama sekali?

Untuk pengujian saya menggunakan https://github.com/avast/docker-compose-gradle-plugin dan menggunakan Docker healthcheck juga - tidak ada lagi jeda buatan, pembuatan lebih cepat.

@korya - Docker compose sebenarnya bukan alat orkestrasi - ini lebih merupakan spesifikasi lingkungan dan alat manajemen. Saya menggunakan Make untuk menyediakan orkestrasi gaya prosedural melalui Docker Compose dan Docker (dan alat lain sesuai kebutuhan). Kombinasi Make, Docker dan Docker Compose sangat kuat dan Anda dapat mencapai banyak skenario berbeda dengan blok bangunan ini.

@mixja yah, semoga kamu benar. Tapi seperti yang ditunjukkan banyak orang di utas ini, fungsionalitas orkestrasi sangat dibutuhkan dalam lingkungan pengujian, dan ketika ada docker-compose di kotak alat Anda, sangat menggoda untuk meminta fungsionalitas semacam ini dari docker-compose.

Memang, menurut dokumen "Compose adalah alat untuk mendefinisikan dan menjalankan aplikasi Docker multi-container". Meskipun tidak mengatakan bahwa compose adalah alat orkestrasi, menurut saya dari sudut pandang pengguna (misalnya saya sendiri) wajar untuk mengharapkan dari "alat untuk mendefinisikan dan menjalankan aplikasi Docker multi-container" untuk mendukung manajemen ketergantungan dasar antara container yang dikelola keluar dari kotak.

Saya tidak mengatakan bahwa alat tersebut harus mendukungnya. Yang ingin saya katakan adalah bahwa sangat wajar untuk mengharapkannya. Jika tidak, setiap orang harus menemukan cara super cerdas mereka untuk melakukannya. Faktanya, kami menggunakan skrip bash yang melakukan sesuatu yang mirip dengan apa yang dilakukan makefile Anda.

@mixja @korya Saya ingin meningkatkan alat saya menunggu dan ingin meminta tanggapan Anda tentang apa yang Anda sediakan versi Makefile yang hilang / lebih nyaman / mengaktifkan lebih dari await .

Tampaknya versi healthcheck + make tampak seperti tampilan "global", tidak ada penampung tunggal yang mengetahui status global (tetapi makefile tahu) dan await adalah tampilan "lokal", setiap penampung yang diaktifkan mengetahui (hanya) apa yang perlu diketahui, mirip dengan depends_on atau links . Selain itu, Anda lebih memilih untuk mengirimkan container dengan alat yang diperlukan untuk healthcheck (yang terkadang merupakan default, misalnya mysqlshow ) dan membiarkan Dockerfile tidak tersentuh. Selain itu Anda tampaknya menggunakan docker-compose tidak hanya untuk komposisi lagi tetapi terutama untuk konfigurasi fleksibel (misalnya docker-compose up -d mysql harus setara dengan docker run -d -e ... -v ... -p ... mysql ).

Hai @ djui - ini mungkin sudut pandang filosofis, tetapi saya pikir keseluruhan premis HEALTHCHECK mempromosikan perilaku yang benar - yaitu wadah dapat menyediakan sarana untuk membangun kesehatan wadah, tanpa ketergantungan eksternal.

Ini tidak mengurangi nilai dari memiliki sesuatu konektivitas verifikasi eksternal, namun saya biasanya akan menjalankan serangkaian tes penerimaan untuk mencakup ini karena Anda ingin memverifikasi konektivitas dan lebih banyak lagi (yaitu fungsionalitas aplikasi). Tentu saja Anda tidak dapat secara umum menjalankan tingkat pengujian ini sampai lingkungan yang lengkap telah ditetapkan dan cakupan alat await dan pendekatan lain yang telah saya gunakan sebelumnya (Buku pedoman yang mungkin dibungkus dengan agent container) benar-benar fokus untuk mendapatkan pengaturan lingkungan yang diatur dengan benar (bukan tujuan akhir dari pengujian penerimaan) dan sampai sekarang benar-benar satu-satunya pendekatan yang tersedia di dunia Docker.

Dengan Docker 1.12 kita sekarang memiliki sarana untuk introspeksi lingkungan Docker dan kemampuan untuk menggunakan konstruksi mapan (yaitu mekanisme bash / shell) untuk "menunggu" keadaan tertentu, tentu saja selama container kita telah menetapkan health check mereka sendiri . Saya melihat nilai lebih dalam memanfaatkan kemampuan asli platform dan mendorong pemilik kontainer untuk menentukan health check mereka sendiri, daripada mengandalkan pendekatan eksternal historis (saya telah memulai proses aplikasi saya, ini bukan lagi masalah saya) yang harus kami lakukan resor untuk.

Sebagai analogi terkait pertimbangkan AWS CloudFormation dan konsep grup penskalaan otomatis dan mengatur pembaruan berkelanjutan. Bagaimana CloudFormation mengetahui jika instance baru "sehat" siap digunakan dan kita dapat menghentikan instance lama dan menjalankan instance baru lainnya? Apakah kita menulis healthcheck eksternal atau mengandalkan instance itu sendiri untuk memberi sinyal kesehatan? Jawabannya adalah yang terakhir, itu berarti pemilik instans dapat menetapkan kriteria keberhasilan apa pun yang diperlukan untuk instansnya, dan kemudian memberi sinyal ke sistem orkestrasi menyeluruh (yaitu CloudFormation) bahwa instans tersebut "sehat".

Berkenaan dengan komentar Anda tentang Docker Compose - ini adalah alat yang dapat menyediakan kedua aspek yang Anda sebutkan. Bagian docker-compose.yml adalah spesifikasi lingkungan komposisi keadaan yang diinginkan, sementara berbagai perintah docker-compose menyediakan kemampuan untuk berinteraksi dengan lingkungan dalam beberapa cara. Untuk saat ini kami membutuhkan alat orkestrasi eksternal karena pada dasarnya docker-compose tidak melakukan manajemen ketergantungan antar layanan dengan cukup baik. Karena docker-compose mendapatkan fitur seperti dukungan pemeriksaan kesehatan asli, tujuan dari satu perintah docker-compose up akan lebih realistis, dengan asumsi kita akan dapat menentukan, misalnya layanan harus ditandai sehat sebelum itu dianggap "naik", yang berarti layanan yang bergantung kami secara efektif menunggu sampai ketergantungan itu sehat.

@mixja Terima kasih atas penjelasan detailnya. kupikir

Saya melihat nilai lebih dalam memanfaatkan kemampuan asli platform

adalah poin yang baik / utama. Tunggu saja Docker Compose memanfaatkan healthcheck secara native baik di depend_on atau kunci baru, tunggu. Hanya ingin tahu apakah harus / akan melangkah lebih jauh dari itu dan pada dasarnya menurunkan penampung tertaut jika misalnya --abort-on-container-exit disetel dan pemeriksaan kesehatan selama runtime menetapkan label pemeriksaan kesehatan ke _unhealthy_.

Solusi sementara yang mungkin bagi Anda yang mencari delay functionallity untuk menjalankan tes:

Saya memiliki dua file docker-compose yml. Satu untuk pengujian dan satu lagi untuk pengembangan. Perbedaannya hanya memiliki sut container di docker-compose.test.yml . sut container habis pytest . Tujuan saya adalah menjalankan pengujian docker-compose dan jika pytest perintah di sut container gagal, jangan jalankan pengembangan docker-compose . Inilah yang saya dapatkan:

# launch test docker-compose; note: I'm starting it with -p argument
docker-compose -f docker-compose.test.yml -p ci up --build -d
# simply get ID of sut container
tests_container_id=$(docker-compose -f docker-compose.test.yml -p ci ps -q sut)
# wait for sut container to finish (pytest will return 0 if all tests passed)
docker wait $tests_container_id
# get exit code of sut container
tests_status=$(docker-compose -f docker-compose.test.yml -p ci ps -q sut | xargs docker inspect -f '{{ .State.ExitCode  }}' | grep -v 0 | wc -l | tr -d ' ')
# print logs if tests didn't pass and return exit code
if [ $tests_status = "1" ] ; then
    docker-compose -f docker-compose.test.yml -p ci logs sut
    return 1
else
    return 0
fi

Sekarang Anda dapat menggunakan kode di atas dalam fungsi apa pun pilihan Anda (milik saya disebut test ) dan lakukan seperti itu:

test
test_result=$?
if [[ $test_result -eq 0 ]] ; then
    docker-compose -f docker-compose.yml up --build -d
fi

Bekerja dengan baik untuk saya tetapi saya masih menantikan untuk melihat docker-compose mendukung hal-hal semacam itu secara native :)

+1

Mungkin hal-hal yang dianggap di luar inti dari docker-compose dapat didukung dengan mengizinkan plugin? Mirip dengan permintaan # 1341, tampaknya ada fungsionalitas tambahan yang beberapa orang anggap berguna tetapi tidak sepenuhnya selaras dengan visi saat ini. Mungkin mendukung sistem plugin seperti yang diusulkan oleh # 3905 akan menyediakan cara untuk memungkinkan fokus penulisan pada serangkaian kemampuan inti dan jika ini bukan salah satu, maka mereka yang menginginkannya untuk kasus penggunaan khusus mereka dapat menulis plugin untuk menangani kinerja up berbeda?

Alangkah baiknya dapat memiliki docker-compose bertindak sebagai titik masuk ke semua proyek yang kita miliki secara lokal di sekitar pengaturan env buruh pelabuhan, daripada perlu menambahkan skrip yang ada di depan semua untuk bertindak sebagai titik masuk default daripada orang perlu mengingat untuk menjalankan skrip untuk kasus-kasus ganjil.

Berikut cara melakukannya dengan healthcheck dan buruh pelabuhan-menulis 2.1+ :

version: "2.1"
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
    healthcheck:
      test: mysqladmin -uroot -ppassword ping
      interval: 2s
      timeout: 5s
      retries: 30
  web:
    image: nginx:latest # your image
    depends_on:
      db:
        condition: service_healthy

Di sini docker-compose up akan memulai penampung web hanya setelah penampung db dianggap sehat.

Maaf jika sudah disebutkan, tetapi saya rasa solusi lengkap belum diposting.

Berikut cara untuk PostgreSQL.

Terima kasih @Silex 👍

version: '2.1'
services:
  db:
    image: postgres:9.6.1
    healthcheck:
      test: "pg_isready -h localhost -p 5432 -q -U postgres"
      interval: 3s
      timeout: 5s
      retries: 5

@Silex sayangnya dengan versi "3" dan format ini:

    image: nginx:latest # your image
    depends_on:
      db:
        condition: service_healthy

Saya mendapatkan ERROR: The Compose file './docker-compose.yml' is invalid because: depends_on contains an invalid type, it should be an array

2.1 terus mendukungnya dan tidak akan dihentikan. 3.x terutama untuk mode layanan swarm (non lokal).

  From: Vlad Filippov <[email protected]>

Kepada: buruh pelabuhan / tulis [email protected]
Cc: mbdas [email protected] ; Sebutkan [email protected]
Dikirim: Rabu, 8 Maret 2017 11.45
Subjek: Perihal: [buruh pelabuhan / tulis] Apakah ada cara untuk menunda startup kontainer untuk mendukung layanan yang bergantung dengan waktu startup yang lebih lama (# 374)

@Silex sayangnya dengan versi "3" dan format ini: image: nginx: terbaru # gambar Anda
tergantung pada:
db:
kondisi: service_healthy
Saya mendapatkan ERROR: File Tulis './docker-compose.yml' tidak valid karena: services.auth.depends_on berisi tipe yang tidak valid, seharusnya berupa array—
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub, atau nonaktifkan utasnya.

2.1 terus mendukungnya dan tidak akan dihentikan. 3.x terutama untuk mode layanan swarm (non lokal).

Terima kasih!

@vladikoff : info lebih lanjut tentang versi 3 di https://github.com/docker/compose/issues/4305

Pada dasarnya, ini tidak akan didukung, Anda harus menjadikan container Anda toleran terhadap kesalahan alih-alih mengandalkan penulisan galangan kapal.

Saya yakin ini bisa ditutup sekarang.

Sayangnya, kondisi tidak mendukung lagi di v3. Berikut solusi yang saya temukan:

website:
    depends_on:
      - 'postgres'
    build: .
    ports:
      - '3000'
    volumes:
      - '.:/news_app'
      - 'bundle_data:/bundle'
    entrypoint: ./wait-for-postgres.sh postgres 5432

  postgres:
    image: 'postgres:9.6.2'
    ports:
      - '5432'

wait-for-postgres.sh:

#!/bin/sh

postgres_host=$1
postgres_port=$2
shift 2
cmd="$@"

# wait for the postgres docker to be running
while ! pg_isready -h $postgres_host -p $postgres_port -q -U postgres; do
  >&2 echo "Postgres is unavailable - sleeping"
  sleep 1
done

>&2 echo "Postgres is up - executing command"

# run the command
exec $cmd

@slava-nikulin custom entrypoint adalah praktik umum, ini hampir satu-satunya cara (docker native) bagaimana Anda dapat mendefinisikan dan memeriksa semua kondisi yang Anda butuhkan sebelum melihat aplikasi Anda dalam sebuah container.

Sebenarnya ada banyak perdebatan dan saya pikir dukungan 2.x untuk dukungan bersyarat untuk mengintegrasikan secara native dengan health check dan memesan startup adalah dukungan yang sangat dibutuhkan. Docker tidak mendukung pod lokal dari kontainer secara asli dan jika itu terjadi, Docker harus mendukung sesuatu yang serupa lagi seperti kubernetes misalnya menyediakan semantik.

Docker 3.x adalah seri untuk membawa dukungan swarm ke dalam penulisan dan karenanya banyak opsi telah dihapus dengan mengingat sifat terdistribusi.

2.x series mempertahankan fitur compose / local topology asli.

Docker harus mencari cara untuk menggabungkan 2 versi ini karena memaksa swarm untuk menulis dengan mengurangi kumpulan fitur penulisan bukanlah arah yang diterima.

Pada 10 Mei 2017, pukul 20:15, Slava Nikulin [email protected] menulis:

Sayangnya, kondisi tidak mendukung lagi di v3. Berikut solusi yang saya temukan:

situs web:
tergantung pada:
- 'postgres'
membangun:.
port:
- '3000'
volume:
- '.: / news_app'
- 'bundle_data: / bundle'
entrypoint: ./wait-for-postgres.sh postgres 5432

postgres:
gambar: ' postgres: 9.6.2 '
port:
- '5432'
wait-for-postgres.sh:

! / bin / sh

postgres_host = $ 1
postgres_port = $ 2
cmd = "$ @"

tunggu hingga postgres buruh pelabuhan berjalan

sementara! pg_isready -h $ postgres_host -p $ postgres_port -q -U postgres; melakukan

& 2 echo "Postgres tidak tersedia - tidur"
tidur 1
selesai

& 2 echo "Postgres sudah habis - menjalankan perintah"

jalankan perintahnya

exec $ cmd
-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub, atau nonaktifkan utasnya.

Saya bisa melakukan sesuatu seperti ini
// start.sh

#!/bin/sh
set -eu

docker volume create --name=gql-sync
echo "Building docker containers"
docker-compose build
echo "Running tests inside docker container"
docker-compose up -d pubsub
docker-compose up -d mongo
docker-compose up -d botms
docker-compose up -d events
docker-compose up -d identity
docker-compose up -d importer
docker-compose run status
docker-compose run testing

exit $?

// status.sh

#!/bin/sh

set -eu pipefail

echo "Attempting to connect to bots"
until $(nc -zv botms 3000); do
    printf '.'
    sleep 5
done
echo "Attempting to connect to events"
until $(nc -zv events 3000); do
    printf '.'
    sleep 5
done
echo "Attempting to connect to identity"
until $(nc -zv identity 3000); do
    printf '.'
    sleep 5
done
echo "Attempting to connect to importer"
until $(nc -zv importer 8080); do
    printf '.'
    sleep 5
done
echo "Was able to connect to all"

exit 0

// di file tulis buruh pelabuhan saya

  status:
    image: yikaus/alpine-bash
    volumes:
      - "./internals/scripts:/scripts"
    command: "sh /scripts/status.sh"
    depends_on:
      - "mongo"
      - "importer"
      - "events"
      - "identity"
      - "botms"

Saya memiliki masalah serupa tetapi sedikit berbeda. Saya harus menunggu MongoDB untuk memulai dan menginisialisasi set replika.
Saya melakukan semua prosedur di buruh pelabuhan. yaitu membuat dan set replika otentikasi. Tetapi saya memiliki skrip python lain di mana saya harus terhubung ke simpul utama dari set replika. Saya mendapatkan kesalahan di sana.

docker-compose.txt
Dockerfile.txt
dan dalam skrip python saya mencoba melakukan sesuatu seperti ini
for x in range(1, 4): client = MongoClient(host='node' + str(x), port=27017, username='admin', password='password') if client.is_primary: print('the client.address is: ' + str(client.address)) print(dbName) print(collectionName) break

Apakah mengalami kesulitan dalam melakukannya, ada yang tahu?

@patrickml Jika saya tidak menggunakan docker compose, Bagaimana saya melakukannya dengan Dockerfile?
Saya perlu 'cqlsh' untuk menjalankan build_all.cql saya. Namun, 'cqlsh' belum siap ... harus menunggu 60 detik untuk siap.

kucing Dockerfile

DARI penyimpanan / datastax / dse- server: 5.1.8

Root PENGGUNA

JALANKAN pembaruan apt-get
JALANKAN apt-get install -y vim

TAMBAHKAN db-scripts-2.1.33.2-RFT-01.tar / docker / cms /
COPY entrypoint.sh /entrypoint.sh

WORKDIR /docker/cms/db-scripts-2.1.33.2/
JALANKAN cqlsh -f build_all.cql

PENGGUNA dse

=============

Langkah 8/9: JALANKAN cqlsh -f build_all.cql
-> Berjalan di 08c8a854ebf4
Kesalahan koneksi: ('Tidak dapat terhubung ke server mana pun', {'127.0.0.1': kesalahan (111, "Mencoba menghubungkan ke [('127.0.0.1', 9042)]. Kesalahan terakhir: Koneksi ditolak")})
Perintah '/ bin / sh -c cqlsh -f build_all.cql' mengembalikan kode bukan nol: 1

Membutuhkan = var-lib-libvirt.mount var-lib-libvirt-images-ram.mount

Apakah halaman ini membantu?
0 / 5 - 0 peringkat