Docker - podstawy zarządzania obrazami

Red Hat 7.x / CentOS 7.x
Jak wspomniałem w poprzedniej części (Docker - instalacja i zarządzanie kontenerami) podstawą uruchomienia kontenera w naszym środowisku są obrazy (images). W tej części zajmiemy się tym aspektem architektury Dockera.

Zarządzanie obrazami Dockera

Podstawowym, domyślnie skonfigurowanym repozytorium obrazów dockera jest hub.docker.com. Dostępne dla nas obrazy możemy przeglądać poprzez stronę www pod tym adresem. Znajdziemy tam opisy obrazów, informacje o wersji, tagi oraz komentarze i opinie użytkowników dockera na temat danego systemu.

Wizyta na stronie nie jest jednak jedyną metodą na wyszukiwanie w repozytorium interesujących nas obrazów. Możemy to robić również bezpośrednio z poziomu serwera przy pomocu polecenia docker search

[docker@docker-base ~]$ docker search ubuntu
INDEX       NAME                                        DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/ubuntu                            Ubuntu is a Debian-based Linux operating s...   3489      [OK]
docker.io   docker.io/ubuntu-upstart                    Upstart is an event-based replacement for ...   60        [OK]
docker.io   docker.io/torusware/speedus-ubuntu          Always updated official Ubuntu docker imag...   25                   [OK]
docker.io   docker.io/ubuntu-debootstrap                debootstrap --variant=minbase --components...   24        [OK]
docker.io   docker.io/rastasheep/ubuntu-sshd            Dockerized SSH service, built on top of of...   23                   [OK]
docker.io   docker.io/neurodebian                       NeuroDebian provides neuroscience research...   20        [OK]
docker.io   docker.io/nickistre/ubuntu-lamp             LAMP server on Ubuntu                           6                    [OK]
docker.io   docker.io/nickistre/ubuntu-lamp-wordpress   LAMP on Ubuntu with wp-cli installed            5                    [OK]
docker.io   docker.io/nuagebec/ubuntu                   Simple always updated Ubuntu docker images...   4                    [OK]
docker.io   docker.io/nimmis/ubuntu                     This is a docker images different LTS vers...   3                    [OK]
docker.io   docker.io/maxexcloo/ubuntu                  Docker base image built on Ubuntu with Sup...   2                    [OK]
docker.io   docker.io/avatao/ubuntu                     Ubuntu for challenges                           1                    [OK]
docker.io   docker.io/darksheer/ubuntu                  Base Ubuntu Image -- Updated hourly             1                    [OK]
docker.io   docker.io/jordi/ubuntu                      Ubuntu Base Image                               1                    [OK]
docker.io   docker.io/esycat/ubuntu                     Ubuntu LTS                                      0                    [OK]
docker.io   docker.io/konstruktoid/ubuntu               Ubuntu base image                               0                    [OK]
docker.io   docker.io/life360/ubuntu                    Ubuntu is a Debian-based Linux operating s...   0                    [OK]
docker.io   docker.io/lynxtp/ubuntu                     https://github.com/lynxtp/docker-ubuntu         0                    [OK]
docker.io   docker.io/rallias/ubuntu                    Ubuntu with the needful                         0                    [OK]
docker.io   docker.io/suzlab/ubuntu                     ubuntu                                          0                    [OK]
docker.io   docker.io/teamrock/ubuntu                   TeamRock's Ubuntu image configured with AW...   0                    [OK]
docker.io   docker.io/ustclug/ubuntu                    ubuntu image for docker with USTC mirror        0                    [OK]
docker.io   docker.io/uvatbc/ubuntu                     Ubuntu images with unprivileged user            0                    [OK]
docker.io   docker.io/webhippie/ubuntu                  Docker images for ubuntu                        0                    [OK]
docker.io   docker.io/widerplan/ubuntu                  Our basic Ubuntu images.                        0                    [OK]

Wynik polecenia zwraca nam w postaci kolumnowej informacje o nazwie repozytorium w którym znajduje się dany obraz, jego nazwę, krótki opis, ocenę użytkowników (STARS), a także informację o tym, czy dany obraz jest oficjalnie wspierany przez zespół dockera (OK w kolumnie OFFICIAL). Na tej podstawie możemy pobierać obrazy do lokalnego repozytorium serwera. Niestety póki co polecenie to nie umożliwia nam podglądania tagów obrazów, które są przydatne, jeśli zależy nam na konkretnej wersji.

Wspomniałem wcześniej o repozytorium lokalnym. Trafia do niego każdy obraz, na podstawie którego tworzony jest kontener. W dowolnej chwili możemy przejrzeć jego zawartość i zweryfikować jakie obrazy aktualnie posiadamy:

[docker@docker-base ~]$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
docker.io/busybox   latest              bc744c4ab376        6 days ago          1.113 MB
docker.io/httpd     latest              ee4a5faa57f7        3 weeks ago         193.3 MB

Znajdziemy tu informacje z jakiego repozytorium obraz pochodzi oraz jego nazwę, tag danego obrazu, ID obrazu, kiedy został utworzony oraz jaki zajmuje obszar dyskowy.

Wiemy jak sprawdzać repozytoria, czas zatem poznać metody pracy z nimi.

W pierwszej kolejności zależeć nam będzie na pobieraniu obrazów. Będziemy potrzebowali do tego znajomości nazwy obrazu oraz ewentualnie taga wersji. Konwencja nazewnicza przy operacjach na obrazach wygląda następująco: nazwa_repo/nazwa_obrazu:tag (w docker search wyświetlane jako docker.io/nazwa_repo/nazwa_obrazu). Jeśli pominiemy nazwę repo obraz będzie pobrany z domyślnego repozytorium (library, czyli obraz widniejący w docker search jako docker.io/nazwa_obrazu). Jeśli pominiemy tag operować będziemy na pakietach otagowanych jako latest.

[docker@docker-base ~]$ docker pull ubuntu
Using default tag: latest
Trying to pull repository docker.io/library/ubuntu ... latest: Pulling from library/ubuntu

808ef855e5b6: Pull complete
267903aa9bd1: Pull complete
d28d8a6a946d: Pull complete
ab035c88d533: Pull complete
Digest: sha256:1bea66e185d3464fec1abda32ffaf2a11de69833cfcf81bd2b9a5be147776814
Status: Downloaded newer image for docker.io/ubuntu:latest

Tym sposobem pobraliśmy do lokalnego repo obraz ubuntu w wersji latest. Na potwierdzenie sprawdzamy zawartość repo lokalnego:

[docker@docker-base ~]$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
docker.io/ubuntu    latest              ab035c88d533        6 days ago          187.9 MB
docker.io/busybox   latest              bc744c4ab376        6 days ago          1.113 MB
docker.io/httpd     latest              ee4a5faa57f7        3 weeks ago         193.3 MB

Możemy pobrać konkretną wersję (sprawdzając tagi na stronie hub.docker.com), np:

[docker@docker-base ~]$ docker pull ubuntu:14.04
Trying to pull repository docker.io/library/ubuntu ... 14.04: Pulling from library/ubuntu

808ef855e5b6: Already exists
267903aa9bd1: Already exists
d28d8a6a946d: Already exists
ab035c88d533: Already exists
Digest: sha256:1c8b813b6b6656e9a654bdf29a7decfcc73b92a62b934adc4253b0dc2be9d0a2
Status: Downloaded newer image for docker.io/ubuntu:14.04

Hmmm... niespodzianka - otrzymujemy komunikat "Alredy exists" i nic się nie pobiera, sprawdźmy zatem nasze lokalne repo:

[docker@docker-base ~]$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
docker.io/ubuntu    latest              ab035c88d533        6 days ago          187.9 MB
docker.io/ubuntu    14.04               ab035c88d533        6 days ago          187.9 MB
docker.io/busybox   latest              bc744c4ab376        6 days ago          1.113 MB
docker.io/httpd     latest              ee4a5faa57f7        3 weeks ago         193.3 MB

Okazuje się, że wersja otagowana jako 14.04 to ten sam obraz (taki sam IMAGE ID) co wersja latest - obraz się nie pobrał bo faktycznie jest już na dysku. W lokalnym repo pojawił się jednak dodatkowy wpis otagowany jako 14.04.

Kolejnym poleceniem, które pomoże nam w zarządzaniu obrazami będzie docker rmi. Polecenie pozwala usunąć z dysku niepotrzebne już obrazy, zwalniając przy tym zajmowane przez nie miejsce. Do usunięcia obrazu potrzebować będziemy jego nazwy oraz taga, lub IMAGE ID. Jedna uwaga: nie uda się nam usunąć obrazu, jeśli istnieje korzystający z niego kontener! Przy czym nie jest ważne czy kontener jest aktywny czy nie - jeśli obraz istnieje w liście docker ps -a usuwanie zakończy się błędem.

[docker@docker-base ~]$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
docker.io/ubuntu    latest              ab035c88d533        6 days ago          187.9 MB
docker.io/ubuntu    14.04               ab035c88d533        6 days ago          187.9 MB
docker.io/busybox   latest              bc744c4ab376        6 days ago          1.113 MB
docker.io/httpd     latest              ee4a5faa57f7        3 weeks ago         193.3 MB
[docker@docker-base ~]$ docker rmi bc744c4ab376
Untagged: docker.io/busybox:latest
Deleted: bc744c4ab376115cc45c610d53f529dd2d4249ae6b35e5d6e7a96e58863545aa
Deleted: 56ed16bd6310cca65920c653a9bb22de6b235990dcaa1742ff839867aed730e5
[docker@docker-base ~]$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
docker.io/ubuntu    14.04               ab035c88d533        6 days ago          187.9 MB
docker.io/ubuntu    latest              ab035c88d533        6 days ago          187.9 MB
docker.io/httpd     latest              ee4a5faa57f7        3 weeks ago         193.3 MB

Jak widać obraz zniknął z naszego repo.

Muszę tu jeszcze wspomnieć o jednym przypadku - a mianowicie naszym obrazie ubuntu. W repozytorium widnieje dwukrotnie, ale ma ten sam image id. Usunięcie obrazu z wykorzystaniem tego id poprzez docker rmi ab035c88d533 usunie z repo plik obrazu, więc znikną obie pozycje. Jeśli chcemy usunąć tylko jedną z nich należy posłużyć się ich nazwą oraz tagiem: docker rmi ubuntu:14.04.

TIP: jeśli chcemy szybko wyczyścić nasze lokalne repo usuwając wszystkie dostępne obrazy, możemy to zrobić przez docker rmi $(docker images -q)

Tworzenie własnych obrazów

Kontenery tworzone na bazie obrazów, póki istnieją w systemie są tworami trwałymi, jeśli chodzi o zmiany wewnątrz nich. Tzn. jeśli utworzysz kontener na bazie obrazu i zmienisz w nim konfigurację, przetrwa ona restarty kontenera. Będzie ona jednak zmieniona tylko w jego obrębie, więc jeśli utworzysz drugi kontener, na bazie tego samego obrazu - konfiguracja będzie domyślną konfiguracją obrazu.
Dlatego szybko odkryjesz potrzebę tworzenia własnych obrazów. Choćby taka sytuacja: chcesz uruchomić 20 systemów ubuntu. W każdym z nich, dajmy na to, ma istnieć 5 Twoich userów, ma on korzystać z customowego pliku /etc/hosts i ma mieć doinstalowany jakiś pakiet. Możesz rzecz jasna logować się do każdego kontenera i wprowadzać te zmiany... ale po co?

Przydatna będzie tu pierwsza z metod tworzenia własnych obrazów dockera - obraz na podstawie kontenera. Tworzysz kontener bazowy, na którym wprowadzasz wymagane zmiany. Może to być dodanie plików, pakietów, użytkowników, zmiany w konfiguracji, cokolwiek innego. Po zakończeniu konfiguracji tworzysz obraz, na podstawie którego możesz uruchomić kolejne kontenery, i będą one dziedziczyły konfigurację z Twojego obrazu.

Szybki przykład. Uruchamiamy kontener na bazie obrazu ubuntu:

[root@docker-base ~]# docker run -itd ubuntu
5be36e595f63dec02677fc9f43068274eb58abb5de8b341c16848a917b19ad3d
[root@docker-base ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
5be36e595f63        ubuntu              "/bin/bash"         5 seconds ago       Up 3 seconds                            adoring_heisenberg

W kontenerze tworzymy usera, np. o nazwie docker:

[root@docker-base ~]# docker exec -it adoring_heisenberg bash
root@5be36e595f63:/# id docker
id: docker: no such user
root@5be36e595f63:/# useradd docker
root@5be36e595f63:/# id docker
 uid=1000(docker) gid=1000(docker) groups=1000(docker)

Jak widać, domyślnie usera nie było, ale udało się go utworzyć. Stwórzmy zatem nasz obraz. Użyjemy do tego polecenia docker commit nazwa_kontenera nazwa_nowego_obrazu:

[root@docker-base ~]# docker commit adoring_heisenberg ubuntu_z_userem
bdb8fa2baf1462bba28cb481db4310cf7f93e4b30d157a55d913e24c0ba11021
[root@docker-base ~]# docker images
REPOSITORY                TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu_z_userem           latest              bdb8fa2baf14        5 seconds ago       188.3 MB
docker.io/ubuntu          latest              ab035c88d533        2 weeks ago         187.9 MB
docker.io/busybox         latest              bc744c4ab376        2 weeks ago         1.113 MB

Polecenie utworzyło nam nowy obraz... Tworzymy na jego podstawie kolejny kontener:

[root@docker-base ~]# docker run -itd ubuntu_z_userem
4c3b3a0891921da5b659add59d35d07d3e4b492cb4c873a3bed8ce927349f437
[root@docker-base ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
4c3b3a089192        ubuntu_z_userem     "/bin/bash"         4 seconds ago       Up 2 seconds                            reverent_jones
5be36e595f63        ubuntu              "/bin/bash"         8 minutes ago       Up 8 minutes                            adoring_heisenberg
[root@docker-base ~]# docker exec -it reverent_jones bash
root@4c3b3a089192:/# id docker
uid=1000(docker) gid=1000(docker) groups=1000(docker)

Nasz nowy kontener posiada prekonfigurowanego usera docker.
Metoda ta pozwala nam na stworzenie obrazu bazowego do dalszych zabaw, ale również możemy ją wykorzystywać do zapisywania kamieni milowych naszej pracy :)

Druga z metod polega na budowaniu obrazów na podstawie plików konfiguracyjnych Dockerfile, ale temat jest na tyle obszerny i zaawansowany, że nie będę go poruszał na etapie zaznajamiania się z Dockerem. Jest również na tyle interesujący, że z pewnością popełnię o nim jakiś tekst.

Dodatkowe informacje o obrazach

Docker pozwala nam uzyskać pewne informacje na temat dostępnych obrazów. Pierwszym poleceniem, które możemy zastosować również w odniesieniu do kontenera jest docker inspect. Polecenie wyświetla nam w formie tablicy json-a parametry konfiguracyjne, jakie zostaną użyte do uruchomienia kontenera. Przykładowy output komendy dla obrazu ubuntu:

[root@docker-base ~]# docker inspect ubuntu
[
{
    "Id": "ab035c88d533b656f25574a9f6f6dde8e8a9badf004d748690e9ee0b17205781",
    "Parent": "d28d8a6a946d1a1b25a6f4b438d1e92858a17bc58e15c5945d3ae12753a2883d",
    "Comment": "",
    "Created": "2016-03-18T18:24:28.818918568Z",
    "Container": "85c4705d113ecf7f3ae704f1b7597c5b6bc919fb8ac83e3fa5987ab49cc8153e",
    "ContainerConfig": {
        "Hostname": "f5ee59d47428",
        "Domainname": "",
        "User": "",
        "AttachStdin": false,
        "AttachStdout": false,
        "AttachStderr": false,
        "ExposedPorts": null,
        "PublishService": "",
        "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": [],
        "Cmd": [
            "/bin/sh",
            "-c",
            "#(nop) CMD [\"/bin/bash\"]"
        ],
        "Image": "d28d8a6a946d1a1b25a6f4b438d1e92858a17bc58e15c5945d3ae12753a2883d",
        "Volumes": null,
        "VolumeDriver": "",
        "WorkingDir": "",
        "Entrypoint": null,
        "NetworkDisabled": false,
        "MacAddress": "",
        "OnBuild": null,
        "Labels": {}
    },
    "DockerVersion": "1.9.1",
    "Author": "",
    "Config": {
        "Hostname": "f5ee59d47428",
        "Domainname": "",
        "User": "",
        "AttachStdin": false,
        "AttachStdout": false,
        "AttachStderr": false,
        "ExposedPorts": null,
        "PublishService": "",
        "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": [],
        "Cmd": [
            "/bin/bash"
        ],
        "Image": "d28d8a6a946d1a1b25a6f4b438d1e92858a17bc58e15c5945d3ae12753a2883d",
        "Volumes": null,
        "VolumeDriver": "",
        "WorkingDir": "",
        "Entrypoint": null,
        "NetworkDisabled": false,
        "MacAddress": "",
        "OnBuild": null,
        "Labels": {}
    },
    "Architecture": "amd64",
    "Os": "linux",
    "Size": 0,
    "VirtualSize": 187939858,
    "GraphDriver": {
        "Name": "devicemapper",
        "Data": {
            "DeviceId": "357",
            "DeviceName": "docker-253:1-8396148-ab035c88d533b656f25574a9f6f6dde8e8a9badf004d748690e9ee0b17205781",
            "DeviceSize": "107374182400"
        }
    }
}
]

Możemy zobaczyć tu jakie parametry były zdefiniowane dla obrazu - ustawienia sieciowe, komendy inicjacyjne kontenera, informacje o autorze, konfiguracji obrazu itd. Większość z nich definiowana jest w pliku Dockerfile użytym do stworzenia obrazu. Na początku znajomości z dockerem informacje te nie koniecznie muszą okazać się przydatne (przynajmniej w odniesieniu do obrazów).

Kolejnym poleceniem, które dostarczy nam informacji będzie docker history. Wyświetla ono historię (przynajmniej w teorii) poleceń, które zostały wykonane przed zacommitowaniem obrazu. Celowo piszę, że "przynajmniej w teorii", bo wpisy te są dla mnie zrozumiałe do momentu, kiedy tyczą się oryginalnego obrazu. Dobrze widać to na przykładzie tworzonego wcześniej "ubuntu_z_userem":

[root@docker-base ~]# docker history ubuntu_z_userem
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
bdb8fa2baf14        About an hour ago   /bin/bash                                       329.3 kB
ab035c88d533        2 weeks ago         /bin/sh -c #(nop) CMD ["/bin/bash"]             0 B
d28d8a6a946d        2 weeks ago         /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/   1.895 kB
267903aa9bd1        2 weeks ago         /bin/sh -c set -xe                                                  && echo '#!/bin/sh' > /u   194.5 kB
808ef855e5b6        2 weeks ago         /bin/sh -c #(nop) ADD file:e01d51d39ea04c8efb   187.7 MB

Nasze dodanie usera przedstawia się tu jako /bin/bash. Dla mnie totalnie niezrozumiałe, ale pewnie to kwestia poziomu zaawansowania.

Brak komentarzy:

Prześlij komentarz