Diferència entre revisions de la pàgina «ASIX/M11/UF4/EX2»

De Lordwektabyte Wiki
Salta a la navegació Salta a la cerca
m (Guillem ha mogut M11/UF4/EX2 a ASIX/M11/UF4/EX2 sense deixar una redirecció: Crear subnivell ASIX)
 
(Hi ha 50 revisions intermèdies del mateix usuari que no es mostren)
Línia 1: Línia 1:
{{titol|Docker}}
+
==Objectius==  
==Objectius==
 
 
*Instal·lar l'entorn Docker (seguir indicacions als docs de Docker).
 
*Instal·lar l'entorn Docker (seguir indicacions als docs de Docker).
 
*Comprovar que funciona (''docker run''...).
 
*Comprovar que funciona (''docker run''...).
Línia 22: Línia 21:
 
</source>
 
</source>
  
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.
+
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 amb el nom ''docker'', afegiré el meu usuari en aquest grup.
 
<source>
 
<source>
 
usermod -aG docker guillem
 
usermod -aG docker guillem
 
</source>
 
</source>
  
:'''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.
+
{{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 haver-ho de fer 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===
 
===Prova inicial===
Línia 43: Línia 42:
 
Hello from Docker!
 
Hello from Docker!
 
This message shows that your installation appears to be working correctly.
 
This message shows that your installation appears to be working correctly.
 
+
 
To generate this message, Docker took the following steps:
 
To generate this message, Docker took the following steps:
 
  1. The Docker client contacted the Docker daemon.
 
  1. The Docker client contacted the Docker daemon.
Línia 69: Línia 68:
 
===Docker Hub===
 
===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).
 
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:
+
Jo mateix m'hi he registrat i he creat un ''repo'' públic per als exercicis que fem a ASIX amb l'usuari '''lordwektabyte'''.
 
{{imatge|M11UF4EX2-1.png}}
 
{{imatge|M11UF4EX2-1.png}}
  
Línia 98: Línia 97:
  
 
Veiem que com a "Debian" hi ha imatges del propi Debian i també d'Ubuntu; com a derivat d'aquest.
 
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í
 +
<source>
 +
$ docker run -it ubuntu
 +
 +
 +
root@3760d3de5750:/#
 +
</source>
 +
{{nota|Hem de diferenciar que en mode '''I'''nteractiu amb '''T'''erminal 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.
 +
<source>
 +
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.
 +
</source>
 +
<source>
 +
root@3760d3de5750:/# apt install apache2
 +
 +
 +
Reading package lists... Done
 +
( . . . )
 +
Processing triggers for libc-bin (2.27-3ubuntu1) ...
 +
</source>
 +
<source>
 +
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
 +
</source>
 +
 +
Finalment engeguem el servidor Apache.
 +
<source>
 +
root@3760d3de5750:/# apache2ctl start
 +
</source>
 +
 +
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 <code>docker ps</code>.
 +
 +
{{nota|Aquesta comanda l'haurem d'executar des de l'amfitrió, per tant, ens deslligarem del terminal del contenidor (sense aturar-lo) amb <code>Ctrl+P Ctrl+Q</code>}}
 +
 +
<source>
 +
$ docker ps
 +
 +
 +
CONTAINER ID        IMAGE              COMMAND            CREATED            STATUS              PORTS              NAMES
 +
3760d3de5750        ubuntu              "/bin/bash"        13 minutes ago      Up 13 minutes                          wonderful_cartwright
 +
</source>
 +
 +
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 <code>inspect</code>
 +
<source>
 +
$ 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
 +
                }
 +
            }
 +
        }
 +
    }
 +
]
 +
</source>
 +
 +
Si ens fixem en l'apartat ''Networks'', veurem que hi ha una línia corresponent a l'adreça IP
 +
<source>
 +
"IPAddress": "172.17.0.2",
 +
</source>
 +
 +
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 <code>ifconfig</code> o <code>ip -a</code> 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.
 +
{{imatge|M11UF4EX2-2.png||thumb|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 <code>commit</code> des del terminal del sistema amfitrió i després <code>push</code> per a pujar-lo al ''repo'' remot, a l'estil de Git.
 +
<source>
 +
$ docker commit -a "LordWektabyte" wonderful_cartwright lordwektabyte/m11-apache
 +
 +
 +
sha256:1abfc7a84850c4a503438a89a20c8a662206dd12f3ad1e5b039c8629eb399870
 +
</source>
 +
<source>
 +
$ 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
 +
</source>
 +
 +
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.
 +
 +
Si ara accedim pel navegador a https://hub.docker.com veurem el nostre nou repo que acabem de crear:
 +
{{imatge|M11UF4EX2-3.png|El ''repo'' m11-apache ja apareix}}
 +
 +
===Mapeig de ports===
 +
Amb el paràmetre <code>-p</code> podem definir un mapejat de ports entre la màquina amfitriona i el contenidor; com si es tractés d'un ''PAT'' (Port Address Translation). Si engeguem el servidor amb l'ordre
 +
<source>
 +
$ docker run -it -p 8080:80 lordwektabyte/m11-apache
 +
</source>
 +
engeguem l'apache
 +
<source>
 +
root@e9e3d447df48:/# apachectl start
 +
</source>
 +
 +
i accedim des de l'amfitrió a http://localhost:8080 estarem dins del mateix contenidor que si entrem per la xarxa virtualitzada pels contenidors
 +
{{imatge|M11UF4EX2-4.png}}
 +
 +
Des de la consola de l'amfitrió podem llistar els ports que s'han mapejat amb <code>port</code>
 +
<source>
 +
$ docker port vibrant_wright
 +
 +
 +
80/tcp -> 0.0.0.0:8080
 +
</source>
 +
Aquest mètode pot ésser interessant si muntem un servidor en un contenidor i aquest ha de ser accedit des de la xarxa: el ''host'' fa de pont (a mode de NAT) entre la xarxa física i el contenidor.
 +
 +
===Persistència de dades===
 +
Els contenidors ''per se'' no tenen persistència i les dades modificades es perden al morir. Per a afegir persistència s'han de mapejar '''volums''' des del sistema de fitxers amfitrió cap al sistema de fitxers del contenidor per tal de mantenir-los més enllà de la vida del ''container''.
 +
En l'exemple d'Apache seria interessant afegir un mapeig per al directori <code>/var/www/html</code> del contenidor amb una ruta de l'amfitrió com ara <code>/dades/docker/m11-apache</code>. Aleshores podrem arrencar contenidors d'Apache que tinguin les dades permanentment en un sistema de fitxers real (no volàtil) i fins i tot poder-los editar des de l'amfitrió (en cas de fer ''deployments'' d'aplicacions web, en aquest cas.
 +
 +
Primer de tot crearem el directori a la màquina física:
 +
<source>
 +
$ mkdir /dades/docker-vol/
 +
$ mkdir /dades/docker-vol/m11-apache
 +
mkdir /dades/docker-vol/m11-apache/html
 +
</source>
 +
 +
Llavors arrencarem el nostre contenidor amb el paràmetre <code>-v</code> per a "lligar" el directori <code>/dades/docker/volums/m11-apache/html</code> amb el directori base de l'Apache del contenidor:
 +
<source>
 +
$ docker run -it -v /dades/docker/volums/m11-apache/html:/var/www/html lordwektabyte/m11-apache
 +
</source>
 +
 +
Si des de l'amfitrió accedim al servidor web veurem que no hi ha res:
 +
{{imatge|M11UF4EX2-5.png}}
 +
 +
Ara bé, si des de l'amfitrió creem un arxiu al directori que hem mapejat, veurem que se serveix des del contenidor; ja que el directori físic i virtual els hem lligat.
 +
Afegim contingut a l'arxiu <code>index.html</code>.
 +
<source>
 +
$ echo "Aquest arxiu es troba al Fedora de'n Guillem i el serveix Apache des d'un contenidor" > /dades/docker-vol/m11-apache/html/index.html
 +
</source>
 +
Entrem amb navegador web al contenidor.
 +
{{imatge|M11UF4EX2-6.png|Ara el contingut que serveix l'Apache és l'arxiu que hem creat abans}}
 +
 +
===''Build'' d'imatge amb Docker Compose===
 +
Per tal d'optimitzar la posada en marxa de contenidors, és interessant automatitzar el desplegament d'aquests utilitzant arxius <code>dockerfile</code> que facin les accions pertinents per, en el nostre cas, aixecar un servidor web Apache en qüestió de segons.
 +
Per fer això necessitarem crear un directori a l'amfitrió per al "projecte". Jo he fet un durectori <code>/dades/docker/compose</code> on hi penjaran els diversos projectes que fem. En aquest cas, crearé un directori <code>1-apache</code> i dins hi afegiré un arxiu <code>Dockerfile</code> amb el contingut necessari per a posar en marxa un Apache basat en la imatge oficial d'Ubuntu.
 +
<source>
 +
$ mkdir /dades/docker/compose/1-apache
 +
</source>
 +
 +
Creem l'arxiu ''Dockerfile'' necessari per a poder fer el ''build'' d'aquesta imatge automàticament.
 +
<source>
 +
nano /dades/docker/compose/1-apache/Dockerfile
 +
 +
 +
FROM library/ubuntu
 +
MAINTAINER LordWektabyte
 +
 +
# Actualitzem repositoris i instal·lem Apache
 +
RUN apt-get update && \
 +
apt-get install -y apache2 && \
 +
apt-get clean && apt-get autoclean
 +
 +
# NO fa el mapeig del port però dóna informació per saber quins ports hem de mapejar.
 +
#El mapeig l'haurem de fer amb -p 8080:80
 +
EXPOSE 80
 +
 +
# NO mapeja el volum. Només notifica el volum que s'hauria de muntar en l'amfitrió.
 +
# El mapeig l'haurem de fer amb -v /dades/docker/volums/m11-apache/html:/var/www/html
 +
VOLUME ["/var/www/html/"]
 +
 +
# Comanda que s'executarà al contenidor. En aquest cas engeguem APACHE en primer pla.       
 +
# Si l'engeguéssim en segon pla, escaparia de la consola i el contenidor mor.
 +
CMD /usr/sbin/apache2ctl -D FOREGROUND
 +
</source>
 +
 +
Llavors executem el <code>build</code>
 +
<source>
 +
$ docker build -t lordwektabyte/m11-apache /dades/docker/compose/1-apache
 +
 +
 +
Sending build context to Docker daemon  2.56kB
 +
Step 1/6 : FROM library/ubuntu
 +
---> 94e814e2efa8
 +
Step 2/6 : MAINTAINER LordWektabyte
 +
---> Running in 0ebb8bca293d
 +
Removing intermediate container 0ebb8bca293d
 +
---> b00704323232
 +
Step 3/6 : RUN apt-get update && apt-get install -y apache2 && apt-get clean && apt-get autoclean
 +
---> Running in e6c2da1dd766
 +
Get:1 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
 +
( . . . )
 +
Reading state information...
 +
Removing intermediate container e6c2da1dd766
 +
---> 77c072a5d0a2
 +
Step 4/6 : EXPOSE 80
 +
---> Running in 9a473ae3e067
 +
Removing intermediate container 9a473ae3e067
 +
---> 4801a5f5a438
 +
Step 5/6 : VOLUME ["/var/www/html/"]
 +
---> Running in af5dfc6dfe11
 +
Removing intermediate container af5dfc6dfe11
 +
---> e0fd8bc81911
 +
Step 6/6 : CMD /usr/sbin/apache2ctl -D FOREGROUND
 +
---> Running in d984f0abfa66
 +
Removing intermediate container d984f0abfa66
 +
---> 0c8aa1208ae8
 +
Successfully built 0c8aa1208ae8
 +
Successfully tagged lordwektabyte/m11-apache:latest
 +
</source>
 +
 +
Un cop acabat, executem el contenidor com a dimoni (ara sense mode interactiu) amb:
 +
<source>
 +
$ docker run -d -p 8080:80 -v /dades/docker/volums/m11-apache/html/:/var/www/html lordwektabyte/m11-apache
 +
dbf860d8c12e037e173d49c656ed5c4f97090058d8e99abb412f242cd6ba593a
 +
</source>
 +
 +
Podem mirar l'estat amb <code>ps</code>
 +
<source>
 +
$ docker ps
 +
CONTAINER ID        IMAGE                      COMMAND                  CREATED            STATUS              PORTS                  NAMES
 +
dbf860d8c12e        lordwektabyte/m11-apache  "/bin/sh -c '/usr/sb…"  26 seconds ago      Up 24 seconds      0.0.0.0:8080->80/tcp  condescending_lovelace
 +
</source>
 +
 +
Efectivament, el contenidor està corrent.
 +
Si en qualsevol moment volem matar-lo sense haver de fer ''attach'', podem fer-ho amb <code>kill</code>
 +
<source>
 +
$ docker kill condescending_lovelace
 +
condescending_lovelace
 +
</source>
 +
 +
===Exemple de Docker Compose===
 +
En aquest cas crearem un arxiu ''.yml'' amb els paràmetres necessaris per a automatitzar la tasca d'arrencada d'un contenidor. Tot i això, la idea d'aquesta eina és l'orquestació de contenidors per a poder definir dependències entre ells en el moment d'engegar-los.
 +
Per al nostre exemple serà suficient crear l'arxiu <code>docker-compose.yml</code> a la ruta <code>/dades/docker/compose/1-apache</code> amb el següent contingut
 +
<source>
 +
nano /dades/docker/compose/1-apache/docker-compose.yml
 +
 +
version: '3'
 +
services:   
 +
  web:       
 +
    build: /dades/docker/compose/1-apache
 +
    ports:
 +
    - "8080:80"
 +
    volumes:
 +
    - /dades/docker/volums/m11-apache/html:/var/www/html
 +
</source>
 +
 +
ara és qüestió d'engegar el contenidor/s que estiguin especificats en aquest arxiu amb <code>docker-compose</code>. La comanda s'ha d'executar des del directori on es troba l'arxiu <code>docker-compose.yml</code>.
 +
{{nota|És necessari tenir instal·lat el paquet <code>docker-compose</code>, que no es troba en ''Docker''. En cas de no tenir-lo instal·lat, cercar-lo als repositoris.}}
 +
<source>
 +
docker-compose up -d
 +
 +
 +
Creating network "1-apache_default" with the default driver
 +
Building web
 +
Step 1/6 : FROM library/ubuntu
 +
---> 94e814e2efa8
 +
Step 2/6 : MAINTAINER LordWektabyte
 +
---> Using cache
 +
---> b00704323232
 +
Step 3/6 : RUN apt-get update && apt-get install -y apache2 && apt-get clean && apt-get autoclean
 +
---> Using cache
 +
---> 77c072a5d0a2
 +
Step 4/6 : EXPOSE 80
 +
---> Using cache
 +
---> 4801a5f5a438
 +
Step 5/6 : VOLUME ["/var/www/html/"]
 +
---> Using cache
 +
---> e0fd8bc81911
 +
Step 6/6 : CMD /usr/sbin/apache2ctl -D FOREGROUND
 +
---> Using cache
 +
---> 0c8aa1208ae8
 +
Successfully built 0c8aa1208ae8
 +
Successfully tagged 1-apache_web:latest
 +
WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
 +
Creating 1-apache_web_1 ... done
 +
</source>
 +
 +
Si fem una ullada als contenidors que estan corrent ara, veiem que el nom del contenidor ja no és un aleatori sinó que correspon amb el nom que li hem donat nosaltres.
 +
<source>
 +
$ docker ps
 +
 +
CONTAINER ID        IMAGE              COMMAND                  CREATED              STATUS              PORTS                  NAMES
 +
043ef5c11418        1-apache_web        "/bin/sh -c '/usr/sb…"  About a minute ago  Up 58 seconds      0.0.0.0:8080->80/tcp  1-apache_web_1
 +
</source>
 +
 +
Amb <code>docker inspect</code> he esbrinat que el contenidor està a 172.18.0.2.
 +
{{imatge|M11UF4EX2-7.png||thumb|Com és d'esperar, se serveix l'''index'' del volum mapejat}}

Revisió de 11:32, 15 abr 2020

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 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 haver-ho de fer 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 amb l'usuari lordwektabyte.

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.

Si ara accedim pel navegador a https://hub.docker.com veurem el nostre nou repo que acabem de crear:

S'ha produït un error en crear la miniatura: No es pot desar la miniatura a la destinació


Mapeig de ports

Amb el paràmetre -p podem definir un mapejat de ports entre la màquina amfitriona i el contenidor; com si es tractés d'un PAT (Port Address Translation). Si engeguem el servidor amb l'ordre

$ docker run -it -p 8080:80 lordwektabyte/m11-apache

engeguem l'apache

root@e9e3d447df48:/# apachectl start

i accedim des de l'amfitrió a http://localhost:8080 estarem dins del mateix contenidor que si entrem per la xarxa virtualitzada pels contenidors

S'ha produït un error en crear la miniatura: No es pot desar la miniatura a la destinació


Des de la consola de l'amfitrió podem llistar els ports que s'han mapejat amb port

$ docker port vibrant_wright 


80/tcp -> 0.0.0.0:8080

Aquest mètode pot ésser interessant si muntem un servidor en un contenidor i aquest ha de ser accedit des de la xarxa: el host fa de pont (a mode de NAT) entre la xarxa física i el contenidor.

Persistència de dades

Els contenidors per se no tenen persistència i les dades modificades es perden al morir. Per a afegir persistència s'han de mapejar volums des del sistema de fitxers amfitrió cap al sistema de fitxers del contenidor per tal de mantenir-los més enllà de la vida del container. En l'exemple d'Apache seria interessant afegir un mapeig per al directori /var/www/html del contenidor amb una ruta de l'amfitrió com ara /dades/docker/m11-apache. Aleshores podrem arrencar contenidors d'Apache que tinguin les dades permanentment en un sistema de fitxers real (no volàtil) i fins i tot poder-los editar des de l'amfitrió (en cas de fer deployments d'aplicacions web, en aquest cas.

Primer de tot crearem el directori a la màquina física:

$ mkdir /dades/docker-vol/
$ mkdir /dades/docker-vol/m11-apache
mkdir /dades/docker-vol/m11-apache/html

Llavors arrencarem el nostre contenidor amb el paràmetre -v per a "lligar" el directori /dades/docker/volums/m11-apache/html amb el directori base de l'Apache del contenidor:

$ docker run -it -v /dades/docker/volums/m11-apache/html:/var/www/html lordwektabyte/m11-apache

Si des de l'amfitrió accedim al servidor web veurem que no hi ha res:

S'ha produït un error en crear la miniatura: No es pot desar la miniatura a la destinació


Ara bé, si des de l'amfitrió creem un arxiu al directori que hem mapejat, veurem que se serveix des del contenidor; ja que el directori físic i virtual els hem lligat. Afegim contingut a l'arxiu index.html.

$ echo "Aquest arxiu es troba al Fedora de'n Guillem i el serveix Apache des d'un contenidor" > /dades/docker-vol/m11-apache/html/index.html

Entrem amb navegador web al contenidor.

S'ha produït un error en crear la miniatura: No es pot desar la miniatura a la destinació


Build d'imatge amb Docker Compose

Per tal d'optimitzar la posada en marxa de contenidors, és interessant automatitzar el desplegament d'aquests utilitzant arxius dockerfile que facin les accions pertinents per, en el nostre cas, aixecar un servidor web Apache en qüestió de segons. Per fer això necessitarem crear un directori a l'amfitrió per al "projecte". Jo he fet un durectori /dades/docker/compose on hi penjaran els diversos projectes que fem. En aquest cas, crearé un directori 1-apache i dins hi afegiré un arxiu Dockerfile amb el contingut necessari per a posar en marxa un Apache basat en la imatge oficial d'Ubuntu.

$ mkdir /dades/docker/compose/1-apache

Creem l'arxiu Dockerfile necessari per a poder fer el build d'aquesta imatge automàticament.

nano /dades/docker/compose/1-apache/Dockerfile


FROM library/ubuntu
MAINTAINER LordWektabyte

# Actualitzem repositoris i instal·lem Apache
RUN apt-get update && \
apt-get install -y apache2 && \
apt-get clean && apt-get autoclean

# NO fa el mapeig del port però dóna informació per saber quins ports hem de mapejar.
#El mapeig l'haurem de fer amb -p 8080:80
EXPOSE 80

# NO mapeja el volum. Només notifica el volum que s'hauria de muntar en l'amfitrió.
# El mapeig l'haurem de fer amb -v /dades/docker/volums/m11-apache/html:/var/www/html
VOLUME ["/var/www/html/"]

# Comanda que s'executarà al contenidor. En aquest cas engeguem APACHE en primer pla.         
# Si l'engeguéssim en segon pla, escaparia de la consola i el contenidor mor.
CMD /usr/sbin/apache2ctl -D FOREGROUND

Llavors executem el build

$ docker build -t lordwektabyte/m11-apache /dades/docker/compose/1-apache


Sending build context to Docker daemon   2.56kB
Step 1/6 : FROM library/ubuntu
 ---> 94e814e2efa8
Step 2/6 : MAINTAINER LordWektabyte
 ---> Running in 0ebb8bca293d
Removing intermediate container 0ebb8bca293d
 ---> b00704323232
Step 3/6 : RUN apt-get update && apt-get install -y apache2 && apt-get clean && apt-get autoclean
 ---> Running in e6c2da1dd766
Get:1 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
( . . . )
Reading state information...
Removing intermediate container e6c2da1dd766
 ---> 77c072a5d0a2
Step 4/6 : EXPOSE 80
 ---> Running in 9a473ae3e067
Removing intermediate container 9a473ae3e067
 ---> 4801a5f5a438
Step 5/6 : VOLUME ["/var/www/html/"]
 ---> Running in af5dfc6dfe11
Removing intermediate container af5dfc6dfe11
 ---> e0fd8bc81911
Step 6/6 : CMD /usr/sbin/apache2ctl -D FOREGROUND
 ---> Running in d984f0abfa66
Removing intermediate container d984f0abfa66
 ---> 0c8aa1208ae8
Successfully built 0c8aa1208ae8
Successfully tagged lordwektabyte/m11-apache:latest

Un cop acabat, executem el contenidor com a dimoni (ara sense mode interactiu) amb:

$ docker run -d -p 8080:80 -v /dades/docker/volums/m11-apache/html/:/var/www/html lordwektabyte/m11-apache
dbf860d8c12e037e173d49c656ed5c4f97090058d8e99abb412f242cd6ba593a

Podem mirar l'estat amb ps

$ docker ps
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                  NAMES
dbf860d8c12e        lordwektabyte/m11-apache   "/bin/sh -c '/usr/sb…"   26 seconds ago      Up 24 seconds       0.0.0.0:8080->80/tcp   condescending_lovelace

Efectivament, el contenidor està corrent. Si en qualsevol moment volem matar-lo sense haver de fer attach, podem fer-ho amb kill

$ docker kill condescending_lovelace
condescending_lovelace

Exemple de Docker Compose

En aquest cas crearem un arxiu .yml amb els paràmetres necessaris per a automatitzar la tasca d'arrencada d'un contenidor. Tot i això, la idea d'aquesta eina és l'orquestació de contenidors per a poder definir dependències entre ells en el moment d'engegar-los. Per al nostre exemple serà suficient crear l'arxiu docker-compose.yml a la ruta /dades/docker/compose/1-apache amb el següent contingut

nano /dades/docker/compose/1-apache/docker-compose.yml

version: '3'
services:    
  web:         
    build: /dades/docker/compose/1-apache
    ports: 
     - "8080:80"
    volumes: 
     - /dades/docker/volums/m11-apache/html:/var/www/html

ara és qüestió d'engegar el contenidor/s que estiguin especificats en aquest arxiu amb docker-compose. La comanda s'ha d'executar des del directori on es troba l'arxiu docker-compose.yml.


Nota: És necessari tenir instal·lat el paquet docker-compose, que no es troba en Docker. En cas de no tenir-lo instal·lat, cercar-lo als repositoris.


docker-compose up -d


Creating network "1-apache_default" with the default driver
Building web
Step 1/6 : FROM library/ubuntu
 ---> 94e814e2efa8
Step 2/6 : MAINTAINER LordWektabyte
 ---> Using cache
 ---> b00704323232
Step 3/6 : RUN apt-get update && apt-get install -y apache2 && apt-get clean && apt-get autoclean
 ---> Using cache
 ---> 77c072a5d0a2
Step 4/6 : EXPOSE 80
 ---> Using cache
 ---> 4801a5f5a438
Step 5/6 : VOLUME ["/var/www/html/"]
 ---> Using cache
 ---> e0fd8bc81911
Step 6/6 : CMD /usr/sbin/apache2ctl -D FOREGROUND
 ---> Using cache
 ---> 0c8aa1208ae8
Successfully built 0c8aa1208ae8
Successfully tagged 1-apache_web:latest
WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating 1-apache_web_1 ... done

Si fem una ullada als contenidors que estan corrent ara, veiem que el nom del contenidor ja no és un aleatori sinó que correspon amb el nom que li hem donat nosaltres.

$ docker ps

CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                  NAMES
043ef5c11418        1-apache_web        "/bin/sh -c '/usr/sb…"   About a minute ago   Up 58 seconds       0.0.0.0:8080->80/tcp   1-apache_web_1

Amb docker inspect he esbrinat que el contenidor està a 172.18.0.2.

Com és d'esperar, se serveix l'index del volum mapejat