Pokud chcete zmenšit velikost obrázku dockeru , musíte při vytváření obrazu Dockeru použít standardní doporučené postupy.
Tento blog pojednává o různých technikách optimalizace, které můžete rychle implementovat, abyste vytvořili co nejmenší a minimální obrázek ukotvitelné stanice . Podíváme se také na některé z nejlepších nástrojů pro optimalizaci obrázků Docker .
Docker jako kontejnerový engine usnadňuje vzít kus kódu a spustit jej v kontejneru. Umožňuje inženýrům shromáždit všechny závislosti kódu a soubory do jediného umístění, které lze spustit kdekoli, poměrně rychle a snadno.
Celý koncept obrázků „spustit kdekoli“ začíná jednoduchým konfiguračním souborem s názvem Dockerfile. Nejprve do Dockerfile přidáme všechny pokyny k sestavení, jako jsou závislosti kódu, příkazy a podrobnosti o základním obrázku.
Need for Docker Image Optimization
Přestože je proces sestavení Dockeru snadný, mnoho organizací dělá chybu při vytváření nadupaných obrázků Docker bez optimalizace obrázků kontejneru.
Při typickém vývoji softwaru bude mít každá služba více verzí/vydání a každá verze vyžaduje více závislostí, příkazů a konfigurací. To představuje výzvu při vytváření bitové kopie Dockeru, stejně jako nyní – vytvoření stejného kódu vyžaduje více času a zdrojů, než jej lze odeslat jako kontejner.
Viděl jsem případy, kdy počáteční obraz aplikace začínal na 350 MB a postupem času se rozrostl na více než 1,5 GB.
Instalací nežádoucích knihoven také zvyšujeme šanci na potenciální bezpečnostní riziko tím, že zvyšujeme plochu útoku.
Proto musí inženýři DevOpsoptimalizovat obrázky dockerů abyste zajistili, že obraz dockeru nebude nafouknutý po sestavení aplikace nebo budoucích vydáních. Nejen pro produkční prostředí, v každé fázi procesu CI/CD byste měli optimalizovat obrázky dockeru.
S nástroji pro orchestraci kontejnerů, jako je Kubernetes, je také nejlepší mít obrázky malé velikosti, aby se zkrátil čas přenosu obrázků a nasazení .
Jak zmenšit velikost obrázku Docker?
Pokud vezmeme obrázek kontejneru typické aplikace, obsahuje základní obrázek, Dependencies/Files/Configs , a cruft (nežádoucí software).
Vše se tedy scvrkává na to, jak efektivně dokážeme spravovat tyto zdroje uvnitř obrazu kontejneru.
Podívejme se na různé zavedené metody optimalizace obrázků Docker Kromě toho jsme uvedli praktické příklady pro pochopení optimalizace obrazu dockeru v reálném čase.
Buď použijete příklady uvedené v článku, nebo vyzkoušejte optimalizační techniky na existujících souborech Dockerfiles.
Níže jsou uvedeny metody, kterými můžeme dosáhnout optimalizace obrazu dockeru.
- Používání základních obrazů bez distribuce/minimálního počtu
- Vícestupňová sestavení
- Minimalizace počtu vrstev
- Porozumění ukládání do mezipaměti
- Použití Dockerignore
- Uchovávání dat aplikace jinde
Soubory cvičení Docker: Veškerý kód aplikace, soubory Dockerfiles a konfigurace použité v tomto článku jsou hostovány v tomto úložišti Github. Můžete jej naklonovat a postupovat podle návodu.
Metoda 1:Použijte minimální základní obrázky
Nejprve byste se měli zaměřit na výběr správného základního obrazu s minimálními nároky na operační systém.
Jedním z takových příkladů jsou obrázky alpské základny. Obrázky Alpine mohou mít až 5,59 MB . Není jen malý; je to také velmi bezpečné.
alpine latest c059bfaa849c 5.59MB
Nginx alpine základní obrázek má pouze 22 MB.
Ve výchozím nastavení je dodáván s shellem sh, který pomáhá ladit kontejner jeho připojením.
Velikost základního obrázku můžete dále zmenšit pomocí obrázků bez distribuce. Jedná se o zkrácenou verzi operačního systému. Základní obrázky Distroless jsou dostupné pro java, nodejs, python, Rust atd.
Obrázky Distroless jsou tak minimální, žev nich není ani skořápka . Můžete se tedy zeptat, jak tedy ladíme aplikace? Mají ladicí verzi stejného obrazu, který je dodáván s busyboxem pro ladění.
Také většina distribucí má nyní své minimální základní obrazy.
Poznámka: Veřejně dostupné základní obrazy nemůžete přímo používat v prostředí projektu. Chcete-li použít základní bitovou kopii, musíte získat souhlas týmu podnikového zabezpečení. V některých organizacích samotný bezpečnostní tým publikuje základní obrazy každý měsíc po testování a bezpečnostní kontrole. Tyto obrázky budou dostupné ve společném soukromém úložišti dockeru organizace.
Metoda 2:Použijte vícefázové sestavení Docker
Vzorec vícefázového sestavení se vyvinul z konceptu vzoru stavitele, kde používáme různé soubory Dockerfiles pro vytváření a balení kódu aplikace. I když tento vzor pomáhá zmenšit velikost obrázku, klade malé nároky na budování potrubí.
Ve vícestupňovém sestavení získáme podobné výhody jako vzor stavitele. Používámeprostřední obrázky (fáze sestavení) ke kompilaci kódu, instalaci závislostí a balení souborů v tomto přístupu. Smyslem toho je eliminovat nežádoucí vrstvy na obrázku.
Poté se do jiného obrázku zkopírují pouze soubory aplikace nezbytné ke spuštění aplikace s pouze požadovanými knihovnami, tj. lehčí pro spuštění aplikace.
Podívejme se na to v praxi pomocí praktického příkladu, kdy vytvoříme jednoduchou aplikaci Nodejs a optimalizujeme její Dockerfile.
Nejprve vytvoříme kód. Budeme mít následující strukturu složek.
├── Dockerfile1
├── Dockerfile2
├── env
├── index.js
└── package.json
Následující uložte jako 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}`);
}
}
)
Následující uložte jako 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"
}
}
Uložte následující proměnnou portu do souboru s názvem env
.
PORT=8080
Jednoduchý Dockerfile
pro tuto aplikaci by to chtělo toto – Uložit jako Dockerfile1
.
FROM node:16
COPY . .
RUN npm installEXPOSE 3000
CMD [ "node", "index.js" ]
Podívejme se, jaký úložný prostor vyžaduje při jeho stavbě.
docker build -t devopscube/node-app:1.0 --no-cache -f Dockerfile1 .
Po dokončení stavby. Zkontrolujeme jeho velikost pomocí –
docker image ls
To je to, co dostáváme.
devopscube/node-app 1.0 b15397d01cca 22 seconds ago 910MB
Velikost je tedy 910MBs
.
Nyní použijeme tuto metodu k vytvoření vícefázového sestavení.
Použijeme node:16
jako základní obraz, tj. obraz pro všechny instalace závislostí a modulů, poté přesuneme obsah do minimální a lehčí ‘alpine
„založený obrázek. „alpine
“ obrázek má minimum užitečných funkcí, a proto je velmi světlý.
Zde je obrázkové znázornění vícefázového sestavení Docker.
Také v jediném Dockerfile
, můžete mít více fází s různými základními obrázky. Například můžete mít různé fáze pro sestavení, test, statickou analýzu a balíček s různými základními obrázky.
Pojďme se podívat, jak by mohl nový Dockerfile vypadat. Právě kopírujeme potřebné soubory ze základního obrázku do hlavního obrázku.
Uložte následující jako 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"]
Podívejme se, jaký úložný prostor vyžaduje při jeho stavbě.
docker build -t devopscube/node-app:2.0 --no-cache -f Dockerfile2 .
Po dokončení stavby. Zkontrolujeme jeho velikost pomocí
docker image ls
To je to, co dostáváme.
devopscube/node-app 2.0 fa6ae75da252 32 seconds ago 171MB
Takže nová zmenšená velikost obrázku je 171 MB ve srovnání s obrázkem se všemi závislostmi.
To je optimalizace o více než 80 %!
Pokud bychom však použili stejný základní obrázek, jaký jsme použili ve fázi sestavování, neviděli bychom velký rozdíl.
Velikost obrázku můžete dále zmenšit pomocí obrázků bez distribuce . Zde je stejný Dockerfile
s vícestupňovým krokem sestavení, který používá google nodeJS distroless image místo 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"]
Pokud vytvoříte výše uvedený soubor Dockerfile, váš obrázek bude mít 118 MB ,
devopscube/distroless-node 1.0 302990bc5e76 118MB
Metoda 3:Minimalizujte počet vrstev
Obrázky dockeru fungují následujícím způsobem – každý RUN, COPY, FROM
Pokyny Dockerfile přidávají novou vrstvu a každá vrstva prodlužuje dobu provádění sestavení a zvyšuje požadavky na úložiště obrázku.
Podívejme se na to v praxi pomocí praktického příkladu:pojďme vytvořit bitovou kopii ubuntu s aktualizovanými a upgradovanými knihovnami spolu s některými nezbytnými nainstalovanými balíčky, jako je vim, net-tools, dnsutils.
Dockerfile
Chcete-li toho dosáhnout, postupujte takto – Uložte to jako 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
Rádi bychom se také podívali na dobu sestavení tohoto obrázku.
Démon Docker má vestavěnou schopnost zobrazit celkovou dobu provádění souboru Dockerfile.
Chcete-li tuto funkci povolit, proveďte následující kroky –
- Vytvořte
daemon.json
soubor s následujícím obsahem v/etc/docker/
{
"experimental": true
}
2. Pro aktivaci funkce spusťte následující příkaz.
export DOCKER_BUILDKIT=1
Pojďme to postavit a podívat se na úložiště a dobu sestavení.
time docker build -t devopscube/optimize:3.0 --no-cache -f Dockerfile3 .
V terminálu by se zobrazily časy provádění.
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
Po dokončení sestavení – doba provedení bude 117,1 sekund .
Zkontrolujeme jeho velikost pomocí
docker image ls
To je to, co dostáváme.
devopscube/optimize 3.0 9601bcac0100 About a minute ago 227MB
Takže velikost je 227 MB .
Pojďme zkombinovat příkazy RUN do jedné vrstvy a uložit ji jako 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
Ve výše uvedeném příkazu RUN jsme použili --no-install-recommends
flag pro zakázání doporučených balíčků. Doporučuje se vždy, když používáte install
ve vašich Dockerfiles
Podívejme se na úložný prostor a čas potřebný k sestavení.
time docker build -t devopscube/optimize:4.0 --no-cache -f Dockerfile4 .
V terminálu by se zobrazily časy provádění.
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
Po dokončení sestavení – doba provedení bude 91,7 sekund.
Zkontrolujeme jeho velikost pomocí
docker image ls
To je to, co dostáváme.
devopscube/optimize 4.0 37d746b976e3 42 seconds ago 216MB
Velikost je tedy 216 MB.
Pomocí této techniky optimalizace se doba provádění zkrátila z 117,1 s na 91,7 s a velikost úložiště byla snížena z 227 MB na 216 MB.
Metoda 4:Pochopení ukládání do mezipaměti
Často musí být stejný obrázek znovu a znovu vytvořen s mírnými úpravami v kódu.
Docker v takových případech pomáhá tím, že ukládá mezipaměť každé vrstvy sestavení a doufá, že by to mohlo být užitečné v budoucnu.
Kvůli tomuto konceptu se doporučuje přidat řádky, které se používají pro instalaci závislostí a balíčků dříve v Dockerfile – před příkazy COPY.
Důvodem je to, že docker by byl schopen uložit do mezipaměti obraz s požadovanými závislostmi a tuto mezipaměť lze poté použít v následujících sestaveních, když se kód upraví.
Podívejme se například na následující dva soubory Docker.
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 by mohl využívat funkce mezipaměti lépe s Dockerfile6 než Dockerfile5 kvůli lepšímu umístění příkazu COPY.
Metoda 5:Použijte Dockerignore
Zpravidla je třeba přes obraz dockeru zkopírovat pouze nezbytné soubory.
Docker může ignorovat soubory v pracovním adresáři, pokud je nakonfigurován v .dockerignore
soubor.
Tuto funkci je třeba mít na paměti při optimalizaci obrazu dockeru.
Metoda 6:Uchovávejte aplikační data jinde
Ukládání dat aplikace do obrázku zbytečně zvětší velikost obrázků.
Důrazně se doporučuje používat funkci objemu běhových modulů kontejneru, aby byl obraz oddělen od dat.
Nástroje pro optimalizaci obrázků Docker
Níže jsou uvedeny některé z nástrojů s otevřeným zdrojovým kódem, které vám pomohou optimalizovat
- Potápění :Jedná se o nástroj pro průzkumník obrázků, který vám pomůže objevit vrstvy v obrázcích kontejnerů Docker a OCI. Pomocí potápění můžete najít způsoby, jak optimalizovat obrázky Dockeru. Další podrobnosti najdete v repozitáři Dive Github.
- Docker Slim: Pomáhá vám optimalizovat vaše obrázky Docker pro zabezpečení a velikost. Další podrobnosti najdete v repozitáři Docker Slim Github.
Do tohoto seznamu budu průběžně přidávat nástroje.