Kontainer profesional aplikasi Node.js menggunakan Docker

Penulis bahan, terjemahan yang kami terbitkan hari ini, adalah seorang insinyur DevOps. Dia bilang dia harus menggunakan Docker . Secara khusus, platform manajemen kontainer ini digunakan pada berbagai tahap siklus hidup aplikasi Node.js. Menggunakan Docker, sebuah teknologi yang, baru-baru ini, sangat populer, memungkinkan Anda untuk mengoptimalkan proses pengembangan dan keluaran proyek Node.js dalam produksi.

gambar

Sekarang kami menerbitkan serangkaian artikel tentang Docker, yang dirancang untuk mereka yang ingin mempelajari platform ini untuk penggunaannya dalam berbagai situasi. Materi yang sama berfokus terutama pada penggunaan profesional Docker dalam pengembangan Node.js.

Apa itu buruh pelabuhan?


Docker adalah program yang dirancang untuk mengatur virtualisasi di tingkat sistem operasi (containerisasi). Di jantung wadah adalah gambar berlapis. Sederhananya, Docker adalah alat yang memungkinkan Anda untuk membuat, menyebarkan, dan menjalankan aplikasi menggunakan wadah yang tidak tergantung pada sistem operasi yang digunakannya. Wadah tersebut mencakup gambar OS dasar yang diperlukan agar aplikasi berfungsi, perpustakaan tempat aplikasi ini bergantung, dan aplikasi ini sendiri. Jika beberapa kontainer berjalan di komputer yang sama, maka mereka menggunakan sumber daya komputer ini bersama-sama. Wadah Docker dapat mengemas proyek yang dibuat menggunakan berbagai teknologi. Kami tertarik pada proyek berdasarkan Node.js.

Membuat proyek Node.js


Sebelum kita mengemas proyek Node.js ke dalam wadah Docker, kita perlu membuat proyek ini. Ayo lakukan. Ini adalah file package.json dari proyek ini:

 { "name": "node-app", "version": "1.0.0", "description": "The best way to manage your Node app using Docker", "main": "index.js", "scripts": {   "start": "node index.js" }, "author": "Ankit Jain <ankitjain28may77@gmail.com>", "license": "ISC", "dependencies": {   "express": "^4.16.4" } } 

Untuk menginstal dependensi proyek, jalankan perintah npm install . Dalam menjalankan perintah ini, antara lain, file package-lock.json akan dibuat. Sekarang buat file index.js , yang akan berisi kode proyek:

 const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('The best way to manage your Node app using Docker\n'); }); app.listen(3000); console.log('Running on http://localhost:3000'); 

Seperti yang Anda lihat, di sini kami menggambarkan server sederhana yang mengembalikan beberapa teks sebagai tanggapan terhadap permintaan untuk itu.

Buat Dockerfile


Sekarang setelah aplikasi siap, mari kita bicara tentang cara mengemasnya ke dalam wadah Docker. Yaitu, itu akan tentang apa yang paling penting dari setiap proyek berbasis Docker, tentang Dockerfile.

Dockerfile adalah file teks yang berisi instruksi untuk membuat gambar Docker untuk suatu aplikasi. Instruksi dalam file ini, jika tidak masuk ke dalam perincian, menjelaskan pembuatan lapisan dari sistem file multi-level, yang memiliki segala yang diperlukan suatu aplikasi untuk bekerja. Platform Docker dapat menyimpan cache lapisan gambar, yang, ketika menggunakan kembali lapisan yang sudah ada dalam cache, mempercepat proses pembuatan gambar.

Dalam pemrograman berorientasi objek, ada yang namanya kelas. Kelas digunakan untuk membuat objek. Di Docker, gambar dapat dibandingkan dengan kelas, dan wadah dapat dibandingkan dengan contoh gambar, yaitu, dengan objek. Pertimbangkan proses pembuatan Dockerfile, yang akan membantu kami mengetahui hal ini.

Buat Dockerfile kosong:

 touch Dockerfile 

Karena kita akan membangun sebuah wadah untuk aplikasi Node.js, hal pertama yang perlu kita masukkan ke dalam wadah adalah gambar Node dasar, yang dapat ditemukan di Docker Hub . Kami akan menggunakan versi LTS dari Node.js. Akibatnya, pernyataan pertama Dockerfile kami adalah pernyataan berikut:

 FROM node:8 

Setelah itu, buat direktori untuk kode kita. Pada saat yang sama, berkat instruksi ARG digunakan di sini, kita dapat, jika perlu, menentukan nama direktori aplikasi selain /app selama perakitan wadah. Detail tentang manual ini dapat ditemukan di sini .

 #   ARG APP_DIR=app RUN mkdir -p ${APP_DIR} WORKDIR ${APP_DIR} 

Karena kita menggunakan gambar Node, platform Node.js dan npm akan sudah diinstal di dalamnya. Menggunakan apa yang sudah ada dalam gambar, Anda dapat mengatur instalasi dependensi proyek. Menggunakan flag NODE_ENV (atau jika NODE_ENV lingkungan NODE_ENV diatur ke production ) npm tidak akan menginstal modul yang terdaftar di bagian devDependencies pada file devDependencies .

 #   COPY package*.json ./ RUN npm install #     # RUN npm install --production 

Di sini kita menyalin file package*.json ke gambar, alih-alih, misalnya menyalin semua file proyek. Kami melakukan hal itu karena petunjuk Dockerfile RUN , COPY dan ADD membuat lapisan gambar tambahan, sehingga Anda dapat menggunakan fitur caching dari lapisan platform Docker. Dengan pendekatan ini, saat berikutnya kami mengumpulkan gambar yang serupa, Docker akan mencari tahu apakah mungkin untuk menggunakan kembali lapisan gambar yang sudah ada dalam cache, dan jika demikian, itu akan mengambil keuntungan dari apa yang sudah ada, daripada membuat yang baru. lapisan. Ini memungkinkan Anda untuk secara serius menghemat waktu ketika merakit lapisan-lapisan selama mengerjakan proyek-proyek besar, yang mencakup banyak modul npm.

Sekarang salin file proyek ke direktori kerja saat ini. Di sini kita tidak akan menggunakan instruksi ADD , tetapi instruksi COPY . Bahkan, dalam banyak kasus dianjurkan untuk memberikan preferensi pada instruksi COPY .

Instruksi ADD , dibandingkan dengan COPY , memiliki beberapa fitur, yang, bagaimanapun, tidak selalu diperlukan. Misalnya, kita berbicara tentang opsi untuk membongkar arsip .tar dan mengunduh file dengan URL.

 #    COPY . . 

Wadah buruh pelabuhan adalah lingkungan yang terisolasi. Ini berarti bahwa ketika kita meluncurkan aplikasi dalam wadah, kita tidak akan dapat berinteraksi dengannya secara langsung tanpa membuka port yang didengarkan aplikasi ini. Untuk memberi tahu Docker bahwa ada aplikasi dalam wadah tertentu yang mendengarkan pada port tertentu, Anda dapat menggunakan instruksi EXPOSE .

 #   ,      EXPOSE 3000 

Sampai saat ini, kami, menggunakan Dockerfile, telah menggambarkan gambar yang akan berisi aplikasi dan segala yang diperlukan untuk berhasil diluncurkan. Sekarang tambahkan instruksi ke file yang memungkinkan Anda untuk memulai aplikasi. Ini adalah instruksi CMD . Ini memungkinkan Anda untuk menentukan perintah tertentu dengan parameter yang akan dieksekusi ketika wadah mulai, dan, jika perlu, dapat ditimpa oleh alat baris perintah.

 #   CMD ["npm", "start"] 

Inilah yang akan terlihat seperti Dockerfile:

 FROM node:8 #   ARG APP_DIR=app RUN mkdir -p ${APP_DIR} WORKDIR ${APP_DIR} #   COPY package*.json ./ RUN npm install #     # RUN npm install --production #    COPY . . #   ,      EXPOSE 3000 #   CMD ["npm", "start"] 

Perakitan gambar


Kami telah menyiapkan file Dockerfile yang berisi instruksi untuk membangun gambar, atas dasar mana wadah dengan aplikasi yang sedang berjalan akan dibuat. Rakit gambar dengan mengeksekusi perintah dari formulir berikut:

 docker build --build-arg <build arguments> -t <user-name>/<image-name>:<tag-name> /path/to/Dockerfile 

Dalam kasus kami, akan terlihat seperti ini:

 docker build --build-arg APP_DIR=var/app -t ankitjain28may/node-app:V1 . 

Dockerfile memiliki pernyataan ARG yang menjelaskan argumen APP_DIR . Di sini kita mengatur maknanya. Jika ini tidak dilakukan, maka akan mengambil nilai yang ditugaskan padanya dalam file, yaitu - app .

Setelah menyusun gambar, periksa apakah Docker melihatnya. Untuk melakukan ini, jalankan perintah berikut:

 docker images 

Menanggapi perintah ini, kira-kira berikut ini harus menjadi output.


Gambar Docker

Peluncuran Gambar


Setelah kita merakit gambar Docker, kita dapat menjalankannya, yaitu membuat instance darinya, diwakili oleh wadah yang berfungsi. Untuk melakukan ini, gunakan perintah seperti ini:

 docker run -p <External-port:exposed-port> -d --name <name of the container> <user-name>/<image-name>:<tag-name> 

Dalam kasus kami, akan terlihat seperti ini:

 docker run -p 8000:3000 -d --name node-app ankitjain28may/node-app:V1 

Kami akan meminta sistem untuk informasi tentang wadah yang bekerja menggunakan perintah ini:

 docker ps 

Menanggapi hal ini, sistem harus menampilkan sesuatu seperti berikut:


Wadah Docker

Sejauh ini, semuanya berjalan seperti yang diharapkan, meskipun kami belum mencoba mengakses aplikasi yang berjalan di wadah. Yaitu, wadah kami, bernama node-app , mendengarkan pada port 8000 . Untuk mencoba mengaksesnya, Anda dapat membuka browser dan masuk ke localhost:8000 . Selain itu, untuk memeriksa kesehatan wadah, Anda dapat menggunakan perintah berikut:

 curl -i localhost:8000 

Jika wadah benar-benar berfungsi, maka sesuatu seperti yang ditunjukkan pada gambar berikut akan dikembalikan sebagai respons terhadap perintah ini.


Hasil Pemeriksaan Kesehatan Kontainer

Atas dasar gambar yang sama, misalnya, atas dasar yang baru saja dibuat, dimungkinkan untuk membuat banyak wadah. Selain itu, Anda dapat mengirim gambar kami ke registri Docker Hub, yang akan memungkinkan pengembang lain mengunggah gambar kami dan meluncurkan wadah yang sesuai di rumah. Pendekatan ini menyederhanakan bekerja dengan proyek.

Rekomendasi


Berikut adalah beberapa saran yang layak dipertimbangkan untuk memanfaatkan kekuatan Docker dan membuat gambar seringkas mungkin.

▍1. Selalu buat file .dockerignore


Dalam folder proyek yang Anda rencanakan untuk ditempatkan di wadah, Anda selalu perlu membuat file .dockerignore . Ini memungkinkan Anda untuk mengabaikan file dan folder yang tidak diperlukan saat membangun gambar. Dengan pendekatan ini, kita dapat mengurangi apa yang disebut konteks pembangunan, yang akan memungkinkan kita untuk dengan cepat mengumpulkan gambar dan mengurangi ukurannya. File ini mendukung templat nama file, dalam hal ini mirip dengan file .gitignore . Disarankan untuk menambahkan perintah ke .dockerignore karena Docker akan mengabaikan folder /.git , karena folder ini biasanya berisi materi besar (terutama selama pengembangan proyek) dan menambahkannya ke gambar menyebabkan peningkatan ukurannya. Selain itu, menyalin folder ini ke dalam gambar tidak masuk akal.

▍2. Gunakan proses perakitan gambar multi-tahap


Pertimbangkan contoh ketika kita mengumpulkan proyek untuk organisasi tertentu. Proyek ini menggunakan banyak paket npm, dan masing-masing paket tersebut dapat menginstal paket tambahan yang bergantung padanya. Melakukan semua operasi ini mengarah ke waktu tambahan yang dihabiskan dalam proses perakitan gambar (meskipun ini, berkat kemampuan caching Docker, bukan masalah besar). Lebih buruk lagi, gambar yang dihasilkan mengandung dependensi dari proyek tertentu cukup besar. Di sini, jika kita berbicara tentang proyek front-end, kita dapat mengingat bahwa proyek seperti itu biasanya diproses menggunakan bundler seperti webpack, yang memungkinkan untuk dengan mudah mengemas semua yang dibutuhkan aplikasi dalam paket penjualan. Akibatnya, file paket npm untuk proyek semacam itu tidak diperlukan. Dan ini berarti bahwa kita dapat menyingkirkan file-file tersebut setelah membangun proyek menggunakan paket web yang sama.

Berbekal ide ini, coba lakukan ini:

 #   COPY package*.json ./ RUN npm install --production # - COPY . . RUN npm run build:production #    npm- RUN rm -rf node_modules 

Namun pendekatan semacam itu tidak cocok untuk kita. Seperti yang telah kami katakan, instruksi RUN , ADD dan COPY membuat lapisan yang di-cache oleh Docker, jadi kita perlu menemukan cara untuk menangani instalasi dependensi, membangun proyek, dan kemudian menghapus file yang tidak perlu dengan satu perintah. Misalnya, mungkin terlihat seperti ini:

 #      COPY . . #  ,      RUN npm install --production && npm run build:production && rm -rf node_module 

Dalam contoh ini, hanya ada satu pernyataan RUN yang menginstal dependensi, node_modules proyek, dan menghapus folder node_modules . Ini mengarah pada fakta bahwa ukuran gambar tidak akan sebesar ukuran gambar yang mencakup folder node_modules . Kami menggunakan file dari folder ini hanya selama proses pembangunan proyek, dan kemudian menghapusnya. Benar, pendekatan ini buruk karena butuh banyak waktu untuk menginstal dependensi npm. Anda dapat menghilangkan kelemahan ini menggunakan teknologi perakitan multi-tahap gambar.

Bayangkan kami sedang mengerjakan proyek frontend yang memiliki banyak dependensi, dan kami menggunakan webpack untuk membangun proyek ini. Dengan pendekatan ini, kita dapat, demi mengurangi ukuran gambar, memanfaatkan kemampuan Docker untuk perakitan gambar multi-tahap .

 FROM node:8 As build #  RUN mkdir /app && mkdir /src WORKDIR /src #   COPY package*.json ./ RUN npm install #     # RUN npm install --production #       COPY . . RUN npm run build:production #    ,     FROM node:alpine #      build   app COPY --from=build ./src/build/* /app/ ENTRYPOINT ["/app"] CMD ["--help"] 

Dengan pendekatan ini, gambar yang dihasilkan jauh lebih kecil dari gambar sebelumnya, dan kami juga menggunakan node:alpine gambar node:alpine , yang itu sendiri sangat kecil. Dan di sini adalah perbandingan sepasang gambar, di mana dapat dilihat bahwa gambar node:alpine jauh lebih kecil daripada gambar node:8 .


Membandingkan gambar dari repositori Node

▍3. Gunakan Docker Cache


Berusaha keras untuk menggunakan kemampuan cache Docker untuk membangun gambar Anda. Kami sudah memperhatikan fitur ini ketika bekerja dengan file yang diakses oleh package*.json nama package*.json . Ini mengurangi waktu pembuatan gambar. Namun kesempatan ini jangan digunakan dengan gegabah.

Misalkan kita jelaskan di Dockerfile menginstal paket dalam gambar yang dibuat dari gambar dasar Ubuntu:16.04 :

 FROM ubuntu:16.04 RUN apt-get update && apt-get install -y \   curl \   package-1 \   .   . 

Ketika sistem akan memproses file ini, jika ada banyak paket yang diinstal, operasi pembaruan dan instalasi akan memakan banyak waktu. Untuk memperbaiki situasi, kami memutuskan untuk mengambil keuntungan dari kemampuan caching lapisan Docker dan menulis ulang Dockerfile sebagai berikut:

 FROM ubuntu:16.04 RUN apt-get update RUN apt-get install -y \   curl \   package-1 \   .   . 

Sekarang, ketika merakit gambar untuk pertama kalinya, semuanya berjalan sebagaimana mestinya, karena cache belum terbentuk. Bayangkan sekarang bahwa kita perlu menginstal paket lain, package-2 . Untuk melakukan ini, kami menulis ulang file:

 FROM ubuntu:16.04 RUN apt-get update RUN apt-get install -y \   curl \   package-1 \   package-2 \   .   . 

Sebagai hasil dari perintah seperti itu, package-2 tidak akan diinstal atau diperbarui. Mengapa Faktanya adalah bahwa ketika menjalankan instruksi RUN apt-get update , Docker tidak melihat perbedaan antara instruksi ini dan instruksi yang dieksekusi sebelumnya, sebagai akibatnya, ia mengambil data dari cache. Dan data ini sudah usang. Saat memproses instruksi RUN apt-get install sistem menjalankannya, untuk itu, itu tidak terlihat seperti instruksi serupa di Dockerfile sebelumnya, tetapi selama instalasi, kesalahan mungkin terjadi atau versi paket yang lama akan diinstal. Hasilnya, ternyata perintah update dan install harus dijalankan dalam instruksi RUN sama, seperti yang dilakukan pada contoh pertama. Caching adalah fitur yang hebat, tetapi penggunaan sembrono dari fitur ini dapat menyebabkan masalah.

▍4. Minimalkan jumlah lapisan gambar


Disarankan, jika memungkinkan, berusaha untuk meminimalkan jumlah lapisan gambar, karena setiap lapisan adalah sistem file gambar Docker, yang berarti bahwa semakin kecil lapisan dalam gambar, semakin kompak akan. Saat menggunakan proses multi-tahap perakitan gambar, pengurangan jumlah lapisan dalam gambar dan penurunan ukuran gambar tercapai.

Ringkasan


Pada artikel ini, kami melihat proses pengemasan aplikasi Node.js dalam wadah Docker dan bekerja dengan wadah tersebut. Selain itu, kami membuat beberapa rekomendasi yang, omong-omong, dapat digunakan tidak hanya ketika membuat wadah untuk proyek Node.js.

Pembaca yang budiman! Jika Anda menggunakan Docker secara profesional saat bekerja dengan proyek Node.js, silakan bagikan rekomendasi tentang penggunaan efektif sistem ini dengan pemula.

Source: https://habr.com/ru/post/id440656/


All Articles