Docker

De Lordwektabyte Wiki
Salta a la navegació Salta a la cerca

Objectius

  • Instal·lar l'entorn Docker (seguir indicacions als docs de Docker).
  • Comprovar que funciona (docker run...).
  • Crear un compte al DockerHub i iniciar sessió en entorn de comandes.
  • Busqueu al DockerHub quines imatges oficials de Debian hi ha disponibles.
  • Crear el primer contenidor Docker amb Ubuntu (a partir de la imatge oficial), en mode interactiu.
  • Desconectar-se del contenidor i tornar-s'hi a connectar.
  • Crear un Dockerfile mínim per a generar un contenidor partint d'una imatge Debian Wheezy.

Procediment

Instal·lació de l'entorn

Tenint en compte que estic sobre Fedora 29, instal·larem l'entorn de Docker de la següent manera (com a root):

dnf install docker-ce

Després d'instal·lar, engegarem i habilitarem el servei de Docker perquè s'engegui automàticament on boot

systemctl start docker
systemctl enable docker

Pot ser interessant executar comandes de Docker sense necessitat de permisos de superusuari root; pel que podem afegir el nostre usuari al grup docker del Linux. Assumint que la instal·lació ha creat un nou grup d'Unix amb el nom docker, afegiré el meu usuari en aquest grup.

usermod -aG docker guillem
Nota: per tal de gaudir dels privilegis d'aquest nou grup, l'usuari haurà de tancar sessió i tornar a autenticar-se al sistema per tal que es reavaluïn els seus grups. Fins llavors no serà possible arrencar contenidors, per exemple, sense fer login amb root. Així doncs, podem tancar sessió al sistema i tornar a entrar abans de seguir amb els següents passos si volem fer-ho amb el nostre usuari no-privilegiat.

Prova inicial

Per a comprovar el funcionament correcte podem engegar un contenidor simple que ens mostrarà un "Hello World" per pantalla

$ docker run hello-world


Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete 
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

En tots els casos, si no tenim localment la còpia de la imatge del contenidor que volem descarregar, Docker la cercarà als repositoris públics (Docker Hub) i la copiarà al sistema per si es necessita més endavant. Després d'executar la comanda veiem que, segons sembla, tot és correcte i ja tenim a punt l'entorn per a virtualitzar contenidors.

Docker Hub

Des de https://hub.docker.com/ ens podem registrar i tenir el nostre repositori públic/privat d'imatges de Docker que podem accedir des de qualsevol lloc (sempre i quan tinguem accés a Internet). Jo mateix m'hi he registrat i he creat un repo públic per als exercicis que fem a ASIX:

M11UF4EX2-1.png


Després de registrar-nos podem iniciar sessió des del mateix terminal de Fedora per a poder pujar les nostres imatges de contenidors al repositori.

$ docker login -u lordwektabyte


Password: 
WARNING! Your password will be stored unencrypted in /home/guillem/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

Imatges Debian

Podem buscar-ho amb el navegador web o bé per terminal amb l'ordre search i paràmetres per tal de filtrar les imatges oficials.

$ docker search debian --filter is-official=true


NAME                DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
ubuntu              Ubuntu is a Debian-based Linux operating sys…   9333                [OK]                
debian              Debian is a Linux distribution that's compos…   3022                [OK]   

Veiem que com a "Debian" hi ha imatges del propi Debian i també d'Ubuntu; com a derivat d'aquest.

Contenidor Ubuntu

Per a executar el primer contenidor Ubuntu en mode interactiu ho farem així

$ docker run -it ubuntu


root@3760d3de5750:/# 
Nota: hem de diferenciar que en mode Interactiu amb Terminal se'ns obre el terminal propi del contenidor amb l'usuari root. No estem ja dins de Fedora sinó dins del contenidor.

A partir d'aquí, per a fer la prova, podríem instal·lar un programa de servei com ara Apache per poder comprovar el funcionament i la comunicació amb el contenidor. Des del terminal de Docker que se'ns ha obert abans, farem una instal·lació normal com si es tractés d'un Ubuntu pròpiament.

root@3760d3de5750:/# apt update


Get:1 http://archive.ubuntu.com/ubuntu bionic InRelease [242 kB]
( . . . )
5 packages can be upgraded. Run 'apt list --upgradable' to see them.
root@3760d3de5750:/# apt install apache2


Reading package lists... Done
( . . . )
Processing triggers for libc-bin (2.27-3ubuntu1) ...
root@3760d3de5750:/# mv /var/www/html/index.html /var/www/html/index.html.old
root@3760d3de5750:/# echo "Apache en Ubuntu dins de Docker de'n Guillem" > /var/www/html/index.html 

Finalment engeguem el servidor Apache.

root@3760d3de5750:/# apache2ctl start

Ara accedirem a l'adreça del contenidor que s'està executant mitjançant el navegador web del nostre sistema "amfitrió"; però necessitem saber quina adreça IP té assignada aquest contenidor. Per a saber-ho, treurem informació dels contenidors que estan en marxa amb la comanda docker ps.

Nota: aquesta comanda l'haurem d'executar des de l'amfitrió, per tant, ens deslligarem del terminal del contenidor (sense aturar-lo) amb Ctrl+P Ctrl+Q
$ docker ps


CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
3760d3de5750        ubuntu              "/bin/bash"         13 minutes ago      Up 13 minutes                           wonderful_cartwright

Ens fixarem amb la variable "NAME" (que docker assigna aleatòriament a no ser que li definim nosaltres al fer docker run) per a treure informació d'aquest contenidor amb la comanda inspect

$ docker inspect wonderful_cartwright
[
    {
        "Id": "3760d3de5750fbe8a766d29615cbe1b0c97ebe11f124e502fa12bace79fd14e6",
        "Created": "2019-03-24T18:44:34.980207153Z",
        "Path": "/bin/bash",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 6824,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2019-03-24T18:44:36.35967354Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:94e814e2efa8845d95b2112d54497fbad173e45121ce9255b93401392f538499",
        "ResolvConfPath": "/var/lib/docker/containers/3760d3de5750fbe8a766d29615cbe1b0c97ebe11f124e502fa12bace79fd14e6/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/3760d3de5750fbe8a766d29615cbe1b0c97ebe11f124e502fa12bace79fd14e6/hostname",
        "HostsPath": "/var/lib/docker/containers/3760d3de5750fbe8a766d29615cbe1b0c97ebe11f124e502fa12bace79fd14e6/hosts",
        "LogPath": "/var/lib/docker/containers/3760d3de5750fbe8a766d29615cbe1b0c97ebe11f124e502fa12bace79fd14e6/3760d3de5750fbe8a766d29615cbe1b0c97ebe11f124e502fa12bace79fd14e6-json.log",
        "Name": "/wonderful_cartwright",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {},
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "shareable",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DiskQuota": 0,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": 0,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/60c43748962b7286f5e91d7ad1851056777c27af96bd9d00a69e120de66b48fc-init/diff:/var/lib/docker/overlay2/14d356ffc23abe35d830492dafdfd71d40b351f3f57c4997daea0029c353299e/diff:/var/lib/docker/overlay2/35a7619c4006b1ae9de71c3a7dd37461b82277bb8fb7987ed3786d4c97b7ef46/diff:/var/lib/docker/overlay2/5909cffe001a341719a99c2c89f7de6617e76a822513d2b02f300d7ea50ff858/diff:/var/lib/docker/overlay2/87f60bcc3bb18e06d425da77091baa092efc24be09080b8f5fd40c75a3393cf8/diff",
                "MergedDir": "/var/lib/docker/overlay2/60c43748962b7286f5e91d7ad1851056777c27af96bd9d00a69e120de66b48fc/merged",
                "UpperDir": "/var/lib/docker/overlay2/60c43748962b7286f5e91d7ad1851056777c27af96bd9d00a69e120de66b48fc/diff",
                "WorkDir": "/var/lib/docker/overlay2/60c43748962b7286f5e91d7ad1851056777c27af96bd9d00a69e120de66b48fc/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "3760d3de5750",
            "Domainname": "",
            "User": "",
            "AttachStdin": true,
            "AttachStdout": true,
            "AttachStderr": true,
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": true,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "ArgsEscaped": true,
            "Image": "ubuntu",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "dedd4199d327d3d1df9ded3859ac04e0fe14dff0fadcd23435130a4b55ae78cb",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/dedd4199d327",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "18f1369f7f06f73565280f36e3b29035e259374e16954da61411cb62ef3f77e0",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "fa7f7eb1da9b86a66ffc1e9a632b8ded5bf4c8d49e988bf2ec1dbb9cff8f5d1b",
                    "EndpointID": "18f1369f7f06f73565280f36e3b29035e259374e16954da61411cb62ef3f77e0",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]

Si ens fixem en l'apartat Networks, veurem que hi ha una línia corresponent a l'adreça IP

"IPAddress": "172.17.0.2",

Hem d'entendre doncs, que el nostre Fedora (host) està en una xarxa "virtual" creada pel Docker on hi penjaran els diferents contenidors. Podem verificar-ho amb ifconfig o ip -a des de la nostra màquina amfitriona.

Aleshores només és qüestió d'accedir a l'adreça http://172.17.0.2 des del nostre navegador i veurem el missatge que hem definit abans a l'arxiu d'índex del servidor web.

S'ha produït un error en crear la miniatura: No es pot desar la miniatura a la destinació
Si tot és correcte, l'Apache ens respondrà


Pujar imatge modificada a Docker Hub

Si volem pujar aquesta imatge d'Ubuntu modificada a Docker Hub per a tenir-la disponible per posar en marxa en un altre sistema o bé compartir-la amb la comunitat ho farem amb l'ordre commit des del terminal del sistema amfitrió i després push per a pujar-lo al repo remot, a l'estil de Git.

$ docker commit -a "LordWektabyte" wonderful_cartwright lordwektabyte/m11-apache


sha256:1abfc7a84850c4a503438a89a20c8a662206dd12f3ad1e5b039c8629eb399870
$ docker push lordwektabyte/m11-apache


The push refers to repository [docker.io/lordwektabyte/m11-apache]
b5575c54be58: Pushed 
b57c79f4a9f3: Mounted from library/ubuntu 
d60e01b37e74: Mounted from library/ubuntu 
e45cfbc98a50: Mounted from library/ubuntu 
762d8e1a6054: Mounted from library/ubuntu 
latest: digest: sha256:84c7a7935e0887a8f55f0a0d331ad268e071e4ad43d04a9aa4312002fe9e1a47 size: 1362

Ens retorna un checksum que podríem desar per a comprovar la integritat de la imatge quan la tornem a posar en marxa o bé algú altre la descarregui.