Taula de continguts

Dockerfile : creant les nostres pròpies imatges

El Dockerfile ens permetrà crear els nostres propis contenidors personalitzats.

Veurem com crear un contenidor «des de zero» o from scratch, afegint només els arxius del SO imprescindibles per a la funció que volem resoldre.

També veurem com extendre contenidors ja fets (habitualment partint d'una distribució standard com Debian, Ubuntu, Centos o Alpine) i afegir-los el servei o funció que necessitem.

Referències:

Tenim diverses maneres de crear una imatge Docker:

  1. A partir d'un Dockerfile.
  2. Descarregant-la de Docker Hub (docker pull).
  3. Utilitzant docker commit per guardar els canvis que podem fer en un contenidor en marxa.
, , , , , , , , , , , , ,


Primer Dockerfile from scratch

Una primera versió elemental del Dockerfile seria aquesta:

Dockerfile
# imatge base. "scratch" => imatge buida
FROM scratch
 
WORKDIR /
 
# Afegim arxius al contenidor des de la carpeta local "src"
ADD src /
 
# CMD o ENTRYPOINT van al final per posar en marxa un servei en primer plànol
CMD ["/bin/bash"]

Els fitxers que posarem a la carpeta src local són els que ens calen per poder executar bash. Això ho podem saber amb la instrucció ldd, que examina les dependències d'un binari i ens les mostra.

  1. Localitzem l'arxiu bash del SO base que tinguem:
    $ which bash
    /usr/bin/bash
  2. Ara que sabem quin és, consultem els arxius dels què depèn (aquest exemple és de Ubuntu 20.04):
    $ ldd /usr/bin/bash
    	linux-vdso.so.1 (0x00007ffd30bad000)
    	libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f4ae17f1000)
    	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4ae17eb000)
    	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4ae15f9000)
    	/lib64/ld-linux-x86-64.so.2 (0x00007f4ae196f000)
  3. Aquests arxius, amb el mateix nom exacte i les carpetes idèntiques, cal que els posem a la carpeta src perquè siguin copiades dins la imatge del contenidor.

La llibreria ''linux-vdso'' no cal carregar-la ja que vé mapejada al kernel per defecte.

Resumim aquí una relació d'aquests arxius finals que ens caldrà perquè bash funcioni:

.
├── Dockerfile
└── src
    ├── bin
    │   └── bash
    ├── lib
    │   └── x86_64-linux-gnu
    │       ├── libc.so.6
    │       ├── libdl.so.2
    │       └── libtinfo.so.6
    └── lib64
        └── ld-linux-x86-64.so.2

Construim imatge

Un cop tenim tots els arxius a la carpeta src amb les seves carpetes adequades, construïm la imatge amb:

$ docker build -t <tag> .

Si poseu un namespace al tag, i volem més tard pujar-ho a Docker Hub, convé que aquest namespace sigui el mateix de l'usuari on pujarem la imatge. Per exemple:

$ docker build -t enric/bashic:0.1 .

Podeu veure les vostres imates creades amb:

$ docker images

I la posem en marxa amb:

$ docker run -ti enric/bashic:0.1
bash-5.0#

És molt important que en aquest container no podem posar-ho en marxa amb el flag -d perquè si no es tancarà la shell, per això l'executem amb -ti amb emulació de terminal.

Podem provar un banal echo:

bash-5.0# echo "hola"
hola
bash-5.0# ls
bash: ls: command not found

Però veiem que un simple ls no el podem fer, ja que no disposem del binari executable per executar la comanda.

NOTA: Comandes que es poden fer amb bash sense instal.lar cap binari:

https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html

Script d'inici

Per personalitzar una mica més la nostra imatge i donar instruccions a l'usuari, podem afegir a l'arxiu /etc/bash.bashrc algunes instruccions per personalitzar la shell. En aquest cas ens és suficient executar uns echo amb el missatge de benvinguda, tot i que podríem afegir instruccions més complexes com posar variables d'entorn com PATH, etc.

/etc/bash.bashrc
echo "Benvingut al docker de l'Enric."
echo "Ara només disposeu de les comandes builtin de bash."
echo "Mes comandes ...coming soon..."

Comprova que ens apareix el missatge si reconstruim la imatge i la posem en marxa:

$ docker build -t enric/bashic:0.1 .
$ docker run -ti enric/bashic:0.1
Benvingut al docker de l'Enric.
Ara només disposeu de les comandes builtin de bash.
Mes comandes ...coming soon...
bash-5.1#

Publicar imatge a Docker Hub

  1. Afegeix a src els arxius que siguin necessaris per tal d'afegir mes comandes a la vostra imatge:
    • ls
    • cat
    • una altra comanda de la vostra elecció.
  2. Posa un missatge personalitzat a /etc/bash.bashrc amb el vostre nom i les comandes que heu afegit.
  3. Comprova que les comandes hi son fent un docker run adient i provant les comandes.
  4. Crea un compte a Docker Hub.
    • Poso l'exemple amb l'usuari enric però caldrà que ho feu amb el vostre usuari del Docker Hub.
  5. Logueja't en local per poder pujar la imatge al teu compte d'usuari:
    $ docker login
  6. Puja la amb un docker push:
     docker push enric/bashic:0.1
    • ULL perquè el nom d'usuari (en aquest cas és enric) ha de coincidir amb el teu usuari de Docker Hub. Per tant, abans caldrà fer el docker build també amb nom d'usuari que tingueu al Docker Hub.
  7. Penja al Moodle el nom complet de la imatge usuari/imatge:tag tal qual, sense res mes.


Comparant espai ocupat per les imatges

Descarregueu les imatges de ubuntu, centos, httpd i alpine, i compareu el què ocupen:

ubuntu          latest    ba6acccedd29   2 weeks ago      72.8MB
httpd           latest    be1298ceb0ad   3 weeks ago      138MB
centos          latest    5d0da3dc9764   6 weeks ago      231MB
alpine          latest    14119a10abf4   2 months ago     5.6MB

Com podem veure, la imatge d'Alpine Docker és realment molt mínima. Compareu-la amb el vostre contenidor que només té un ls i un cat. En canvi Alpine disposa fins-i-tot d'un gestor de paquets (apk).


Docker commit

Amb docker commit podem crear una imatge a partir d'un contenidor en marxa.

Millora d'un Wordpress amb docker commit

Tenim un client que ens demana que li migrem un Wordpress, i el volem posar en un contenidor a la nostra màquina segura. Fem un export i al voler fer l'import ens succeeix que la configuració per defecte no permet carregar arxius > 2MB . Volem fer una versió tunejada del Wordpress oficial amb aquest límit augmentat.

  1. Posa en marxa un Wordpress (no cal fer la DB, només el WP)
  2. Connecta't amb un
    $ docker exec -ti <elmeucontainer> bash
  3. Comprova el valor de les variables carregades, pots anar a /var/www/html i crear l'arxiu prova.php d'aquesta manera
    echo "<?php phpinfo();" > prova.php
  4. Visita la web, però canvia la URL a /prova.php i comprova els valors de post_max_size i max_upload_filsize.
  5. Ves a la carpeta /usr/local/etc/php/conf.d i afegeix un arxiu uploads.ini amb les dades següents:
    file_uploads = On
    memory_limit = 500M
    upload_max_filesize = 500M
    post_max_size = 500M
    max_execution_time = 600
  6. Surt del contenidor i guarda la teva imatge amb un
    $ docker commit <elmeudockerenmarxa> enric/wordpressplus
  7. Posa en marxa ara un docker-compose (mira la web de Docker Hub, ara sí, amb DB inclosa). Canvia la imatge de wordpress per la nova imatge que hem creat wordpressplus. Instal·la i comprova que quan volem fer una importació (a Eines → Importar), el límit ha pujat de 2MB a 500MB.
  8. També ho pots comprovar anant a la pàgina prova.php que hem fet en el pas 3 i mirant el valor de les variables.


Combinant Dockerfile i Docker-compose

Ara farem el mateix que hem fet a l'apartat anterior amb el docker commit però de manera més formal, o sigui, mitjançant un Dockerfile combinat amb un docker-compose.

Amb això crearem una imatge de Wordpress personalitzada amb les modificacions que ens interessa (pel cas, que ens permeti pujar arxius grans).

Millora d'un Wordpress amb Dockerfile

  1. Crea una carpeta de projecte wpplus i posa un docker-compose.yml oficial de Wordpress.
  2. Afegeix l'arxiu uploads.ini:
    uploads.ini
    file_uploads = On
    memory_limit = 500M
    upload_max_filesize = 500M
    post_max_size = 500M
    max_execution_time = 600
  3. Modifica el docker-compose.yml oficial de Wordpress substituint l'apartat image per build. Així generarem una imatge personalitzada «al vuelo» a partir del Dockerfile:
    docker-compose.yml
        #image: wordpress
        build: .
  4. Al Dockerfile només li cal:
    Dockerfile
    FROM wordpress
    COPY uploads.ini /usr/local/etc/php/conf.d/uploads.ini
  5. (No li cal CMD o ENTRYPOINT perquè ho hereda del pare wordpress).
  6. Posa-ho en marxa i, quan et funcioni, mostra-ho al professor amb les adequades explicacions i comprovacions.
  7. Carrega la imatge wordpressplus al teu usuari de Docker Hub.


Primera webapp amb Flask, Dockerfile i Docker-compose

Continua a l'article Docker Flask.