Repository navigation
Expand file tree
/
Copy pathdocker-compose.dev.yml
More file actions
175 lines (170 loc) · 8.27 KB
/
Copy pathdocker-compose.dev.yml
File metadata and controls
175 lines (170 loc) · 8.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# Infrastructure de dev locale — uniquement l'état persistant dont les apps ont
# besoin. Les apps elles-mêmes tournent sur l'hôte (`pnpm lfc-suite:dev:watch`)
# pour garder le HMR rapide ; ce fichier ne porte que l'état externe.
#
# Usage :
# pnpm dev:infra # démarre (docker compose up -d)
# pnpm dev:infra:down # arrête, garde les données
# pnpm dev:infra:nuke # arrête ET détruit les volumes (repart de zéro)
# pnpm dev:map:refresh # refabrique graphe OSRM + tuiles de la carte
#
# Miroir prod : Neon (Postgres managé, ADR-09). Même contrat de connexion via
# `DATABASE_URL` — seule l'URL change. En dev :
# DATABASE_URL="postgresql://lfc:lfc@localhost:5433/lfc_pim?schema=public"
#
# Même principe pour le stockage objet : la prod est Cloudflare R2, le dev est
# MinIO. Les deux parlent S3, et `S3StorageService` pose déjà
# `forcePathStyle: true` — c'est l'`endpoint` qui change, rien d'autre.
services:
postgres:
image: postgres:17-alpine
container_name: lfd-dev-postgres
restart: unless-stopped
environment:
POSTGRES_USER: lfc
POSTGRES_PASSWORD: lfc
POSTGRES_DB: lfc_pim
# Port hôte 5433 (et non 5432) : 5432 est déjà occupé sur cette machine.
# Même logique que l'API sur 3100 pour éviter le 3000 de SH3PHERD.
ports:
- "5433:5432"
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U lfc -d lfc_pim"]
interval: 5s
timeout: 3s
retries: 10
start_period: 5s
# Stockage objet compatible S3 — le R2 du poste de dev.
#
# Le KBIS et le mandat SEPA passaient par un `DocumentStore` qui, faute de
# `STORAGE_*`, refusait poliment : on développait le dépôt de pièces sans
# jamais déposer de pièce. MinIO rend le flux RÉEL en local — mêmes octets,
# même SDK, même chemin de code que la prod.
minio:
# quay.io : Docker Hub a fermé l'accès public à `minio/minio` le
# 2026-09-12. Le tag est le même, le registre change — sans quoi un poste
# neuf ne monte plus son stockage objet du tout.
image: quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z
container_name: lfd-dev-minio
restart: unless-stopped
command: server /data --console-address ":9001"
environment:
# Identifiants de DEV, en clair et assumés : ce conteneur n'écoute que sur
# la boucle locale et ne contient que des pièces de test.
MINIO_ROOT_USER: lfc
MINIO_ROOT_PASSWORD: lfclfclfc
# Ports hôte décalés comme Postgres (5433) : 9000 est un port trop courant
# pour le réserver. 9100 = API S3, 9101 = console web.
ports:
- "9100:9000"
- "9101:9001"
volumes:
- minio-data:/data
healthcheck:
test: ["CMD-SHELL", "mc ready local"]
interval: 5s
timeout: 3s
retries: 10
start_period: 5s
# Crée les buckets au démarrage, puis sort. Sans lui, la première pièce déposée
# tomberait sur un `NoSuchBucket` — en prod les buckets R2 sont créés une fois à
# la main, ici ils doivent renaître avec le volume (`dev:infra:nuke`).
#
# QUATRE buckets, et les différences ne sont pas cosmétiques :
#
# lfc-b2b-dev pièces PRIVÉES que le CLIENT NOUS DONNE (KBIS, mandat SEPA).
# Reste fermé : elles se lisent par une URL signée expirante,
# à travers l'API.
# lfc-customers-dev
# pièces privées que NOUS LUI RENDONS : bon de commande, et
# demain les factures déposées par le comptable. Fermé lui
# aussi, et c'est structurant — une adresse publique rendrait
# la facture d'un client lisible par qui devine une clé.
#
# ⚠️ Bucket SÉPARÉ du précédent, alors que les deux sont
# privés et concernent le même client. La configuration le
# dit : « chaque usage porte son bucket ET ses clés — un
# jeton n'ouvre que le sien ». Les ranger ensemble ferait
# qu'un jeton donné pour lire un KBIS lirait aussi les
# factures. Cf. `documentation/order/architecture-pieces-en-r2.md`.
# lfc-production-dev
# ce qui documente NOTRE travail : compte à produire du
# jour, feuille d'atelier. Fermé. Séparé de customers non
# par pudeur mais par DURÉE DE VIE — des semaines contre
# des années — et parce qu'une borne au fournil qui
# recevrait le jeton customers lirait aussi les factures.
#
# Écrit depuis `985d21bf` (2026-09-16) : les deux papiers
# du fournil y sont archivés au premier tirage.
# lfc-media-dev visuels PUBLICS du catalogue. Ouvert en LECTURE ANONYME,
# parce que c'est la moitié du stockage qui ne passe pas par
# nous : le navigateur va chercher l'image droit sur le
# bucket, avec l'URL enregistrée en base. Sans `anonymous set
# download`, le dépôt réussirait et chaque fiche afficherait
# une image cassée — un échec qui ne se voit qu'à l'affichage,
# longtemps après.
#
# Miroir prod : en R2 le bucket média est servi par `media.lafoliecoffee.info`,
# le bucket des pièces par personne.
minio-init:
# Même fermeture que l'image serveur, même report vers quay.io.
image: quay.io/minio/mc:RELEASE.2025-08-13T08-35-41Z
container_name: lfd-dev-minio-init
depends_on:
minio:
condition: service_healthy
entrypoint: >
sh -c "mc alias set lfd http://minio:9000 lfc lfclfclfc &&
mc mb --ignore-existing lfd/lfc-b2b-dev &&
mc mb --ignore-existing lfd/lfc-customers-dev &&
mc mb --ignore-existing lfd/lfc-production-dev &&
mc mb --ignore-existing lfd/lfc-media-dev &&
mc anonymous set download lfd/lfc-media-dev &&
echo 'buckets lfc-b2b-dev + lfc-customers-dev + lfc-production-dev (privés) et lfc-media-dev (lecture publique) prêts'"
# Calcul routier (plan de tournée) — le MÊME osrm-routed que `lfd-route-planner` en
# production, sur le graphe que `dev-toolbox/ensure-map-data.mjs` prépare
# une fois par poste dans ~/.cache/lfd-map/graph. L'API le lit par
# `ROUTE_PLANNER_URL=http://localhost:5055`.
#
# `OSRM_IMAGE` vient de `apps/lfd-route-planner/osrm-version.env`, passé en
# `--env-file` par les scripts `dev:infra*` : une seule copie du digest, un
# graphe préparé par une version ne se charge pas dans une autre. amd64 :
# c'est le seul manifeste épinglé ; sur Mac il tourne en émulation.
#
# Graphe absent (poste hors ligne au premier lancement) : le conteneur sort
# en le disant, et `restart: unless-stopped` le relance avec un recul
# croissant — il démarre de lui-même dès que le graphe apparaît. Choisi
# plutôt qu'un profil, qui obligerait `dev:infra` à décider du profil hors
# de compose et laisserait le service éteint jusqu'au prochain lancement.
# Aucun autre service n'en dépend : Postgres et MinIO montent quoi qu'il arrive.
osrm:
# Le repli n'est pas une image : c'est un nom qui dit quoi faire. Il
# permet aux commandes nues (`docker compose -f … exec postgres`, lancé
# par `dev-toolbox/migrate-dev-db.mjs`) de lire ce fichier sans l'env-file.
image: ${OSRM_IMAGE:-lfd-dev/osrm-image-absente-lancer-pnpm-dev-infra}
platform: linux/amd64
container_name: lfd-dev-osrm
restart: unless-stopped
entrypoint: ["/bin/sh", "-c"]
command:
- >
if [ ! -f /data/savoie.osrm.cell_metrics ]; then
echo "graphe absent de ~/.cache/lfd-map/graph : lancer pnpm dev:map:refresh"; exit 1; fi;
exec osrm-routed --algorithm mld --max-table-size 200 /data/savoie.osrm
ports:
- "5055:5000"
volumes:
- ${HOME}/.cache/lfd-map/graph:/data:ro
# Ni curl ni wget dans l'image : bash ouvre la socket, ça suffit à dire
# qu'osrm-routed a fini de charger le graphe et écoute.
healthcheck:
test: ["CMD", "bash", "-c", "exec 3<>/dev/tcp/127.0.0.1/5000"]
interval: 5s
timeout: 3s
retries: 10
start_period: 60s
volumes:
postgres-data:
minio-data: