Dockerfile i Imatges Pròpies
Creant les vostres pròpies imatges amb Dockerfile
Fins ara hem utilitzat imatges creades per altres persones, però el veritable poder de Docker apareix quan creeu les vostres pròpies imatges personalitzades per les vostres aplicacions. Això es fa amb un fitxer especial anomenat Dockerfile.
Què és un Dockerfile i com funciona
Un Dockerfile és un fitxer de text que conté una sèrie d'instruccions que defineixen com construir una imatge Docker. És com una recepta: descriu pas a pas què cal fer per crear la imatge. Docker llegeix aquest fitxer i executa cada instrucció en ordre, creant una nova capa a la imatge per cada instrucció.
Anem a crear un exemple pràctic per entendre com funciona. Imagineu que teniu una aplicació web senzilla en Python que utilitza Flask. Creeu un directori nou per aquest projecte:
Primer, crearem una aplicació Python molt senzilla. Creeu un fitxer anomenat app.py amb aquest contingut:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return '<h1>Hola des del meu contenidor Docker!</h1>'
@app.route('/salut/<nom>')
def salut(nom):
return f'<h1>Hola, {nom}!</h1>'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
Aquesta és una aplicació Flask molt bàsica que té dues rutes: una pàgina principal que mostra un salut, i una ruta dinàmica que saluda per nom. El paràmetre host='0.0.0.0' és important perquè fa que Flask escolti en totes les interfícies de xarxa, no només en localhost, que és necessari per poder accedir des de fora del contenidor.
També necessitarem especificar les dependències. Creeu un fitxer anomenat requirements.txt:
Ara ve la part interessant: crearem el Dockerfile. Creeu un fitxer anomenat Dockerfile (sense extensió) amb aquest contingut:
# Especifica la imatge base
FROM python:3.12-slim
# Estableix el directori de treball dins del contenidor
WORKDIR /app
# Copia el fitxer de requirements
COPY requirements.txt .
# Instal·la les dependències
RUN pip install --no-cache-dir -r requirements.txt
# Copia tot el codi de l'aplicació
COPY . .
# Exposa el port que utilitzarà l'aplicació
EXPOSE 5000
# Defineix la comanda que s'executarà quan el contenidor arrenqui
CMD ["python", "app.py"]
Anem a analitzar cada instrucció en detall perquè entengueu què fa cadascuna:
La instrucció FROM és sempre la primera, i especifica la imatge base sobre la qual construirem la nostra. En aquest cas, estem utilitzant python:3.12-slim, que és una imatge oficial de Python versió 3.12 en una variant "slim" (lleugera). Aquesta imatge ja té Python instal·lat i configurat, així que no hem de fer-ho nosaltres.
WORKDIR /app crea un directori anomenat /app dins del contenidor i el fa el directori de treball actual. Totes les instruccions posteriors s'executaran en aquest directori. És com fer un mkdir /app seguit d'un cd /app.
COPY requirements.txt . copia el fitxer requirements.txt des del vostre ordinador (el directori on teniu el Dockerfile) cap al directori de treball del contenidor (que és /app). El punt . al final significa "el directori actual", és a dir, /app.
RUN pip install --no-cache-dir -r requirements.txt executa una comanda dins del contenidor durant la construcció de la imatge. En aquest cas, instal·la les dependències Python especificades a requirements.txt. L'opció --no-cache-dir evita que pip guardi fitxers cache, fent que la imatge sigui més petita.
És interessant notar que primer copiem només requirements.txt i l'instal·lem abans de copiar la resta del codi. Això és una optimització: si només canvieu el codi de l'aplicació però no les dependències, Docker pot reutilitzar la capa on s'instal·len les dependències de construccions anteriors, fent que reconstruir la imatge sigui molt més ràpid.
COPY . . copia tots els fitxers del directori actual del vostre ordinador al directori de treball del contenidor. Això inclou app.py i qualsevol altre fitxer que tingueu.
EXPOSE 5000 documenta que el contenidor escoltarà en el port 5000. Atenció: aquesta instrucció NO publica el port automàticament, només el documenta. Encara haureu d'utilitzar -p quan executeu el contenidor si voleu accedir-hi des de fora.
CMD ["python", "app.py"] especifica la comanda que s'executarà quan arrenqueu un contenidor basat en aquesta imatge. En aquest cas, executarà Python amb el fitxer app.py.
Construint la imatge
Ara que teniu el Dockerfile preparat, anem a construir la imatge. Des del directori on teniu tots els fitxers, executeu:
El paràmetre -t la-meva-app:1.0 assigna un nom i una etiqueta a la imatge. El punt . al final indica a Docker que el context de construcció és el directori actual, és a dir, que els fitxers que pot copiar són els del directori actual.
Veureu com Docker executa cada instrucció del Dockerfile, mostrant el progrés. Cada pas crea una nova capa a la imatge. Al final, hauríeu de veure un missatge dient que la construcció ha estat exitosa.
Podeu veure totes les imatges que teniu al vostre sistema amb:
Hauríeu de veure la vostra imatge "la-meva-app" amb l'etiqueta "1.0" a la llista.
Executant la vostra aplicació containeritzada
Ara que teniu la imatge construïda, podeu crear contenidors a partir d'ella:
Si obriu el navegador i aneu a http://localhost:5000, hauríeu de veure el missatge "Hola des del meu contenidor Docker!". També podeu provar http://localhost:5000/salut/Maria i veureu un salut personalitzat.
El més impressionant d'això és que no heu hagut d'instal·lar Python al vostre sistema, ni Flask, ni cap dependència. Tot està encapsulat dins del contenidor. Si copieu aquesta imatge a un altre ordinador, funcionarà exactament igual. Això és el poder de Docker.