GNU/Linux >> Belajar Linux >  >> Panels >> Docker

Cara Mengurangi Ukuran Gambar Docker:6 Metode Optimasi

Jika Anda ingin mengurangi ukuran gambar buruh pelabuhan , Anda perlu menggunakan praktik terbaik standar dalam membangun Gambar Docker.

Blog ini membahas tentang berbagai teknik pengoptimalan yang dapat Anda terapkan dengan cepat untuk membuat gambar buruh pelabuhan terkecil dan minimal . Kami juga akan melihat beberapa alat terbaik untuk Pengoptimalan Gambar Docker .

Docker sebagai mesin kontainer memudahkan untuk mengambil sepotong kode &menjalankannya di dalam sebuah kontainer. Ini memungkinkan para insinyur untuk mengumpulkan semua dependensi kode dan file ke dalam satu lokasi yang dapat dijalankan di mana saja, cukup cepat &mudah.

Seluruh konsep gambar "jalankan di mana saja" dimulai dari file konfigurasi sederhana yang disebut Dockerfile. Pertama, kami menambahkan semua instruksi build, seperti dependensi kode, perintah, dan detail gambar dasar, di Dockerfile.

Perlu Pengoptimalan Gambar Docker

Meskipun proses pembuatan Docker mudah, banyak organisasi membuat kesalahan dengan membuat gambar Docker yang membengkak tanpa mengoptimalkan gambar container.

Dalam pengembangan perangkat lunak pada umumnya, setiap layanan akan memiliki beberapa versi/rilis, dan setiap versi memerlukan lebih banyak dependensi, perintah, dan konfigurasi. Hal ini menimbulkan tantangan dalam pembuatan gambar Docker, seperti sekarang – kode yang sama membutuhkan lebih banyak waktu &sumber daya untuk dibuat sebelum dapat dikirimkan sebagai wadah.

Saya telah melihat kasus di mana gambar aplikasi awal dimulai dengan 350 MB, dan seiring waktu tumbuh menjadi lebih dari 1,5 GB.

Selain itu, dengan memasang pustaka yang tidak diinginkan, kami meningkatkan kemungkinan risiko keamanan potensial dengan meningkatkan permukaan serangan.

Oleh karena itu, insinyur DevOps harus mengoptimalkan gambar buruh pelabuhan untuk memastikan bahwa gambar buruh pelabuhan tidak membengkak setelah pembuatan aplikasi atau rilis mendatang. Tidak hanya untuk lingkungan produksi, pada setiap tahap dalam proses CI/CD, Anda harus mengoptimalkan gambar buruh pelabuhan Anda.

Selain itu, dengan alat orkestrasi container seperti Kubernetes, yang terbaik adalah memiliki gambar berukuran kecil untuk mengurangi transfer gambar dan waktu penerapan .

Bagaimana Cara Mengurangi Ukuran Gambar Docker?

Jika kita mengambil gambar kontainer dari aplikasi biasa, itu berisi gambar dasar, Dependencies/Files/Configs , dan kasar (perangkat lunak yang tidak diinginkan).

Jadi, semuanya bermuara pada seberapa efisien kita dapat mengelola sumber daya ini di dalam gambar penampung.

Mari kita lihat metode yang berbeda untuk mengoptimalkan gambar Docker. Selain itu, kami telah memberikan contoh praktis untuk memahami pengoptimalan gambar buruh pelabuhan secara real-time.

Baik Anda menggunakan contoh yang diberikan dalam artikel atau mencoba teknik pengoptimalan pada file Docker yang ada.

Berikut ini adalah metode yang dengannya kami dapat mencapai pengoptimalan gambar buruh pelabuhan.

  1. Menggunakan gambar dasar tanpa distro/minimal
  2. Pembuatan multitahap
  3. Meminimalkan jumlah lapisan
  4. Memahami cache
  5. Menggunakan Dockerignore
  6. Menyimpan data aplikasi di tempat lain

File Latihan Docker: Semua kode aplikasi, Dockerfile, dan konfigurasi yang digunakan dalam artikel ini dihosting di repositori Github ini. Anda dapat mengkloningnya dan mengikuti tutorialnya.

Metode 1:Gunakan Gambar Dasar Minimal

Fokus pertama Anda adalah memilih gambar dasar yang tepat dengan jejak OS minimal.

Salah satu contohnya adalah gambar dasar alpine. Gambar pegunungan dapat sekecil 5,59 MB . Ini bukan hanya kecil; ini juga sangat aman.

alpine       latest    c059bfaa849c     5.59MB

Nginx alpine gambar dasar hanya 22MB.

Secara default, ia datang dengan shell sh yang membantu men-debug wadah dengan melampirkannya.

Anda selanjutnya dapat mengurangi ukuran gambar dasar menggunakan gambar distroless. Ini adalah versi sistem operasi yang dilucuti. Gambar dasar tanpa distro tersedia untuk java, nodejs, python, Rust, dll.

Gambar distroless sangat minim sehingga tidak bahkan tidak memiliki cangkang di dalamnya . Jadi, Anda mungkin bertanya, lalu bagaimana kami men-debug aplikasi? Mereka memiliki versi debug dari gambar yang sama yang disertakan dengan busybox untuk debugging.

Selain itu, sebagian besar distribusi sekarang memiliki gambar dasar minimal.

Catatan: Anda tidak dapat langsung menggunakan gambar dasar yang tersedia untuk umum di lingkungan proyek. Anda perlu mendapatkan persetujuan dari tim keamanan perusahaan untuk menggunakan gambar dasar. Di beberapa organisasi, tim keamanan itu sendiri menerbitkan gambar dasar setiap bulan setelah pengujian &pemindaian keamanan. Gambar-gambar itu akan tersedia di repositori pribadi buruh pelabuhan organisasi umum.

Metode 2:Gunakan Docker Multistage Builds

Pola pembuatan bertingkat berevolusi dari konsep pola pembangun di mana kami menggunakan file Docker yang berbeda untuk membangun dan mengemas kode aplikasi. Meskipun pola ini membantu mengurangi ukuran gambar, pola ini memberikan sedikit biaya tambahan dalam hal membangun saluran pipa.

Dalam build multistage, kami mendapatkan keuntungan yang sama dengan pola builder. Kami menggunakan gambar perantara (membangun tahapan) untuk mengkompilasi kode, menginstal dependensi, dan mengemas file dalam pendekatan ini. Ide di balik ini adalah untuk menghilangkan lapisan yang tidak diinginkan dalam gambar.

Setelah itu, hanya file aplikasi yang diperlukan untuk menjalankan aplikasi yang disalin ke gambar lain dengan hanya pustaka yang diperlukan, yaitu lebih ringan untuk menjalankan aplikasi.

Mari kita lihat ini dalam tindakan, dengan bantuan contoh praktis di mana kita membuat aplikasi Nodejs sederhana dan mengoptimalkan Dockerfile-nya.

Pertama, mari kita buat kodenya. Kami akan memiliki struktur folder berikut.

├── Dockerfile1
├── Dockerfile2
├── env
├── index.js
└── package.json

Simpan yang berikut ini sebagai index.js .

const dotenv=require('dotenv'); 
dotenv.config({ path: './env' });

dotenv.config();

const express=require("express");
const app=express();

app.get('/',(req,res)=>{
  res.send(`Learning to Optimize Docker Images with DevOpsCube!`);
});


app.listen(process.env.PORT,(err)=>{
    if(err){
        console.log(`Error: ${err.message}`);
    }else{
        console.log(`Listening on port ${process.env.PORT}`);
    }
  }
)

Simpan yang berikut ini sebagai package.json .

{
  "name": "nodejs",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "dotenv": "^10.0.0",
    "express": "^4.17.2"
  }
}

Simpan variabel port berikut dalam file bernama env .

PORT=8080

Dockerfile simple sederhana untuk aplikasi ini akan seperti ini – Simpan sebagai Dockerfile1 .

FROM node:16
COPY . .
RUN npm installEXPOSE 3000
CMD [ "node", "index.js" ]

Mari kita lihat ruang penyimpanan yang dibutuhkan dengan membangunnya.

docker build -t devopscube/node-app:1.0 --no-cache -f Dockerfile1 .

Setelah pembangunan selesai. Mari kita periksa ukurannya menggunakan –

docker image ls

Inilah yang kami dapatkan.

devopscube/node-app   1.0       b15397d01cca   22 seconds ago   910MB

Jadi ukurannya 910MBs .

Sekarang, mari gunakan metode ini untuk membuat build bertingkat.

Kami akan menggunakan node:16 sebagai gambar dasar, yaitu gambar untuk semua pemasangan dependensi &modul, setelah itu, kita akan memindahkan isinya ke 'alpine' yang minimal dan lebih ringan ' gambar berbasis. ‘alpine ' gambar memiliki utilitas minimal &karenanya sangat ringan.

Berikut adalah representasi bergambar dari build multitahap Docker.

Juga, dalam satu Dockerfile , Anda dapat memiliki beberapa tahapan dengan gambar dasar yang berbeda. Misalnya, Anda dapat memiliki tahap berbeda untuk pembuatan, pengujian, analisis statis, dan paket dengan gambar dasar yang berbeda.

Mari kita lihat seperti apa Dockerfile baru. Kami hanya menyalin file yang diperlukan dari gambar dasar ke gambar utama.

Simpan yang berikut ini sebagai Dockerfile2 .

FROM node:16 as build

WORKDIR /app
COPY package.json index.js env ./
RUN npm install

FROM node:alpine as main

COPY --from=build /app /
EXPOSE 8080
CMD ["index.js"]

Mari kita lihat ruang penyimpanan yang dibutuhkan dengan membangunnya.

docker build -t devopscube/node-app:2.0 --no-cache -f Dockerfile2 .

Setelah pembangunan selesai. Mari kita periksa ukurannya menggunakan

docker image ls

Inilah yang kami dapatkan.

devopscube/node-app   2.0       fa6ae75da252   32 seconds ago   171MB

Jadi ukuran gambar baru yang diperkecil adalah 171 MB dibandingkan dengan gambar dengan semua dependensi.

Itu adalah pengoptimalan lebih dari 80%!

Namun, jika kami menggunakan gambar dasar yang sama dengan yang kami gunakan pada tahap pembuatan, kami tidak akan melihat banyak perbedaan.

Anda dapat mengurangi ukuran gambar lebih lanjut menggunakan gambar tanpa distro . Ini adalah Dockerfile yang sama dengan langkah pembangunan bertingkat yang menggunakan gambar tanpa distro google nodeJS, bukan alpine.

FROM node:16 as build

WORKDIR /app
COPY package.json index.js env ./
RUN npm install

FROM gcr.io/distroless/nodejs

COPY --from=build /app /
EXPOSE 3000
CMD ["index.js"]

Jika Anda membangun Dockerfile di atas, gambar Anda akan menjadi 118MB ,

devopscube/distroless-node   1.0       302990bc5e76     118MB

Metode 3:Minimalkan Jumlah Lapisan

Gambar Docker bekerja dengan cara berikut – masing-masing RUN, COPY, FROM Instruksi Dockerfile menambahkan layer baru &setiap layer menambah waktu eksekusi build &meningkatkan persyaratan penyimpanan gambar.

Mari kita lihat ini beraksi, dengan bantuan contoh praktis:mari buat image ubuntu dengan pustaka yang diperbarui &ditingkatkan, bersama dengan beberapa paket yang diperlukan yang diinstal seperti vim, net-tools, dnsutils.

Sebuah Dockerfile untuk mencapai ini adalah sebagai berikut – Simpan ini sebagai Dockerfile3 .

FROM ubuntu:latest
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -y
RUN apt-get upgrade -y
RUN apt-get install vim -y
RUN apt-get install net-tools -y
RUN apt-get install dnsutils -y

Kami juga ingin melihat waktu pembuatan untuk gambar ini.

Daemon Docker memiliki kemampuan bawaan untuk menampilkan total waktu eksekusi yang dilakukan Dockerfile.

Untuk mengaktifkan fitur ini, lakukan langkah-langkah berikut –

  1. Buat daemon.json file dengan konten berikut di /etc/docker/
{
  "experimental": true
}

2. Jalankan perintah berikut untuk mengaktifkan fitur tersebut.

export DOCKER_BUILDKIT=1

Mari kita bangun dan lihat penyimpanan &waktu pembuatannya.

time docker build -t devopscube/optimize:3.0 --no-cache -f Dockerfile3 .

Ini akan menampilkan waktu eksekusi di terminal.

time docker build -t devopscube/optimize:3.0 --no-cache -f Dockerfile3 .


[+] Building 117.1s (10/10) FINISHED                                                                   
 => [internal] load build definition from Dockerfile                                              
.
.
.
.                                                                       
 => => writing image sha256:9601bcac010062c656dacacbc7c554b8ba552c7174f32fdcbd24ff9c7482a805      0.0s 
 => => naming to docker.io/devopscube/optimize:3.0                                                0.0s 
                                                                                                       
real    1m57.219s                                                                                      
user	0m1.062s
sys	0m0.911s

Setelah pembangunan selesai – waktu eksekusi menjadi 117,1 detik .

Mari kita periksa ukurannya menggunakan

docker image ls

Inilah yang kami dapatkan.

devopscube/optimize  3.0   9601bcac0100   About a minute ago   227MB

Jadi ukurannya adalah 227MB .

Mari gabungkan perintah RUN menjadi satu lapisan &simpan sebagai Dockerfile4.

FROM ubuntu:latest
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -y && apt-get upgrade -y && apt-get install --no-install-recommends vim net-tools dnsutils -y

Dalam perintah RUN di atas, kami telah menggunakan --no-install-recommends tandai untuk menonaktifkan paket yang direkomendasikan. Direkomendasikan setiap kali Anda menggunakan install di Dockerfiles . Anda

Mari kita lihat penyimpanan &waktu pembuatan yang dibutuhkan dengan membangunnya.

time docker build -t devopscube/optimize:4.0 --no-cache -f Dockerfile4 .

Ini akan menampilkan waktu eksekusi di terminal.

time docker build -t devopscube/optimize:0.4 --no-cache -f Dockerfile4 .


[+] Building 91.7s (6/6) FINISHED                                                                      
 => [internal] load build definition from Dockerfile2                                             0.4s
.
.
.  
 => => naming to docker.io/devopscube/optimize:4.0                                                0.0s 
                                                                                                       
real    1m31.874s                                                                                      
user	0m0.884s
sys	0m0.679s

Setelah pembangunan selesai – waktu eksekusi menjadi 91,7 detik.

Mari kita periksa ukurannya menggunakan

docker image ls

Inilah yang kami dapatkan.

devopscube/optimize  4.0   37d746b976e3   42 seconds ago      216MB

Jadi ukurannya 216MB.

Dengan menggunakan teknik pengoptimalan ini, waktu eksekusi berkurang dari 117,1 menjadi 91,7 detik &ukuran penyimpanan berkurang dari 227 MB menjadi 216 MB.

Metode 4:Memahami Caching

Seringkali, gambar yang sama harus dibuat ulang lagi &lagi dengan sedikit modifikasi dalam kode.

Docker membantu dalam kasus seperti itu dengan menyimpan cache setiap lapisan build, dengan harapan dapat berguna di masa mendatang.

Karena konsep ini, disarankan untuk menambahkan baris yang digunakan untuk menginstal dependensi &paket sebelumnya di dalam Dockerfile – sebelum perintah COPY.

Alasan di balik ini adalah bahwa buruh pelabuhan akan dapat men-cache image dengan dependensi yang diperlukan, dan cache ini kemudian dapat digunakan dalam build berikut ketika kode dimodifikasi.

Sebagai contoh, mari kita lihat dua file Docker berikut.

Dockerfile5

FROM ubuntu:latest
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -y
RUN apt-get upgrade -y
RUN apt-get install vim -y
RUN apt-get install net-tools -y
RUN apt-get install dnsutils -y
COPY . .

Dockerfile6

FROM ubuntu:latest
COPY . .
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -y
RUN apt-get upgrade -y
RUN apt-get install vim -y
RUN apt-get install net-tools -y
RUN apt-get install dnsutils -y

Docker akan dapat menggunakan fungsionalitas cache dengan lebih baik dengan Dockerfile6 daripada Dockerfile5 karena penempatan perintah COPY yang lebih baik.

Metode 5:Gunakan Dockerignore

Sebagai aturan, hanya file yang diperlukan yang perlu disalin melalui gambar buruh pelabuhan.

Docker dapat mengabaikan file yang ada di direktori kerja jika dikonfigurasi di .dockerignore berkas.

Fitur ini harus diingat saat mengoptimalkan gambar buruh pelabuhan.

Metode 6:Simpan Data Aplikasi di Tempat Lain

Menyimpan data aplikasi dalam gambar tidak perlu meningkatkan ukuran gambar.

Sangat disarankan untuk menggunakan fitur volume runtime container untuk memisahkan gambar dari data.

Alat Pengoptimalan Gambar Docker

Berikut adalah beberapa alat sumber terbuka yang akan membantu Anda mengoptimalkan

  1. Menyelam :Ini adalah alat penjelajah gambar yang membantu Anda menemukan lapisan dalam gambar wadah Docker &OCI. Menggunakan menyelam, Anda dapat menemukan cara untuk mengoptimalkan gambar Docker Anda. Lihat repo Dive Github untuk detail selengkapnya.
  2. Docker Slim: Ini membantu Anda mengoptimalkan gambar Docker Anda untuk keamanan dan ukuran. Lihat repo Docker Slim Github untuk detail selengkapnya.

Saya akan terus menambahkan alat ke daftar ini.


Docker
  1. Cara Menggunakan Dockerfile untuk Membangun Gambar Docker

  2. Cara Memodifikasi Gambar Docker

  3. Cara membuat Gambar Docker dari Wadah dan File Docker

  1. Cara Memindahkan Gambar Docker antar Host

  2. Cara Berbagi Gambar Docker Dengan Orang Lain

  3. Cara memperbarui/menambahkan file di Gambar Docker

  1. Cara Membuat Gambar Docker dengan Dockerfile

  2. Ukuran Gambar Docker - Bagaimana Menjaganya Tetap Kecil?

  3. Cara melakukan perubahan pada gambar Docker