Exercisis amb Docker i Docker Compose
-
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:app
On
app
és el nom del fitxer on es troba l'aplicació.A més, sabem que l'aplicació necessita les següents llibreries:
falcon
igunicorn
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.
-
Analitza el següent projecte Dockeritzat Laboratoris i desplega'l en el teu entorn de desenvolupament.
-
Crea un fitxer
docker-compose.yml
que permeti desplegar 3 aplicacions web diferents, i un servidor nginx que faci de balancejador de càrrega entre elles. Per fer-ho, farem servir aplicacions web molt senzilles en Python amb Flask. A continuació, es mostren els fitxers de les aplicacions:from flask import Flask app = Flask(__name__) @app.route('/') def home(): return "Hello from App 1!" if __name__ == "__main__": app.run(host="0.0.0.0", port=5000)
Nota: Per instal·lar docker-compose a Amazon linux 2023, es pot fer servir el següent script:
sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose
-
A la feina us han demanat una arquitectura de desplegament escalable i portable per desenvolupar una app web que fa consultes a una base de dades. La estructura del projecte és la següent:
web-app/ ├── app/ │ ├── main.py │ ├── models.py │ ├── database.py │ ├── schemas.py │ ├── requirements.txt ├── db/ │ ├── init.sql
El requísits són els següents:
- La base de dades ha de ser MySQL a la versió 5.7.
- La aplicació web ha de ser en Python 3.9 utiltizant les següents llibreries:
- fastapi==0.95.1
- uvicorn==0.22.0
- SQLAlchemy==2.0.21
- pymysql==1.0.3
- cryptography==35.0.0
On
main.py
és el següent:from fastapi import FastAPI, HTTPException, Depends from sqlalchemy.orm import Session import models, schemas, database # Crear l'aplicació FastAPI app = FastAPI() # Crear les taules de la base de dades models.Base.metadata.create_all(bind=database.engine) # Ruta inicial @app.get("/") def read_root(): return {"message": "Hello World"} # Ruta per obtenir un element @app.get("/items/{item_id}", response_model=schemas.Item) def read_item(item_id: int, db: Session = Depends(database.get_db)): item = db.query(models.Item).filter(models.Item.id == item_id).first() if item is None: raise HTTPException(status_code=404, detail="Item not found") return item # Ruta per crear un nou element @app.post("/items/", response_model=schemas.Item) def create_item(item: schemas.ItemCreate, db: Session = Depends(database.get_db)): db_item = models.Item(**item.dict()) db.add(db_item) db.commit() db.refresh(db_item) return db_item
i models.py:
from sqlalchemy import Column, Integer, String, Float from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Item(Base): __tablename__ = "items" id = Column(Integer, primary_key=True, index=True) name = Column(String(50), index=True) description = Column(String(255)) price = Column(Float) tax = Column(Float, nullable=True)
i schemas.py:
from pydantic import BaseModel class ItemBase(BaseModel): name: str description: str price: float tax: float = None class ItemCreate(ItemBase): pass class Item(ItemBase): id: int class Config: orm_mode = True
i database.py:
from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker SQLALCHEMY_DATABASE_URL = "mysql+pymysql://root:password@db:3306/testdb" engine = create_engine(SQLALCHEMY_DATABASE_URL) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) def get_db(): db = SessionLocal() try: yield db finally: db.close()
i init.sql:
CREATE DATABASE IF NOT EXISTS testdb; USE testdb; CREATE TABLE IF NOT EXISTS items ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, description TEXT, price FLOAT NOT NULL, tax FLOAT );