Obraz kontenera to pakiet binarny zawierający wszystkie pliki oraz metadane niezbędne do uruchomienia kontenera
Obrazy kontenera możemy budować lokalnie lub pobrać z rejestrów (publicznych lub prywatnych)
Najpopularniejszym formatem obrazów jest ten wykorzystywany przez Dockera
Obraz Dockerowy jako plik to archiwum tar, w którym
umieszczone są metadane oraz warstwy
Każda warstwa składa się z własnych metadanych oraz
kolejnego archiwum tar zawierającego zestaw zmian jakie
warstwa wprowadza
Główne metadane obrazu znajdują się w pliku
manifest.json np.:
[
{
"Config": "f63181f19b2fe819156dcb068b3b5bc036820bec7014c5f77277cfa341d4cb5e.json",
"RepoTags": ["ubuntu:latest"],
"Layers": ["151ae8ef4f042fd5173fd2497f0a365b4413468163e7bd567146f29dcfea3517/layer.tar", "2872658e1abe34d0c7391abbc0848fdeddb456659e39511df0574fcfc8b7ad70/layer.tar", "2b83a9243dd8405d0811beeb14aeb797745b100e4538d056adb63fcc6b47c59f/layer.tar"]
}
]Mamy tutaj informację o użytych tagach dla tego obrazu w
repozytorium (RepoTags), listę warstw (Layers)
oraz ścieżkę do pliku konfiguracyjnego (Config)
zawierającego szereg informacji o wymaganej architekturze CPU, zmiennych
środowiskowych, itp.
Alternatywnym standardem obrazów kontenerów jest format OCI (Open Container Initiative)
Jest to również archiwum tar zawierające metadane
oraz zestaw binarnych paczek (blobów)
Metadane znajdują się w pliku index.json np.
{
"schemaVersion": 2,
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:7ad481b55901a1b5472c0e1b3fbf0bf2867dc38feb6eb7a18cd310f00208e05c",
"size": 658
}
]
}Manifest w formacie JSON znajduje się pliku
blobs/7ad4...e05c:
{
"schemaVersion": 2,
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"digest": "sha256:10bdc2317d43a5421151e135881e172002c7d61e934de7e1e79df560a151f112",
"size": 2427
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:f3f8f4bd7c131f4d967bc162207ab72c24f427915682f895eb4f793ad05d7e35",
"size": 29989546
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:0188b501936213b7cd0b5333245960781a8b035249cfa427fe9a229fe557c624",
"size": 924
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:db861e57845ea7ba52a2ac277abbdd8cd04bda5db69c49bf95be49d11e5a47e1",
"size": 202
}
]
}Podobnie jak w przykładzie dla Dockera, tutaj również mamy jeden plik konfiguracyjny oraz trzy pliki warstw
Oba przedstawione formaty dotyczą zapisu obrazu jako pojedynczego pliku, jednak taki projekt służy przede wszystkim wydajnemu cache’owaniu w przypadku transferu sieciowego
Kiedy pobierany jest obraz z rejestru to nie następuje ściągnięcie całego obrazu, ale porównanie które warstwy znajdują się już lokalnie i ściągnięcie tylko tych brakujących
Przykładowo:
cron,
ssh)Dockerfile zawierający instrukcję budowania (dokumentacja)FROM <image>, gdzie image to nazwa
obrazu, na którym bazujemyRUN <command> pozwala uruchomić
komendę command w ramach powstającego obrazu (np.
instalacja pakietu, stworzenie pliku, itp.)CMD <command> określa jaka jest
domyślna komenda uruchamiana podczas startu konteneraEXPOSE <port> dodaje metadane o tym,
że aplikacje wewnątrz kontenera nasłuchuje na porcie port
EXPOSE jest tylko
formą dokumentacjiENV <key>=<value> ustawia
zmienne środowiskoweCOPY <src> <dest> pozwala
skopiować pliki do obrazu konteneraUSER <user> ustawia bieżącego
użytkownika (dalsze instrukcje poniżej USER będą wykonywane
na prawach user)WORKDIR <path> ustawia bieżący katalog
roboczy (ścieżki relatywne w instrukcjach poniżej WORKDIR
będą rozwiązywane wg path)ARG <name> określa, że
name to argument, który należy podać na etapie budowania
obrazuDockerfile tworzymy przy
pomocy komendy docker build -t mytag ., gdzie
mytag oznacza nazwę obrazuDockerfile<!-- index.html -->
<h1>Hello World from Docker!</h1>FROM ubuntu
ENV DEBIAN_FRONTEND=noninteractive
COPY index.html /var/www/html/index.html
RUN apt-get update -y
RUN apt-get install -y apache2
EXPOSE 80
CMD ["/usr/sbin/apachectl", "-DFOREGROUND"]/bigfile, a obraz B rozszerza A
poprzez usunięcie /bigfile, to i tak obraz kontenera B
będzie zawierał wewnętrznie warstwę z zawartością pliku, której i tak
użytkownik końcowy nie będzie mógł odczytaćDockerfile każda instrukcja tworzy
osobną warstwę:
RUN w jedną,
która wykonuje wiele operacji jednocześnieRUN powinno się czyścić
wszystkie pliki tymczasowe by nie zostały zapisane w żadnej warstwie, w
szczególności:
RUNRUNindex.htmlindex.htmlindex.html wymusi utworzenie warstwy D od
nowaDockerfile po optymalizacjiFROM ubuntu
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -y \
&& apt-get install -y \
apache2 \
&& rm -rf /var/lib/apt/lists/*
EXPOSE 80
CMD ["/usr/sbin/apachectl", "-DFOREGROUND"]
COPY index.html /var/www/html/index.htmlRUN, ale jest to podatne na błędy, które trudno i
długo się naprawiaDockerfile opisuje
kilka obrazów, między którymi możemy swobodnie kopiować pliki// hello.go
package main
import "fmt"
func main() {
fmt.Println("hello world")
}FROM golang AS builder
COPY hello.go hello.go
RUN go build hello.go
FROM ubuntu
COPY --from=builder /go/hello /usr/bin/hello
CMD /usr/bin/hellopostgres pozwala na
konfigurację wielu aspektów poprzez zmienne środowiskowe np.
POSTGRESS_PASSWORD ustala hasło administratorapostgres pokazuje również jak
wypełnić bazę danymi przy pierwszym uruchomieniudocker push a
pobieramy komendą docker pullIstnieje kilka mechanizmów uruchamiania kontenerów, jednak najpopularniejszym jest Docker
Komenda docker run pozwala na uruchomienie kontenera
oraz konfigurację parametrów (dodatkowe zmienne środowiskowe,
przekierowanie portów, itp.)
Przykładowo, jeśli pierwszy przykład na tej stronie został
zbudowany jako myapache. to uruchomienie instancji wraz z
przekierowaniem portu 8080 w systemie gospodarzu do portu 80 w
kontenerze można wykonać tak:
docker run --publish 8080:80 myapacheKiedy kontener działa, można sprawdzić w przeglądarce
http://localhost:8080
services zawiera mapowanie nazw do opisów
kontenerówimage: nazwę obrazucommand: komenda (jeśli potrzebna jest inna
niż domyślna)volumes: listę wolumenów do podłączenia podczas
uruchomieniaports: listę przekierowań portówenvironment: listę zmiennych środowiskowychdocker-compose.ymlversion: 3.9
services:
container1:
image: ubuntu
command: sleep infinity
container2:
image: ubuntu
command: sleep infinitycontainer1 możemy adresować drugi kontener korzystając z
nazwy hosta container2 (i vice versa)Dockerfile, która stworzy obraz
kontenera systemowego z całością rozwijanego projektu: baza danych,
frontend, backend (ocena 3.0)docker-compose.yml,
która uruchomi cały projekt na podstawie kontenerów aplikacyjnych (ocena
5.0)