====== 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:
* [[Docker]]: article amb les bases a bytes.cat
* [[Docker-compose]]: configurar serveis diversos en un arxiu i escalar-los.
* [[https://docs.docker.com/engine/reference/builder/|Referència Dockerfile]] oficial (Docker Builder).
Tenim diverses maneres de crear una imatge Docker:
- A partir d'un Dockerfile.
- Descarregant-la de Docker Hub (''docker pull'').
- Utilitzant [[https://docs.docker.com/engine/reference/commandline/commit/|docker commit]] per guardar els canvis que podem fer en un contenidor en marxa.
{{tag> #FpInfor #Ciber #CiberMp03 #Ceti #CetiMp03 DevOps docker dockerfile flask wordpress docker_commit docker_compose contenidors containers }}
\\
===== Primer Dockerfile from scratch =====
Una primera versió elemental del ''Dockerfile'' seria aquesta:
# 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.
- Localitzem l'arxiu ''bash'' del SO base que tinguem:$ which bash
/usr/bin/bash
- 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)
- 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.
[[https://man7.org/linux/man-pages/man7/vdso.7.html|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 .
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.
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 ====
- 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ó.
- Posa un missatge personalitzat a ''/etc/bash.bashrc'' amb el vostre nom i les comandes que heu afegit.
- Comprova que les comandes hi son fent un ''docker run'' adient i provant les comandes.
- Crea un compte a [[https://hub.docker.com|Docker Hub]].
* Poso l'exemple amb l'usuari ''enric'' però caldrà que ho feu amb el vostre usuari del Docker Hub.
- Logueja't en local per poder pujar la imatge al teu compte d'usuari:$ docker login
- Puja la amb un [[https://docs.docker.com/engine/reference/commandline/push/|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.
- 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 [[https://hub.docker.com/_/alpine|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 [[https://docs.docker.com/engine/reference/commandline/commit/|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.
- Posa en marxa un Wordpress (no cal fer la DB, només el WP)
- Connecta't amb un $ docker exec -ti bash
- Comprova el valor de les variables carregades, pots anar a ''/var/www/html'' i crear l'arxiu ''prova.php'' d'aquesta manera echo " prova.php
- Visita la web, però canvia la URL a /prova.php i comprova els valors de ''post_max_size'' i ''max_upload_filsize''.
- 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
- Surt del contenidor i guarda la teva imatge amb un$ docker commit enric/wordpressplus
- 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.
- 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 ====
- Crea una carpeta de projecte ''wpplus'' i posa un ''docker-compose.yml'' oficial de Wordpress.
- Afegeix l'arxiu ''uploads.ini'': file_uploads = On
memory_limit = 500M
upload_max_filesize = 500M
post_max_size = 500M
max_execution_time = 600
- 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''**: #image: wordpress
build: .
- Al ''Dockerfile'' només li cal:
FROM wordpress
COPY uploads.ini /usr/local/etc/php/conf.d/uploads.ini
- (No li cal CMD o ENTRYPOINT perquè ho hereda del pare //wordpress//).
- Posa-ho en marxa i, quan et funcioni, mostra-ho al professor amb les adequades explicacions i comprovacions.
- Carrega la imatge ''wordpressplus'' al teu usuari de [[https://hub.docker.com/|Docker Hub]].
* Etiqueta la nova imatge amb [[https://docs.docker.com/engine/reference/commandline/tag/|docker tag]]
* Carrega la imatge [[https://docs.docker.com/engine/reference/commandline/push/|docker push]].
\\
===== Primera webapp amb Flask, Dockerfile i Docker-compose =====
Continua a l'article [[Docker Flask]].