Předpokládám, že jste trochu obeznámeni s Dockerem a znáte základy, jako je provozování dockerových kontejnerů atd.
V předchozích článcích jsme diskutovali o aktualizaci kontejneru dockeru a psaní souborů dockeru.
Co přesně je úprava obrazu dockeru?
Obrázek kontejneru je vytvořen ve vrstvách (nebo je to kolekce vrstev), každá instrukce Dockerfile vytváří vrstvu obrázku. Zvažte například následující Dockerfile:
FROM alpine:latest
RUN apk add --no-cache python3
ENTRYPOINT ["python3", "-c", "print('Hello World')"]
Protože existují celkem tři příkazy Dockerfile, bude obraz vytvořený z tohoto Dockerfile obsahovat celkem tři vrstvy.
Můžete to potvrdit vytvořením obrázku:
docker image built -t dummy:0.1 .
A poté pomocí příkazu docker image history
na vytvořeném obrázku.
articles/Modify a Docker Image on modify-docker-images [?] took 12s
❯ docker image history dummy:0.1
IMAGE CREATED CREATED BY SIZE COMMENT
b997f897c2db 10 seconds ago /bin/sh -c #(nop) ENTRYPOINT ["python3" "-c… 0B
ee217b9fe4f7 10 seconds ago /bin/sh -c apk add --no-cache python3 43.6MB
28f6e2705743 35 hours ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 35 hours ago /bin/sh -c #(nop) ADD file:80bf8bd014071345b… 5.61MB
Poslední vrstvu „
Každá z těchto vrstev je pouze pro čtení. To je výhodné, protože vzhledem k tomu, že tyto vrstvy jsou pouze pro čtení, žádný proces spojený s běžící instancí tohoto obrazu nebude schopen upravit obsah tohoto obrazu, takže tyto vrstvy mohou být sdíleny mnoha kontejnery, aniž by bylo nutné uchovávat kopie pro každou instanci. Aby však procesy kontejnerů mohly provádět r/w, je při vytváření kontejnerů přidána další vrstva k existujícím vrstvám RO. Tato vrstva je zapisovatelná a není sdílena jinými kontejnery.
Nevýhodou této vrstvy r/w je, že změny provedené v této vrstvě nejsou trvalé, ačkoli můžete použít svazky k zachování některých dat, někdy můžete potřebovat/chtit přidat vrstvu před nějakou existující vrstvu nebo odstranit vrstvu z obrázek nebo jednoduše nahradit vrstvu. To jsou důvody, proč by bylo vhodné upravit stávající docker
obrázek.
V tomto článku se budu zabývat všemi případy, které jsem zmínil výše, za použití různých metod.
Metody úpravy obrázku dockeru
Existují dva způsoby, jak upravit obrázek dockeru.
- Prostřednictvím Dockerfiles.
- Pomocí příkazu
docker container commit
.
Vysvětlím obě metody a na závěr také doplním, který případ použití by byl pro metodu v kontextu lepší.
Metoda 1:Úprava obrazu dockeru prostřednictvím souboru Dockerfile
Úprava obrázku dockeru v podstatě znamená úpravu vrstev obrázku. Nyní, protože každý příkaz Dockerfile představuje jednu vrstvu obrázku, úprava každého řádku souboru Dockerfile změní i příslušný obrázek.
Pokud byste tedy k obrázku přidali vrstvu, můžete k ní jednoduše přidat další instrukci Dockerfile, pro odstranění jedné byste odstranili řádek a pro změnu vrstvy byste řádek podle toho změnili.
Existují dva způsoby, jak můžete pomocí Dockerfile upravit obrázek.
- Použití obrázku, který chcete upravit, jako základního obrázku a vytvoření podřízeného obrázku.
- Úprava skutečného Dockerfile obrázku, který chcete změnit.
Dovolte mi vysvětlit, která metoda by měla být použita, kdy a jak.
1. Použití obrázku jako základního obrázku
To je, když vezmete obrázek, který chcete upravit, a přidáte k němu vrstvy, abyste vytvořili nový podřízený obrázek. Pokud není obrázek vytvořen od začátku, každý obrázek je modifikací stejného nadřazeného základního obrázku.
Zvažte předchozí soubor Dockerfile. Řekněme, že sestavení obrázku z tohoto obrázku se jmenuje dummy:0.1
. Kdybych si teď myslel, že teď musím použít Perl místo Pythonu3 k tisku "Hello World", ale také nechci odstraňovat Python3, mohl bych použít dummy:0.1
image jako základní obrázek (protože Python3 již existuje) a sestavte z něj následovně
FROM dummy:0.1
RUN apk add --no-cache perl
ENTRYPOINT ["perl", "-e", "print \"Hello World\n\""]
Zde stavím na dummy:0.1
, přidáním dalších vrstev, jak uznám za vhodné.
Tato metoda nebude příliš užitečná, pokud je vaším záměrem změnit nebo odstranit některou existující vrstvu. K tomu musíte postupovat podle následující metody.
2. Úprava Dockerfile obrázku
Vzhledem k tomu, že existující vrstvy obrázku jsou pouze pro čtení, nemůžete je přímo upravovat prostřednictvím nového souboru Dockerfile. Pomocí FROM
příkazu v Dockerfile, vezmete nějaký obrázek jako základ a postavíte na nebo k němu přidat vrstvy.
Některé úkoly mohou vyžadovat, abychom změnili existující vrstvu, i když to můžete udělat pomocí předchozí metody s množstvím protichůdných RUN
pokyny (jako je mazání souborů, odstranění/nahrazení balíčků přidaných v některé předchozí vrstvě), není to ideální řešení nebo to, co bych doporučil. Protože přidává další vrstvy a značně zvětšuje velikost obrázku.
Lepší metodou by bylo nepoužívat obrázek jako základní obrázek, ale změnit skutečný Dockerfile tohoto obrázku. Zvažte znovu předchozí Dockerfile, co kdybych nemusel ponechat Python3 v tomto obrazu a nahradit balíček Python3 a příkaz těmi z Perlu?
Pokud bych postupoval podle předchozí metody, musel bych vytvořit nový soubor Dockerfile -
FROM dummy:0.1
RUN apk del python3 && apk add --no-cache perl
ENTRYPOINT ["perl", "-e", "print \"Hello World\n\""]
Pokud bude tento obrázek vytvořen, bude mít celkem pět vrstev.
articles/Modify a Docker Image on modify-docker-images [?] took 3s
❯ docker image history dummy:0.2
IMAGE CREATED CREATED BY SIZE COMMENT
2792036ddc91 10 seconds ago /bin/sh -c #(nop) ENTRYPOINT ["perl" "-e" "… 0B
b1b2ec1cf869 11 seconds ago /bin/sh -c apk del python3 && apk add --no-c… 34.6MB
ecb8694b5294 3 hours ago /bin/sh -c #(nop) ENTRYPOINT ["python3" "-c… 0B
8017025d71f9 3 hours ago /bin/sh -c apk add --no-cache python3 && … 43.6MB
28f6e2705743 38 hours ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 38 hours ago /bin/sh -c #(nop) ADD file:80bf8bd014071345b… 5.61MB
Velikost obrázku je také 83,8 MB.
articles/Modify a Docker Image on modify-docker-images [?]
❯ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
dummy 0.2 2792036ddc91 19 seconds ago 83.8MB
Nyní místo toho vezměte počáteční soubor Dockerfile a změňte soubory Python3 na Perl takto
FROM alpine:latest
RUN apk add --no-cache perl
ENTRYPOINT ["perl", "-e", "print \"Hello World\n\""]
Počet vrstev se snížil na 3 a velikost je nyní 40,2 MB.
articles/Modify a Docker Image on modify-docker-images [?] took 3s
❯ docker image history dummy:0.3
IMAGE CREATED CREATED BY SIZE COMMENT
f35cd94c92bd 9 seconds ago /bin/sh -c #(nop) ENTRYPOINT ["perl" "-e" "… 0B
053a6a6ba221 9 seconds ago /bin/sh -c apk add --no-cache perl 34.6MB
28f6e2705743 38 hours ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 38 hours ago /bin/sh -c #(nop) ADD file:80bf8bd014071345b… 5.61MB
articles/Modify a Docker Image on modify-docker-images [?]
❯ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
dummy 0.3 f35cd94c92bd 29 seconds ago 40.2MB
Obrázek byl úspěšně změněn.
Předchozí metoda je užitečnější, když se chystáte pouze přidat vrstvy na stávající vrstvy, ale není příliš užitečná, když se pokoušíte upravit existující vrstvy, jako je odstranění jedné, nahrazení jedné, změna pořadí stávajících a již brzy. To je místo, kde tato metoda září.
Metoda 2:Úprava obrazu pomocí docker commit
Existuje další metoda, kdy můžete pořídit snímek běžícího kontejneru a přeměnit jej na vlastní obrázek.
Pojďme vytvořit dummy:0.1
identický obrázek, ale tentokrát bez použití Dockerfile. Protože jsem použil alpine:latest
jako dummy:0.1
's base, roztočte kontejner tohoto obrázku.
docker run --rm --name alpine -ti alpine ash
Nyní do kontejneru přidejte balíček Python3, apk add --no-cache python3
. Po dokončení otevřete nové okno terminálu a spusťte následující příkaz (nebo něco podobného)
docker container commit --change='ENTRYPOINT ["python3", "-c", "print(\"Hello World\")"]' alpine dummy:0.4
Pomocí --change
flag Přidávám instrukci Dockerfile do nového dummy:04
obrázek (v tomto případě ENTRYPOINT
instrukce).
Pomocí docker container commit
V podstatě převedete nejvzdálenější r/w vrstvu na r/o vrstvu, přidáte ji k vrstvám stávajícího obrázku a vytvoříte nový obrázek. Tato metoda je intuitivnější/interaktivnější, takže ji možná budete chtít použít místo Dockerfiles, ale uvědomte si, že to není příliš reprodukovatelné. Stejná pravidla platí také pro odstranění nebo změnu jakýchkoli existujících vrstev, přidání vrstvy jen za účelem odstranění něčeho nebo změny něčeho provedeného v předchozí vrstvě není nejlepší nápad, alespoň ve většině případů.
Tím tento článek končí. Doufám, že vám to pomohlo, pokud máte nějaké dotazy, napište níže.