Prépare la dockerization : Dockerfile, docker-compose, .dockerignore
Image Python 3.14-slim (même version qu'en dev local), utilisateur non-root, healthcheck sans dépendance externe, un seul worker Uvicorn (SQLite gère mal les écritures concurrentes multi-process). data/ monté en volume dans docker-compose.yml pour garder la base SQLite visible et sauvegardable directement dans le dossier du projet, comme en dev local. Non testé avec un vrai build : Docker indisponible dans cet environnement de dev, à vérifier avant un premier déploiement.
This commit is contained in:
parent
11da706573
commit
5792b453e7
12
.dockerignore
Normal file
12
.dockerignore
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.venv
|
||||||
|
__pycache__
|
||||||
|
*.pyc
|
||||||
|
.pytest_cache
|
||||||
|
.ruff_cache
|
||||||
|
.claude
|
||||||
|
data/*.db
|
||||||
|
.env
|
||||||
|
tests
|
||||||
|
*.md
|
||||||
|
|
@ -51,6 +51,12 @@ ruff check . # linter
|
||||||
Les tests utilisent une base SQLite **en mémoire** (voir `tests/conftest.py`),
|
Les tests utilisent une base SQLite **en mémoire** (voir `tests/conftest.py`),
|
||||||
jamais le fichier `data/stock.db` du développement.
|
jamais le fichier `data/stock.db` du développement.
|
||||||
|
|
||||||
|
`docker compose up --build` construit et lance l'app (Dockerfile, Python
|
||||||
|
3.14-slim, `data/` monté en volume depuis l'hôte, 1 seul worker Uvicorn
|
||||||
|
volontairement — SQLite gère mal les écritures concurrentes multi-process).
|
||||||
|
Pas testé avec un vrai build dans cette session (Docker indisponible dans
|
||||||
|
l'environnement de dev) — à vérifier avant un premier déploiement.
|
||||||
|
|
||||||
## Convention : commentaires détaillés
|
## Convention : commentaires détaillés
|
||||||
|
|
||||||
Contrairement à la préférence par défaut (commentaires minimaux), ce projet
|
Contrairement à la préférence par défaut (commentaires minimaux), ce projet
|
||||||
|
|
|
||||||
45
Dockerfile
Normal file
45
Dockerfile
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Image officielle Python, même version majeure qu'en dev local (3.14).
|
||||||
|
# "slim" = Debian minimal : largement suffisant ici, aucune dépendance du
|
||||||
|
# projet ne nécessite de compilation (pas besoin d'une image complète).
|
||||||
|
FROM python:3.14-slim
|
||||||
|
|
||||||
|
# Pas de bytecode .pyc écrit sur disque (inutile dans un conteneur
|
||||||
|
# éphémère) et sortie non bufferisée (les logs uvicorn apparaissent tout
|
||||||
|
# de suite dans `docker logs`, pas seulement à la fermeture du process).
|
||||||
|
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||||
|
PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copié avant le reste du code : cette couche ne se reconstruit que si
|
||||||
|
# requirements.txt change, ce qui accélère largement les rebuilds pendant
|
||||||
|
# le développement (le code applicatif change bien plus souvent).
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY app/ app/
|
||||||
|
COPY scripts/ scripts/
|
||||||
|
|
||||||
|
# data/ (base SQLite) est destiné à être monté en volume (voir
|
||||||
|
# docker-compose.yml) pour que les données survivent aux
|
||||||
|
# rebuilds/redémarrages du conteneur.
|
||||||
|
RUN mkdir -p data
|
||||||
|
|
||||||
|
# Utilisateur non-root par sécurité. Si le volume data/ monté depuis
|
||||||
|
# l'hôte pose un problème de permissions (l'utilisateur de l'hôte n'a pas
|
||||||
|
# forcément l'UID 1000), ajustez les droits du dossier hôte avec
|
||||||
|
# `chown -R 1000:1000 data/`, ou retirez ces deux lignes pour tourner en root.
|
||||||
|
RUN useradd --create-home --uid 1000 appuser && chown -R appuser:appuser /app
|
||||||
|
USER appuser
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
# Vérifie que le serveur répond, sans dépendre d'un outil externe
|
||||||
|
# (curl/wget, absents de l'image "slim").
|
||||||
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s \
|
||||||
|
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/materiels')" || exit 1
|
||||||
|
|
||||||
|
# Un seul worker Uvicorn : SQLite gère mal les écritures concurrentes
|
||||||
|
# depuis plusieurs process. Largement suffisant pour l'usage interne visé.
|
||||||
|
# Pas de --reload : réservé au dev local hors conteneur (voir README).
|
||||||
|
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
22
README.md
22
README.md
|
|
@ -31,6 +31,26 @@ uvicorn app.main:app --reload
|
||||||
L'app est accessible sur http://127.0.0.1:8000. La base SQLite est créée
|
L'app est accessible sur http://127.0.0.1:8000. La base SQLite est créée
|
||||||
automatiquement au premier démarrage dans `data/stock.db`.
|
automatiquement au premier démarrage dans `data/stock.db`.
|
||||||
|
|
||||||
|
## Lancer avec Docker
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env # requis, voir Configuration des emails ci-dessous
|
||||||
|
docker compose up --build
|
||||||
|
```
|
||||||
|
|
||||||
|
L'app est accessible sur http://localhost:8000. `data/` est monté depuis
|
||||||
|
l'hôte : la base SQLite (`data/stock.db`) reste au même endroit qu'en dev
|
||||||
|
local sans Docker, visible et sauvegardable directement dans ce dossier.
|
||||||
|
|
||||||
|
Un seul worker Uvicorn dans le conteneur (voir commentaire dans le
|
||||||
|
`Dockerfile`) : SQLite gère mal les écritures concurrentes depuis
|
||||||
|
plusieurs process, et un seul worker est largement suffisant pour l'usage
|
||||||
|
interne visé.
|
||||||
|
|
||||||
|
Pour du développement actif, la boucle venv + `--reload` ci-dessus reste
|
||||||
|
plus rapide (pas de rebuild d'image à chaque changement) ; Docker sert
|
||||||
|
surtout à tester ou reproduire l'environnement de déploiement.
|
||||||
|
|
||||||
## Lancer les tests
|
## Lancer les tests
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -107,4 +127,6 @@ scripts/
|
||||||
envoyer_resume_stock.py déclenche manuellement l'email récapitulatif
|
envoyer_resume_stock.py déclenche manuellement l'email récapitulatif
|
||||||
tests/ tests pytest (client de test FastAPI + base SQLite en mémoire)
|
tests/ tests pytest (client de test FastAPI + base SQLite en mémoire)
|
||||||
data/ base SQLite locale (ignorée par git)
|
data/ base SQLite locale (ignorée par git)
|
||||||
|
Dockerfile image de l'app (Python 3.14-slim, utilisateur non-root, 1 worker Uvicorn)
|
||||||
|
docker-compose.yml lancement local avec data/ monté en volume
|
||||||
```
|
```
|
||||||
|
|
|
||||||
20
docker-compose.yml
Normal file
20
docker-compose.yml
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Lancement : docker compose up --build
|
||||||
|
# L'app est accessible sur http://localhost:8000
|
||||||
|
#
|
||||||
|
# Prérequis : cp .env.example .env (et le remplir si un vrai relais SMTP
|
||||||
|
# est disponible ; sinon les emails restent simulés dans les logs, comme
|
||||||
|
# en dev local — voir `docker compose logs -f`).
|
||||||
|
#
|
||||||
|
# data/ est monté depuis l'hôte : la base SQLite (data/stock.db) reste
|
||||||
|
# visible et sauvegardable directement dans ce dossier, exactement comme
|
||||||
|
# en dev local sans Docker.
|
||||||
|
services:
|
||||||
|
stock:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "8000:8000"
|
||||||
|
volumes:
|
||||||
|
- ./data:/app/data
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
restart: unless-stopped
|
||||||
Loading…
Reference in a new issue