Exerccisis amb Docker
Exercici 1: Docker bàsic amb un script Python
Donada la següent aplicació en Python:
import falcon
class Item:
def __init__(self, id, name):
self.id = id
self.name = name
items = [
Item(1, "Item 1"),
Item(2, "Item 2"),
Item(3, "Item 3"),
]
class ItemListResource:
def on_get(self, req, resp):
resp.media = [{"id": item.id, "name": item.name} for item in items]
class ItemResource:
def on_get(self, req, resp, item_id):
item = next((i for i in items if i.id == int(item_id)), None)
if item:
resp.media = {"id": item.id, "name": item.name}
else:
resp.status = falcon.HTTP_404
resp.media = {"error": "Item not found"}
app = falcon.App()
app.add_route('/items', ItemListResource())
app.add_route('/items/{item_id}', ItemResource())Per executar l’aplicació, es pot fer servir el següent script:
gunicorn -b 0.0.0.0:8000 app:appOn app és el nom del fitxer on es troba l’aplicació.
A més, sabem que l’aplicació necessita les següents llibreries: falcon i gunicorn en les versions 3.0.0 i 20.1.0 respectivament.
La teva tasca és crear un Dockerfile per a aquesta aplicació i un fitxer Makefile que permeti construir la imatge i executar-la.
Exercici 2: Compartint fitxers entre host i contenidor
Tens el següent script Python:
with open("data.txt") as f:
print(f.read())Crea una imatge Docker mínima que executi aquest script.
No copiïs data.txt dins de la imatge.
Executa el contenidor de manera que l’arxiu
data.txtdel host es vegi dins del contenidor.El contingut de
data.txtés: “Hola, Docker!” i s’ha de mostrar a la terminal quan s’executa el contenidor.- Quina és la comanda per construir la imatge Docker? I per executar el contenidor amb l’arxiu
data.txtdel host muntat dins del contenidor? - Cal recontruir la imatge Docker si es modifica el contingut de
data.txtal host? Justifica la teva resposta. - Quina diferència té incloure l’arxiu
data.txtdins de la imatge Docker o en la execució del contenidor? Quin impacte té això en el temps de construcció i la mida de la imatge Docker?
- Quina és la comanda per construir la imatge Docker? I per executar el contenidor amb l’arxiu
Exercici 3: Optimització de Dockerfile
A partir d’una imatge de Dockerfile, heu d’analitzar capes i mida d’una imatge:
FROM python:3.11-slim
RUN apt-get update
RUN apt-get install -y curl
RUN pip install flask
COPY app.py .
CMD ["python", "app.py"]- Construeix la imatge Docker i identifica les capes creades per cada instrucció del Dockerfile.
- Proposa una versió millorada del Dockerfile que redueixi la mida de la imatge final combinant capes i eliminant redundàncies.
- Calcula la diferència de mida entre la imatge original i la imatge millorada.
Exercici 4: Optimització d’imatges Docker
Donada la següent api amb python i flask:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello world!"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)- Crea un Dockerfile per a aquesta aplicació utilitzant una imatge base oficial de Python (per exemple,
python:3.11-slim). - Crea un Dockerfile ara amb la imatge base
alpine(per exemple,python:3.11-alpine). - Compara les mides i els temps d’arrrencada de les dues imatges Docker creades.
Exercici 5: Multi-stage builds amb Docker
Tens una app de React en un directori frontend/.
- Fes una imatge sense multi-stage build, instal·lant Node.js i servint l’app amb npm run build.
- Fes una imatge amb multi-stage build, on en la primera etapa es construeix l’app i en la segona etapa es serveix amb un servidor web lleuger (com nginx).
- Compara les mides de les dues imatges i explica els avantatges de l’enfoc multi-stage build.
Exercici 6: Servidor web
Crea un directori amb un fitxer index.html que contingui “Hola, Docker!”. Escriu un Dockerfile que utilitzi ula imatge nginx:alpine per servir aquest fitxer. Construeix la imatge i executa un contenidor que exposi el port 8080 del host al 80 del contenidor. Comprova que pots accedir al fitxer index.html des del navegador web.
Exercici 7: Legacy link
Utilitza una imatge de redis per arrancar un contenidor (redis:latest). Crea una app amb python que connecti amb el sevidor Redis utiltizant el hostname amsa-redisi incrementi un comptador cada vegada que s’accedeix a la ruta /. Executa el contenidor amb default bridge network. Com es que Python falla al resoldre el hostname amsa-redis? Quina és la solució perque funcioni correctament?
from flask import Flask
import redis
app = Flask(__name__)
r = redis.Redis(host="amsa-redis", port=6379)
r.ping()
@app.route("/")
def index():
count = r.incr("counter")
return f"Count = {count}"Exercici 8: CMD vs ENTRYPOINT
Assumeix el següent script de python hello.py:
# hello.py
import sys
if __name__ == "__main__":
print("Arguments rebuts:", " ".join(sys.argv[1:]))Crea dues imatges de docker una amb CMD i l’altra amb ENTRYPOINT per executar aquest script. Prova a passar arguments addicionals quan executes els contenidors i observa la diferència en el comportament entre les dues imatges. Explica quan és més adequat utilitzar CMD i quan ENTRYPOINT.
Exercici 9: Multi-Stage amb Go
Tens el següent codi en Go que crea un servidor web senzill:
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
// Define the handler function
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello! This app is running inside a Docker container.")
})
// Determine port for HTTP service.
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
// Start the server
fmt.Printf("Server starting on port %s...\n", port)
if err := http.ListenAndServe(":"+port, nil); err != nil {
panic(err)
}
}Crea dos Dockerfiles per aquesta aplicació: un que utilitzi una sola etapa i un altre que utilitzi multi-stage builds per optimitzar la mida de la imatge final. Compara les mides de les dues imatges i explica els avantatges del multi-stage build en aquest cas.
Per a ajudar-te, aquí tens una estructura bàsica per als dos Dockerfiles:
- single-stage.Dockerfile
- multi-stage.Dockerfile
Per compilar pots utilitzar les següents comandes:
docker build -f single-stage.Dockerfile -t amsa-single-stage .
docker build -f multi-stage.Dockerfile -t amsa-multi-stage .Per compilar l’app amb go, pots utilitzar:
go build -o my-app main.go