diff --git a/exercice-1-port-web/COMMANDS.md b/exercice-1-port-web/COMMANDS.md index 3d1111c..11a8f68 100644 --- a/exercice-1-port-web/COMMANDS.md +++ b/exercice-1-port-web/COMMANDS.md @@ -1,6 +1,12 @@ + # Commandes ```bash -# Exemple de structure attendue docker run -d --name web-port -p 8080:80 nginx -``` +docker ps +docker port web-port +docker rm -f web-port +docker run -d --name web-port -p 127.0.0.1:8080:80 nginx +curl -sI http://localhost:8080 | head -n 5 +docker rm -f web-port || true +``` \ No newline at end of file diff --git a/exercice-1-port-web/README.md b/exercice-1-port-web/README.md index 6159b47..38ccff8 100644 --- a/exercice-1-port-web/README.md +++ b/exercice-1-port-web/README.md @@ -22,8 +22,13 @@ Les commandes doivent etre fournies dans un fichier separe `COMMANDS.md`. ## Questions de reflexion - Quelle est la difference entre le port hote et le port conteneur ? +Le port conteneur est service à l'intérieur,le port hôte est un port de la machine mappé vers le conteneur. + - Pourquoi `EXPOSE` ne suffit-il pas a rendre le service accessible ? +EXPOSE est documentaire, il faut `-p`/`--publish` pour créer le mapping hôte vers un conteneur. + - Dans quel cas limiter l'ecoute a `127.0.0.1` est-il utile ? +Quand on veut restreindre l'accès au host uniquement (développement, sécurité sur un hôte partagé). ## Criteres de validation diff --git a/exercice-2-dns-bridge/COMMANDS.md b/exercice-2-dns-bridge/COMMANDS.md index 8a05490..a17a7d4 100644 --- a/exercice-2-dns-bridge/COMMANDS.md +++ b/exercice-2-dns-bridge/COMMANDS.md @@ -1,6 +1,17 @@ # Commandes ```bash -# Exemple de structure attendue docker network create test_net +docker run -d --name serveur --network test_net nginx +docker run --rm --network test_net alpine sh -c "ping -c1 serveur && echo 'serveur reachable' || echo 'serveur unreachable'" +docker network inspect test_net +docker run --rm --network bridge alpine sh -c "ping -c1 serveur && echo 'bridge: reachable' || echo 'bridge: unreachable'" +docker run -d --name client --network bridge alpine sleep 300 +docker exec client sh -c "ping -c1 serveur && echo 'client before connect: reachable' || echo 'client before connect: unreachable'" +docker network connect test_net client +docker exec client sh -c "ping -c1 serveur && echo 'client after connect: reachable' || echo 'client after connect: unreachable'" +docker network disconnect test_net client || true +docker rm -f client serveur || true +docker network rm test_net || true + ``` diff --git a/exercice-2-dns-bridge/README.md b/exercice-2-dns-bridge/README.md index 8e67a4e..aa73d19 100644 --- a/exercice-2-dns-bridge/README.md +++ b/exercice-2-dns-bridge/README.md @@ -21,8 +21,15 @@ Les commandes doivent etre fournies dans un fichier separe `COMMANDS.md`. ## Questions de reflexion - Pourquoi l'utilisation d'un reseau personnalise est-elle recommandee pour des applications multi-conteneurs ? + +- Pourquoi l'utilisation d'un reseau personnalise est-elle recommandee pour des applications multi-conteneurs ? +Pour l'isolation + découverte de services par nom, pas de mappage de ports entre services. + - Quel avantage apporte le DNS interne Docker ? +Résolution automatique des conteneurs par nom. + - Que permet `docker network inspect` dans une phase de diagnostic ? +De montrer les conteneurs connectés, leurs IP internes et les détails du réseau. ## Criteres de validation diff --git a/exercice-3-web-db-network/COMMANDS.md b/exercice-3-web-db-network/COMMANDS.md index 9314a5f..4786434 100644 --- a/exercice-3-web-db-network/COMMANDS.md +++ b/exercice-3-web-db-network/COMMANDS.md @@ -1,7 +1,47 @@ # Commandes ```bash -# Exemple de structure attendue +# Variables (modifiable si besoin) +ROOT_PASS=rootpass +DB_NAME=demo_db +DB_USER=demo_user +DB_PASS=demo_pass + docker network create app_network docker volume create db_volume -``` +docker run -d --name mysql_db --network app_network \ + -e MYSQL_ROOT_PASSWORD=${ROOT_PASS} \ + -e MYSQL_DATABASE=${DB_NAME} \ + -e MYSQL_USER=${DB_USER} \ + -e MYSQL_PASSWORD=${DB_PASS} \ + -v db_volume:/var/lib/mysql \ + mysql:8 +echo "Waiting for mysql to be ready..." +until docker exec mysql_db mysqladmin ping -h localhost -uroot -p${ROOT_PASS} --silent; do sleep 1; done +echo "mysql ready" +docker build -t webapp-image ./webapp +docker run -d --name webapp --network app_network -p 8080:8080 \ + -e DB_HOST=mysql_db -e DB_USER=${DB_USER} -e DB_PASSWORD=${DB_PASS} -e DB_NAME=${DB_NAME} \ + webapp-image +docker network inspect app_network --format "{{json .Containers}}" +curl -sI http://localhost:8080 | head -n 5 +curl -s http://localhost:8080/init +curl -s http://localhost:8080/show +docker rm -f mysql_db +docker run -d --name mysql_db --network app_network \ + -e MYSQL_ROOT_PASSWORD=${ROOT_PASS} \ + -e MYSQL_DATABASE=${DB_NAME} \ + -e MYSQL_USER=${DB_USER} \ + -e MYSQL_PASSWORD=${DB_PASS} \ + -v db_volume:/var/lib/mysql \ + mysql:8 +echo "Waiting for mysql (recreated) to be ready..." +until docker exec mysql_db mysqladmin ping -h localhost -uroot -p${ROOT_PASS} --silent; do sleep 1; done +echo "mysql recreated and ready" +curl -s http://localhost:8080/show +docker rm -f webapp mysql_db || true +docker network rm app_network || true +docker volume rm db_volume || true +docker rmi webapp-image || true + +``` \ No newline at end of file diff --git a/exercice-3-web-db-network/README.md b/exercice-3-web-db-network/README.md index bf8e534..834148b 100644 --- a/exercice-3-web-db-network/README.md +++ b/exercice-3-web-db-network/README.md @@ -29,8 +29,11 @@ Les commandes doivent etre fournies dans un fichier separe `COMMANDS.md`. ## Questions de reflexion - Pourquoi la base de donnees n'a-t-elle pas besoin d'etre exposee vers l'hote dans cette architecture ? +Parce que la base de données n’a pas besoin d’être accessible directement depuis l’extérieur, seuls les services applicatifs doivent pouvoir s’y connecter comme web app. - En quoi le reseau personnalise simplifie-t-il la communication entre services ? +Le réseau personnalisé fournit DNS + isolation + simplicité, ce qui simplifie fortement l’architecture multi‑conteneurs. - Que se passerait-il si le volume n'etait pas reutilise apres recreation du conteneur MySQL ? +Perte de données ou encore réinitialisation automatique par exemple ## Criteres de validation diff --git a/exercice-3-web-db-network/webapp/Dockerfile b/exercice-3-web-db-network/webapp/Dockerfile new file mode 100644 index 0000000..899b6ed --- /dev/null +++ b/exercice-3-web-db-network/webapp/Dockerfile @@ -0,0 +1,6 @@ +FROM python:3.11-slim +WORKDIR /app +RUN pip install --no-cache-dir flask mysql-connector-python +COPY app.py /app/app.py +EXPOSE 8080 +CMD ["python", "app.py"] diff --git a/exercice-3-web-db-network/webapp/app.py b/exercice-3-web-db-network/webapp/app.py new file mode 100644 index 0000000..e3ae497 --- /dev/null +++ b/exercice-3-web-db-network/webapp/app.py @@ -0,0 +1,55 @@ +from flask import Flask +import os +import mysql.connector + +app = Flask(__name__) + +DB_HOST = os.environ.get('DB_HOST', 'mysql_db') +DB_USER = os.environ.get('DB_USER', 'demo_user') +DB_PASSWORD = os.environ.get('DB_PASSWORD', 'demo_pass') +DB_NAME = os.environ.get('DB_NAME', 'demo_db') + +def get_conn(): + return mysql.connector.connect( + host=DB_HOST, + user=DB_USER, + password=DB_PASSWORD, + database=DB_NAME, + autocommit=True + ) + +@app.route('/') +def index(): + try: + conn = get_conn() + cur = conn.cursor() + cur.execute('SELECT COUNT(*) FROM info') + cnt = cur.fetchone()[0] + cur.close() + conn.close() + return f'webapp OK — rows={cnt}\n' + except Exception as e: + return f'ERROR: {e}\n', 500 + +@app.route('/init') +def init_table(): + conn = get_conn() + cur = conn.cursor() + cur.execute('CREATE TABLE IF NOT EXISTS info (id INT AUTO_INCREMENT PRIMARY KEY, txt VARCHAR(100))') + cur.execute("INSERT INTO info (txt) VALUES ('hello')") + cur.close() + conn.close() + return 'initialized\n' + +@app.route('/show') +def show(): + conn = get_conn() + cur = conn.cursor() + cur.execute('SELECT id, txt FROM info') + rows = cur.fetchall() + cur.close() + conn.close() + return '\n'.join(f'{r[0]}:{r[1]}' for r in rows) + '\n' + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=8080)