Bagaimana saya menjalankan Docker di dalam Docker dan apa hasilnya

Halo semua! Di miliknya Artikel sebelumnya, saya berjanji untuk berbicara tentang menjalankan Docker di Docker dan aspek praktis dalam menggunakan pelajaran ini. Saatnya menepati janjimu. Pengembang berpengalaman mungkin akan keberatan bahwa mereka yang membutuhkan Docker di dalam Docker cukup meneruskan soket daemon Docker dari host ke dalam container dan ini akan cukup dalam 99% kasus. Tapi jangan buru-buru melemparkan cookie ke saya, karena kita akan membahas tentang menjalankan Docker di dalam Docker. Solusi ini memiliki banyak kemungkinan penerapan dan artikel ini membahas salah satunya, jadi duduklah dan luruskan lengan di depan Anda.

Bagaimana saya menjalankan Docker di dalam Docker dan apa hasilnya

awal

Semuanya dimulai pada suatu malam di bulan September yang hujan ketika saya sedang membersihkan mesin yang saya sewa seharga $5 di Digital Ocean, yang dibekukan karena fakta bahwa Docker telah mengisi 24 gigabyte ruang disk yang tersedia dengan gambar dan wadahnya. Ironisnya, semua gambar dan wadah ini bersifat sementara dan hanya diperlukan untuk menguji kinerja aplikasi saya setiap kali versi baru perpustakaan atau kerangka kerja dirilis. Saya mencoba menulis skrip shell dan mengatur jadwal cron untuk membersihkan sampah, tetapi tidak membantu: setiap kali hal itu pasti berakhir dengan ruang disk server saya habis dan server hang (paling banter). Pada titik tertentu, saya menemukan artikel tentang cara menjalankan Jenkins dalam sebuah container dan bagaimana Jenkins dapat membuat dan menghapus pipeline build melalui soket daemon buruh pelabuhan yang diteruskan ke dalamnya. Saya menyukai ide itu, tetapi saya memutuskan untuk melangkah lebih jauh dan mencoba bereksperimen dengan menjalankan Docker secara langsung di dalam Docker. Pada saat itu, menurut saya solusi yang sepenuhnya logis adalah mengunduh gambar Docker dan membuat wadah untuk semua aplikasi yang saya perlukan untuk pengujian di dalam wadah lain (sebut saja wadah pementasan). Idenya adalah untuk memulai staging container dengan flag -rm, yang secara otomatis menghapus seluruh container dan seluruh isinya ketika dihentikan. Saya mengutak-atik image Docker dari Docker itu sendiri (https://hub.docker.com/_/docker), namun ternyata terlalu rumit dan saya tidak pernah berhasil membuatnya berfungsi sesuai kebutuhan dan saya ingin melakukannya sendiri.

Praktik. Kerucut

Saya bertekad untuk membuat wadah tersebut berfungsi sesuai kebutuhan saya dan melanjutkan eksperimen saya, yang menghasilkan banyak sekali tunas. Hasil penyiksaan diri saya adalah algoritma berikut:

  1. Kami meluncurkan wadah Docker dalam mode interaktif.

    docker run --privileged -it docker:18.09.6

    Perhatikan versi wadahnya, melangkah ke kanan atau ke kiri dan DinD Anda berubah menjadi labu. Faktanya, sering kali terjadi kerusakan ketika versi baru dirilis.
    Kita harus segera masuk ke dalam cangkangnya.

  2. Kami mencoba mencari tahu kontainer mana yang sedang berjalan (Jawab: tidak ada), tapi tetap jalankan perintahnya:

    docker ps

    Anda akan sedikit terkejut, tetapi ternyata daemon Docker malah tidak berjalan:

    error during connect: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 
    192.168.65.1:53: no such host

  3. Mari kita jalankan sendiri:

    dockerd &

    Kejutan tidak menyenangkan lainnya:

    failed to start daemon: Error initializing network controller: error obtaining controller instance: failed 
    to create NAT chain DOCKER: Iptables not found

  4. Instal paket iptables dan bash (semuanya lebih menyenangkan bekerja di bash daripada di sh):

    apk add --no-cache iptables bash

  5. Mari kita luncurkan pesta. Akhirnya kita kembali ke cangkang biasa

  6. Mari kita coba memulai Docker lagi:

    dockerd &

    Kita akan melihat lembaran log panjang yang diakhiri dengan:

    INFO[2019-11-25T19:51:19.448080400Z] Daemon has completed initialization          
    INFO[2019-11-25T19:51:19.474439300Z] API listen on /var/run/docker.sock

  7. Tekan enter. Kami kembali ke pesta.

Mulai sekarang, kita dapat mencoba meluncurkan container lain di dalam container Docker kita, tetapi bagaimana jika kita ingin meluncurkan container Docker lain di dalam container Docker kita atau terjadi kesalahan dan container tersebut mogok? Mulai dari awal lagi.

Wadah DinD sendiri dan eksperimen baru

Bagaimana saya menjalankan Docker di dalam Docker dan apa hasilnya
Untuk menghindari pengulangan langkah di atas berulang kali, saya membuat wadah DinD saya sendiri:

https://github.com/alekslitvinenk/dind

Solusi DinD yang berfungsi memberi saya kemampuan untuk menjalankan Docker di dalam Docker secara rekursif dan melakukan eksperimen yang lebih berani.
Saya akan menjelaskan salah satu eksperimen (yang berhasil) dengan menjalankan MySQL dan Nodejs sekarang.
Yang paling tidak sabar bisa melihat bagaimana keadaannya di sini

Jadi mari kita mulai:

  1. Kami meluncurkan DinD dalam mode interaktif. Dalam versi DinD ini, kita perlu memetakan secara manual semua port yang dapat digunakan oleh container anak kita (saya sudah mengerjakannya)

    docker run --privileged -it 
    -p 80:8080 
    -p 3306:3306 
    alekslitvinenk/dind

    Kami masuk ke bash, dari sana kami dapat segera mulai meluncurkan container anak.

  2. Luncurkan MySQL:

    docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysql

  3. Kami terhubung ke database dengan cara yang sama seperti kami terhubung secara lokal. Mari kita pastikan semuanya berfungsi.

  4. Luncurkan wadah kedua:

    docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-server

    Harap dicatat bahwa pemetaan port akan tepat 8080:8080, karena kita telah memetakan port 80 dari host ke container induk ke port 8080.

  5. Kami pergi ke localhost di browser, pastikan server merespons β€œHalo Dunia!”

Dalam kasus saya, percobaan dengan container Docker bersarang ternyata cukup positif dan saya akan terus mengembangkan proyek dan menggunakannya untuk pementasan. Menurut saya ini adalah solusi yang jauh lebih ringan daripada Kubernetes dan Jenkins X. Tapi ini adalah pendapat subjektif saya.

Saya pikir itu saja untuk artikel hari ini. Pada artikel berikutnya saya akan menjelaskan lebih detail eksperimen dengan menjalankan Docker secara rekursif di Docker dan memasang direktori jauh ke dalam container bersarang.

PS Jika menurut Anda proyek ini bermanfaat, silakan beri bintang di GitHub, fork, dan beri tahu teman Anda.

Sunting1 Kesalahan yang diperbaiki, fokus pada 2 video

Sumber: www.habr.com

Tambah komentar