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:
RUN
RUN
index.html
index.html
index.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.html
RUN
, 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() {
.Println("hello world")
fmt}
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/hello
postgres
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 pull
Istnieje 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 myapache
Kiedy 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.yml
version: 3.9
services:
container1:
image: ubuntu
command: sleep infinity
container2:
image: ubuntu
command: sleep infinity
container1
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)