GNU/Linux >> Belajar Linux >  >> Linux

Memperbarui Kontainer Docker Dengan Nol atau Waktu Henti Minimum

Misalkan Anda menjalankan layanan dalam wadah dan ada versi baru layanan yang tersedia melalui gambar buruh pelabuhan mereka. Dalam kasus seperti itu, Anda ingin memperbarui wadah Docker.

Memperbarui wadah buruh pelabuhan bukanlah masalah, tetapi memperbarui wadah buruh pelabuhan tanpa waktu henti merupakan hal yang menantang.

Bingung? Mari saya tunjukkan keduanya satu per satu.

Metode 1:Memperbarui wadah buruh pelabuhan ke gambar terbaru (mengakibatkan waktu henti)

Metode ini pada dasarnya terdiri dari langkah-langkah berikut:

  • Tarik gambar buruh pelabuhan terbaru
  • Hentikan dan hapus container yang menjalankan image buruh pelabuhan lama
  • Buat wadah baru dengan gambar buruh pelabuhan yang baru ditarik

Ingin perintah? Ini dia.

Buat daftar gambar buruh pelabuhan dan dapatkan gambar buruh pelabuhan yang memiliki pembaruan. Dapatkan perubahan terbaru pada gambar ini menggunakan perintah docker pull:

docker pull image_name

Sekarang dapatkan ID wadah atau nama wadah yang menjalankan gambar buruh pelabuhan yang lebih lama. Gunakan perintah docker ps untuk tujuan ini. Hentikan penampung ini:

docker stop container_ID

Dan keluarkan wadahnya:

docker rm container_id

Langkah selanjutnya adalah menjalankan container baru dengan parameter yang sama dengan yang Anda gunakan untuk menjalankan container sebelumnya. Saya yakin Anda tahu parameter tersebut karena Anda telah membuatnya sejak awal.

docker run --name=container_name [options] docker_image

Apakah Anda melihat masalah dengan pendekatan ini? Anda harus menghentikan wadah yang sedang berjalan dan kemudian membuat yang baru. Ini akan mengakibatkan waktu henti untuk layanan yang sedang berjalan.

Waktu henti, meskipun hanya satu menit, dapat meninggalkan dampak besar jika itu adalah proyek yang sangat penting atau layanan web dengan lalu lintas tinggi.

Ingin tahu pendekatan yang lebih aman dan lebih baik untuk masalah ini? Baca bagian selanjutnya.

Metode 2:Memperbarui wadah buruh pelabuhan dalam pengaturan proxy terbalik (dengan nol atau waktu henti minimal)

Jika Anda mencari solusi langsung, maaf mengecewakan Anda, tetapi itu tidak akan menjadi solusi karena di sini Anda harus men-deploy container Anda dalam arsitektur reverse-proxy dengan Docker Compose.

Jika Anda ingin mengelola layanan penting menggunakan wadah buruh pelabuhan, metode proxy terbalik akan banyak membantu Anda dalam jangka panjang.

Biarkan saya membuat daftar tiga keuntungan utama dari pengaturan proxy terbalik:

  • Anda dapat menerapkan beberapa layanan publik di server yang sama. Tidak ada pemblokiran port di sini.
  • Server Let's Encrypt menangani penerapan SSL untuk semua layanan, semua wadah.
  • Anda dapat memperbarui penampung tanpa memengaruhi layanan yang sedang berjalan (untuk sebagian besar layanan web).

Jika Anda penasaran untuk mempelajari lebih lanjut, Anda dapat melihat glosarium Nginx resmi yang menyoroti penggunaan umum proxy terbalik dan bagaimana perbandingannya dengan penyeimbang beban.

Kami memiliki tutorial mendalam yang bagus tentang menyiapkan proxy terbalik Nginx untuk meng-host lebih dari satu contoh layanan web yang berjalan dalam wadah di server yang sama. Jadi, saya tidak akan membahasnya lagi di sini. Anda harus pergi dan mengatur wadah Anda menggunakan arsitektur ini terlebih dahulu. Percayalah, ini sepadan dengan masalahnya.

Dalam tutorial ini, saya telah merancang metodologi langkah demi langkah yang dapat sangat membantu dalam aktivitas DevOps Anda sehari-hari. Persyaratan ini tidak hanya sangat diperlukan saat Anda memperbarui penampung, tetapi juga saat Anda ingin membuat perubahan yang sangat diperlukan di salah satu aplikasi yang sedang berjalan tanpa mengorbankan waktu aktif yang tak ternilai.

Dari sini dan seterusnya, kami berasumsi bahwa Anda menjalankan aplikasi web Anda di bawah pengaturan proxy terbalik yang akan memastikan bahwa perutean ulang berfungsi untuk wadah terbaru yang baru seperti yang diharapkan setelah perubahan konfigurasi yang akan kami lakukan.

Saya akan menunjukkan langkah-langkah metode ini terlebih dahulu, diikuti dengan contoh nyata.

Langkah 1:Perbarui file penulisan buruh pelabuhan

Pertama-tama, Anda perlu mengedit file penulisan buruh pelabuhan yang ada dengan nomor versi gambar terbaru. Itu dapat dilihat di Docker Hub, khususnya di bawah bagian "tag" aplikasi.

Pindah ke direktori aplikasi dan edit file komposisi buruh pelabuhan dengan editor teks baris perintah. Saya menggunakan Nano di sini.

[email protected]:~/web-app$ nano docker-compose.yml

Dalam services: , perbarui image: web-app:x.x.x dengan nomor versi terbaru dan simpan file.

Anda mungkin bertanya-tanya mengapa tidak menggunakan tag terbaru daripada menentukan nomor versi secara manual? Saya melakukannya dengan sengaja karena saya perhatikan bahwa saat memperbarui penampung, mungkin ada penundaan sebentar-sebentar dari tag terbaru untuk benar-benar mengambil versi terbaru dari aplikasi yang di-docker. Ketika Anda menggunakan nomor versi secara langsung, Anda selalu dapat benar-benar yakin.

Langkah 2:Tingkatkan penampung baru

Saat Anda menggunakan perintah berikut, penampung baru dibuat berdasarkan perubahan baru yang dibuat di file penulisan buruh pelabuhan.

[email protected]:~/web-app$ docker-compose up -d --scale web-app=2 --no-recreate

Perhatikan bahwa penampung sebelumnya masih aktif dan berjalan. --scale flag digunakan untuk membuat wadah tambahan seperti yang ditentukan. Di sini, web-app telah ditetapkan sebagai nama layanan untuk aplikasi web.

Meskipun Anda menentukan penskalaan hingga 2 penampung, --no-recreate memastikan bahwa hanya satu yang ditambahkan karena Anda sudah menjalankan penampung lama.

Untuk mempelajari lebih lanjut tentang --scale dan --no-recreate bendera, periksa halaman dokumentasi penulisan buruh pelabuhan resmi.

Langkah 3:Hapus wadah lama

Setelah langkah 2, berikan waktu sekitar 15-20 detik agar perubahan baru diterapkan, lalu keluarkan wadah lama:

[email protected]:~/web-app$ docker rm -f old-web-app

Pada aplikasi web yang berbeda, perubahan yang direfleksikan secara perilaku berbeda setelah Anda menjalankan perintah di atas (dibahas sebagai tip bonus di bagian paling bawah tutorial ini).

Langkah 4:Turunkan ke penyiapan wadah tunggal seperti sebelumnya

Untuk langkah terakhir, turunkan skala ke penyiapan wadah tunggal sekali lagi:

[email protected]:~/web-app$ docker-compose up -d --scale web-app=1 --no-recreate

Saya telah menguji metode ini dengan instance Ghost, WordPress, Rocket.Chat, dan Nextcloud. Kecuali Nextcloud beralih ke mode pemeliharaan selama beberapa detik, prosedur ini bekerja sangat baik untuk tiga lainnya.

Namun wacana, adalah cerita lain dan bisa menjadi pengecualian yang sangat rumit dalam kasus ini karena model hibridanya.

Intinya adalah:semakin aplikasi web menggunakan praktik buruh pelabuhan standar saat melakukan docker, semakin nyaman untuk mengelola semua wadah aplikasi web setiap hari.

Contoh kehidupan nyata:Memperbarui instance Ghost langsung tanpa downtime

Seperti yang dijanjikan, saya akan menunjukkan contoh kehidupan nyata. Saya akan menunjukkan cara memperbarui Ghost yang berjalan di wadah buruh pelabuhan ke versi yang lebih baru tanpa waktu henti.

Ghost adalah CMS dan kami menggunakannya untuk Buku Pegangan Linux. Contoh yang ditampilkan di sini adalah apa yang kami gunakan untuk memperbarui instance Ghost kami yang menjalankan situs web ini.

Katakanlah, saya memiliki konfigurasi yang ada berdasarkan versi yang lebih lama yang terletak di /home/avimanyu/ghost :

version: '3.5'
services:
  ghost:
    image: ghost:3.36
    volumes:
      - ghost:/var/lib/ghost/content
    environment:
      - VIRTUAL_HOST=blog.domain.com
      - LETSENCRYPT_HOST=blog.domain.com
      - url=https://blog.domain.com
      - NODE_ENV=production
    restart: always
    networks:
      - net

volumes:
  ghost:
    external: true

networks:
  net:
    external: true

Perhatikan bahwa konfigurasi penulisan buruh pelabuhan di atas didasarkan pada konfigurasi buruh pelabuhan Nginx yang sudah ada sebelumnya yang dijelaskan di sini, berjalan pada jaringan bernama net . Volume buruh pelabuhannya juga telah dibuat secara manual dengan docker volume create ghost-blog .

Ketika saya memeriksanya dengan docker ps :

CONTAINER ID        IMAGE                                    COMMAND                  CREATED             STATUS              PORTS                                      NAMES
2df6c27c1fe3        ghost:3.36                             "docker-entrypoint.s…"   9 days ago          Up 7 days           2368/tcp                                   ghost_ghost-blog_1
89a5a7fdcfa4        jrcs/letsencrypt-nginx-proxy-companion   "/bin/bash /app/entr…"   9 days ago          Up 7 days                                                      letsencrypt-helper
90b72e217516        jwilder/nginx-proxy                      "/app/docker-entrypo…"   9 days ago          Up 7 days           0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   reverse-proxy

Pada saat penulisan ini, ini adalah versi Ghost yang lebih lama. Saatnya memperbaruinya ke versi terbaru 3.37.1! Jadi, saya merevisinya di bagian gambar sebagai:

version: '3.5'
services:
  ghost-blog:
    image: ghost:3.37.1
    volumes:
      - ghost-blog:/var/lib/ghost/content
    environment:
      - VIRTUAL_HOST=blog.domain.com
      - LETSENCRYPT_HOST=blog.domain.com
      - url=https://blog.domain.com
      - NODE_ENV=production
    restart: always
    networks:
      - net

volumes:
  ghost-blog:
    external: true

networks:
  net:
    external: true

Sekarang untuk menggunakan metode penskalaan dengan baik:

[email protected]:~/ghost$ docker-compose up -d --scale ghost-blog=2 --no-recreate

Dengan perintah di atas, penampung lama tetap tidak terpengaruh tetapi penampung baru bergabung dengan konfigurasi yang sama tetapi berdasarkan versi Ghost terbaru:

[email protected]:~/ghost$ docker-compose up -d --scale ghost-blog=2 --no-recreate
Pulling ghost (ghost:3.37.1)...
3.37.1: Pulling from library/ghost
bb79b6b2107f: Already exists
99ce436c3449: Already exists
f7bdc31da5f5: Already exists
7a1300b9ff59: Already exists
a495c68fa838: Already exists
6e362a39ec35: Already exists
b68b4f3c36f7: Already exists
41f8b02d4a71: Pull complete
3ecc736ea4e5: Pull complete
Digest: sha256:595c759980cd22e99037811397012908d89efb799776db222a4be6d4d892917c
Status: Downloaded newer image for ghost:3.37.1
Starting ghost_ghost-blog_1 ... done
Creating ghost_ghost-blog_2 ... done

Seandainya saya menggunakan pendekatan konvensional dengan docker-compose up -d sebagai gantinya, saya tidak akan bisa menghindari pembuatan ulang wadah yang ada berdasarkan gambar Ghost terbaru.

Rekreasi melibatkan penghapusan wadah lama dan membuat wadah baru di tempatnya dengan pengaturan yang sama. Ini adalah saat downtime terjadi dan situs menjadi tidak dapat diakses.

Inilah sebabnya mengapa Anda harus menggunakan --no-recreate bendera sambil meningkatkan.

Jadi sekarang saya memiliki dua wadah yang berjalan berdasarkan konfigurasi hantu yang sama. Ini adalah bagian penting untuk menghindari waktu henti:

[email protected]:~/ghost$ docker ps
CONTAINER ID        IMAGE                                    COMMAND                  CREATED             STATUS              PORTS                                      NAMES
f239f677de54        ghost:3.37.1                               "docker-entrypoint.s…"   2 minutes ago       Up 2 minutes        2368/tcp                                   ghost_ghost-blog_2
2df6c27c1fe3        ghost:3.36                             "docker-entrypoint.s…"   9 days ago          Up 7 days           2368/tcp                                   ghost_ghost-blog_1
89a5a7fdcfa4        jrcs/letsencrypt-nginx-proxy-companion   "/bin/bash /app/entr…"   9 days ago          Up 7 days                                                      letsencrypt-helper
90b72e217516        jwilder/nginx-proxy                      "/app/docker-entrypo…"   9 days ago          Up 7 days           0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   reverse-proxy

Perhatikan bahwa nama penampung lama adalah ghost_ghost-blog_1 . Periksa nama domain Anda dan Anda akan menemukannya masih dapat diakses di blog.domain.com . Jika Anda me-refresh panel admin Ghost, yang ada di blog.domain.com/ghost setelah ditingkatkan, itu akan terus mencoba memuat sendiri sampai Anda menghapus wadah lama:

[email protected]:~/ghost$ docker rm -f ghost_ghost-blog_1

Tapi untuk blog Ghost sendiri tidak ada downtime sama sekali! Jadi, dengan cara ini Anda dapat memastikan tanpa downtime saat memperbarui blog Ghost.

Terakhir, perkecil konfigurasi ke pengaturan aslinya:

[email protected]:~/ghost$ docker-compose up -d --scale ghost-blog=1 --no-recreate
Starting ghost_ghost-blog_2 ... done

Seperti yang disebutkan sebelumnya, setelah menghapus penampung lama, perubahan tersebut tercermin dalam aplikasi web masing-masing, tetapi mereka jelas berperilaku berbeda karena desain aplikasi yang beragam.

Berikut adalah beberapa pengamatan:

Di WordPress :Pastikan Anda menambahkan define( 'AUTOMATIC_UPDATER_DISABLED', true ); sebagai garis bawah pada file wp-config.php yang terletak di /var/www/html dan mount /var/www/html/wp-content alih-alih /var/www/html sebagai volume. Cek di sini untuk detailnya. Setelah langkah 3, panel admin WordPress akan menunjukkan bahwa WordPress Anda mutakhir dan akan meminta Anda untuk melanjutkan dan memperbarui database Anda. Pembaruan terjadi dengan cepat tanpa downtime di situs WordPress dan hanya itu!

Di Rocket.Chat :Diperlukan waktu sekitar 15-20 detik untuk Admin>Info halaman untuk menunjukkan bahwa Anda menjalankan versi terbaru bahkan sebelum Anda melakukan langkah 3. Tidak ada waktu henti lagi!

Di Nextcloud :Setelah langkah 2, Nextcloud akan beralih ke mode pemeliharaan selama beberapa detik dan kemudian memuat file Anda lagi. Di bawah Administration > Overview > Security & setup warnings , Anda mungkin mendapatkan peringatan seperti, "Server web Anda tidak diatur dengan benar untuk menyelesaikan "./well-known/carddav". Ini karena penampung lama Anda masih berjalan. Setelah Anda menghapusnya dengan langkah 3, peringatan ini akan tidak ada lagi. Pastikan Anda memberikan waktu sebelum mengakses URL Nextcloud Anda karena URL tersebut dapat menampilkan kesalahan gateway 502 yang buruk hingga penampung Nginx Anda melihat penampung Nextcloud yang baru diskalakan berdasarkan versi terbaru.

Kiat bonus

Berikut adalah beberapa tips dan hal yang perlu diingat saat mengikuti metode ini.

Kiat 1

Untuk menjaga waktu henti minimum ke nol di berbagai aplikasi, pastikan Anda menyediakan waktu yang cukup untuk container yang baru diskalakan dan up-to-date sehingga container Nginx akhirnya dapat mengenalinya sebelum Anda menghapus yang lama di langkah 2.

Sebelum Anda pindah ke langkah 2 yang dijelaskan di atas, disarankan untuk mengamati perilaku aplikasi Anda di browser Anda (baik sebagai penyegaran halaman setelah login atau sebagai akses halaman baru di jendela browser pribadi yang bebas cache) setelah melakukan langkah 1.

Karena setiap aplikasi dirancang secara berbeda, tindakan ini akan terbukti sangat membantu sebelum Anda menurunkan container lama Anda.

Kiat 2

Meskipun ini bisa menjadi metode yang sangat banyak akal untuk memperbarui wadah Anda ke versi terbaru dari aplikasi yang mereka jalankan, perhatikan bahwa Anda dapat menggunakan metode yang sama untuk juga membuat perubahan konfigurasi atau memodifikasi pengaturan lingkungan tanpa menghadapi masalah waktu henti.

Ini bisa menjadi penting jika Anda harus memecahkan masalah atau melakukan perubahan yang mungkin Anda anggap perlu dalam wadah langsung, tetapi tidak ingin menurunkannya saat melakukannya. Setelah Anda membuat perubahan dan yakin bahwa masalah telah diperbaiki, Anda dapat menghapus yang lebih lama dengan mudah.

Kami sendiri menghadapi ini ketika kami menemukan bahwa rotasi log tidak diaktifkan di salah satu wadah langsung kami. Kami melakukan perubahan yang diperlukan untuk mengaktifkannya dan pada saat yang sama menghindari waktu henti saat melakukannya dengan metode ini.

Kiat 3

Jika Anda telah secara khusus menamai wadah Anda di file YML dengan menggunakan container_name , metode ini tidak akan berfungsi seperti yang diharapkan karena melibatkan pembuatan nama wadah baru.

Anda dapat menghindari konflik ini dengan meninggalkan tugas penamaan wadah itu ke Docker Compose (dilakukan secara otomatis sesuai dengan konvensi penamaannya). Docker Compose menamai wadahnya sebagai directory-name_service-name_1 . Jumlah pada akhirnya akan bertambah setiap kali wadah diperbarui (sampai Anda menggunakan docker-compose down untuk beberapa alasan).

Jika Anda sudah menggunakan layanan dengan menggunakan wadah bernama khusus di file penulisan buruh pelabuhan Anda, untuk menggunakan metode ini, cukup beri komentar pada baris (dengan awalan #) yang menyertakancontainer_name di dalam definisi layanan.

Setelah membuat container baru untuk hal di atas menggunakan langkah 1 seperti yang dijelaskan dalam tutorial ini, untuk langkah 2, nama container lama (yang tidak dihentikan untuk menghindari waktu henti) akan menjadi seperti yang ditentukan sebelumnya menggunakan container_name (juga dapat diperiksa dengan `docker ps ` sebelum mengeluarkan wadah lama).

Apakah Anda mempelajari sesuatu yang baru?

Saya tahu artikel ini agak panjang, tetapi saya harap ini membantu komunitas DevOps kami dalam mengelola masalah waktu henti dengan server produksi yang menjalankan aplikasi web docker. Waktu henti memang memiliki dampak besar pada tingkat individu dan komersial dan inilah mengapa membahas topik ini adalah kebutuhan mutlak.

Silakan bergabung dalam diskusi dan bagikan pemikiran, masukan, atau saran Anda di bagian komentar di bawah.


Linux
  1. Cara Menginstal WordPress dengan Docker di Ubuntu

  2. Instal ModSecurity dengan Apache di Docker Container

  3. Cara Menyebarkan Wadah nginx dengan Docker di Linode

  1. 7 fitur wadah/transportasi gambar Linux yang menyenangkan

  2. Cara Mendaftar Kontainer Docker

  3. Docker tidak memperbarui perubahan dalam direktori

  1. Memperbarui container yang di-deploy berdasarkan image Docker

  2. Cara Memperbarui Kontainer Docker dengan Zero Downtime

  3. Wadah LXD dan jaringan dengan IP statis