Skip to content

Commit 62c431a

Browse files
committed
feat: Phase 4 Lab 06 -- Production Deployment (restart policy, resource limits, workers)
1 parent b8720d3 commit 62c431a

3 files changed

Lines changed: 461 additions & 7 deletions

File tree

.github/workflows/ci.yml

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,4 +266,60 @@ run: bash tests/labs/test-lab-17-01.sh
266266

267267
- name: Cleanup
268268
if: always()
269-
run: docker compose -f docker/docker-compose.integration.yml down -v
269+
run: docker compose -f docker/docker-compose.integration.yml down -v
270+
271+
lab-06-smoke:
272+
name: Lab 17-06 -- GLPI Production Deployment (restart policy, resource limits, cron container)
273+
runs-on: ubuntu-latest
274+
needs: validate
275+
continue-on-error: true
276+
steps:
277+
- uses: actions/checkout@v4
278+
279+
- name: Install tools
280+
run: sudo apt-get install -y curl default-mysql-client netcat-openbsd ldap-utils
281+
282+
- name: Validate production compose
283+
run: docker compose -f docker/docker-compose.production.yml config -q && echo "Production compose valid"
284+
285+
- name: Start production stack
286+
run: docker compose -f docker/docker-compose.production.yml up -d
287+
288+
- name: Wait for MariaDB
289+
run: |
290+
for i in $(seq 1 18); do
291+
docker exec glpi-p06-db mysqladmin ping -uroot -pRootProd06! --silent 2>/dev/null && echo "DB ready" && break
292+
echo "Waiting for DB... ($i/18)"; sleep 5
293+
done
294+
295+
- name: Wait for Keycloak
296+
run: |
297+
for i in $(seq 1 24); do
298+
curl -sf http://localhost:8562/realms/master | grep -q realm && echo "KC ready" && break
299+
echo "Waiting for KC... ($i/24)"; sleep 5
300+
done
301+
302+
- name: Wait for Mailhog
303+
run: |
304+
for i in $(seq 1 12); do
305+
curl -sf http://localhost:8752/api/v2/messages > /dev/null && echo "MH ready" && break
306+
echo "Waiting for MH... ($i/12)"; sleep 5
307+
done
308+
309+
- name: Wait for GLPI
310+
run: |
311+
for i in $(seq 1 24); do
312+
curl -sf http://localhost:8462/ | grep -qi html && echo "GLPI ready" && break
313+
echo "Waiting for GLPI... ($i/24)"; sleep 5
314+
done
315+
316+
- name: Run Lab 17-06 test script
317+
run: bash tests/labs/test-lab-17-06.sh --no-cleanup
318+
319+
- name: Collect logs on failure
320+
if: failure()
321+
run: docker compose -f docker/docker-compose.production.yml logs
322+
323+
- name: Cleanup
324+
if: always()
325+
run: docker compose -f docker/docker-compose.production.yml down -v

docker/docker-compose.production.yml

Lines changed: 239 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,245 @@
1-
# Lab 06 — Production: glpi HA-ready with monitoring and external volumes
2-
---
1+
# =============================================================================
2+
# IT-Stack: GLPI — Lab 06: Production Deployment
3+
# Module 17 · Phase 4 · Lab 06
4+
# =============================================================================
5+
# Services: MariaDB · OpenLDAP · Keycloak · Mailhog · GLPI App · GLPI Cron
6+
# Ports: App:8462 KC:8562 LDAP:3873 MH:8752
7+
# Credentials:
8+
# DB root: RootProd06! app: glpi / GlpiProd06!
9+
# Keycloak: admin / Admin06!
10+
# LDAP: cn=admin,dc=lab,dc=local / LdapProd06!
11+
# Production features vs Lab 05:
12+
# + restart: unless-stopped on ALL services
13+
# + Resource limits AND reservations on every service
14+
# + Dedicated cron container (GLPI automatic actions + notifications)
15+
# + IT_STACK_ENV: production IT_STACK_LAB: "06" labels
16+
# + Healthcheck start_period on all services
17+
# =============================================================================
18+
19+
name: it-stack-glpi-lab06
20+
321
services:
4-
glpi:
22+
23+
# ── MariaDB ────────────────────────────────────────────────────────────────
24+
glpi-p06-db:
25+
image: mariadb:10.11
26+
container_name: glpi-p06-db
27+
restart: unless-stopped
28+
environment:
29+
MYSQL_ROOT_PASSWORD: RootProd06!
30+
MYSQL_DATABASE: glpi
31+
MYSQL_USER: glpi
32+
MYSQL_PASSWORD: GlpiProd06!
33+
volumes:
34+
- glpi-p06-db-data:/var/lib/mysql
35+
healthcheck:
36+
test: ["CMD", "mysqladmin", "ping", "-uroot", "-pRootProd06!", "--silent"]
37+
interval: 10s
38+
timeout: 5s
39+
retries: 5
40+
start_period: 30s
41+
networks:
42+
- glpi-p06-net
43+
deploy:
44+
resources:
45+
limits:
46+
cpus: "1.0"
47+
memory: 512M
48+
reservations:
49+
cpus: "0.25"
50+
memory: 128M
51+
52+
# ── OpenLDAP ───────────────────────────────────────────────────────────────
53+
glpi-p06-ldap:
54+
image: osixia/openldap:1.5.0
55+
container_name: glpi-p06-ldap
56+
restart: unless-stopped
57+
environment:
58+
LDAP_ORGANISATION: "IT-Stack Production"
59+
LDAP_DOMAIN: lab.local
60+
LDAP_ADMIN_PASSWORD: LdapProd06!
61+
LDAP_CONFIG_PASSWORD: ConfigProd06!
62+
LDAP_BASE_DN: dc=lab,dc=local
63+
LDAP_READONLY_USER: "true"
64+
LDAP_READONLY_USER_USERNAME: readonly
65+
LDAP_READONLY_USER_PASSWORD: ReadOnlyProd06!
66+
ports:
67+
- "3873:389"
68+
volumes:
69+
- glpi-p06-ldap-data:/var/lib/ldap
70+
- glpi-p06-ldap-config:/etc/ldap/slapd.d
71+
healthcheck:
72+
test: ["CMD-SHELL", "ldapsearch -x -H ldap://localhost -b dc=lab,dc=local -D cn=admin,dc=lab,dc=local -w LdapProd06! cn=admin > /dev/null 2>&1 && echo ok"]
73+
interval: 15s
74+
timeout: 5s
75+
retries: 5
76+
start_period: 20s
77+
networks:
78+
- glpi-p06-net
79+
deploy:
80+
resources:
81+
limits:
82+
cpus: "0.5"
83+
memory: 256M
84+
reservations:
85+
cpus: "0.1"
86+
memory: 64M
87+
88+
# ── Keycloak ───────────────────────────────────────────────────────────────
89+
glpi-p06-kc:
90+
image: quay.io/keycloak/keycloak:24.0.3
91+
container_name: glpi-p06-kc
92+
restart: unless-stopped
93+
command: start-dev
94+
environment:
95+
KEYCLOAK_ADMIN: admin
96+
KEYCLOAK_ADMIN_PASSWORD: Admin06!
97+
KC_HEALTH_ENABLED: "true"
98+
KC_DB: dev-file
99+
KC_HOSTNAME_STRICT: "false"
100+
KC_HOSTNAME_STRICT_HTTPS: "false"
101+
KC_HTTP_ENABLED: "true"
102+
ports:
103+
- "8562:8080"
104+
healthcheck:
105+
test: ["CMD-SHELL", "curl -sf http://localhost:8080/realms/master || exit 1"]
106+
interval: 15s
107+
timeout: 5s
108+
retries: 10
109+
start_period: 60s
110+
networks:
111+
- glpi-p06-net
112+
deploy:
113+
resources:
114+
limits:
115+
cpus: "1.0"
116+
memory: 768M
117+
reservations:
118+
cpus: "0.25"
119+
memory: 256M
120+
121+
# ── Mailhog ────────────────────────────────────────────────────────────────
122+
glpi-p06-mail:
123+
image: mailhog/mailhog:latest
124+
container_name: glpi-p06-mail
125+
restart: unless-stopped
126+
ports:
127+
- "8752:8025"
128+
healthcheck:
129+
test: ["CMD-SHELL", "wget -qO- http://localhost:8025/api/v2/messages || exit 1"]
130+
interval: 10s
131+
timeout: 5s
132+
retries: 3
133+
networks:
134+
- glpi-p06-net
135+
deploy:
136+
resources:
137+
limits:
138+
cpus: "0.25"
139+
memory: 128M
140+
reservations:
141+
cpus: "0.05"
142+
memory: 32M
143+
144+
# ── GLPI App ─────────────────────────────────────────────────────────────────
145+
glpi-p06-app:
5146
image: diouxx/glpi:latest
6-
container_name: it-stack-glpi
7-
restart: always
147+
container_name: glpi-p06-app
148+
restart: unless-stopped
149+
depends_on:
150+
glpi-p06-db:
151+
condition: service_healthy
152+
glpi-p06-ldap:
153+
condition: service_healthy
154+
glpi-p06-kc:
155+
condition: service_healthy
8156
ports:
9-
- "80:$firstPort"
157+
- "8462:80"
158+
environment:
159+
IT_STACK_ENV: production
160+
IT_STACK_MODULE: glpi
161+
IT_STACK_LAB: "06"
162+
MARIADB_HOST: glpi-p06-db
163+
MARIADB_PORT: "3306"
164+
MARIADB_DATABASE: glpi
165+
MARIADB_USER: glpi
166+
MARIADB_PASSWORD: GlpiProd06!
167+
GLPI_LDAP_HOST: glpi-p06-ldap
168+
GLPI_LDAP_PORT: "389"
169+
GLPI_LDAP_BASE_DN: dc=lab,dc=local
170+
GLPI_LDAP_BIND_DN: cn=admin,dc=lab,dc=local
171+
GLPI_LDAP_BIND_PASSWORD: LdapProd06!
172+
KEYCLOAK_URL: http://glpi-p06-kc:8080
173+
KEYCLOAK_REALM: it-stack
174+
KEYCLOAK_CLIENT_ID: glpi
175+
KEYCLOAK_CLIENT_SECRET: glpi-prod-secret-06
176+
GLPI_SMTP_HOST: glpi-p06-mail
177+
GLPI_SMTP_PORT: "1025"
178+
GLPI_SMTP_FROM: glpi@lab.local
179+
ZAMMAD_URL: http://zammad.lab.local:3000
180+
ZAMMAD_TOKEN: prod-zammad-token-06
181+
volumes:
182+
- glpi-p06-app-data:/var/www/html/files
183+
healthcheck:
184+
test: ["CMD-SHELL", "curl -sf http://localhost:80/ || exit 1"]
185+
interval: 30s
186+
timeout: 10s
187+
retries: 5
188+
start_period: 120s
189+
networks:
190+
- glpi-p06-net
191+
deploy:
192+
resources:
193+
limits:
194+
cpus: "1.5"
195+
memory: 1G
196+
reservations:
197+
cpus: "0.25"
198+
memory: 256M
199+
200+
# ── GLPI Cron (automatic actions + notifications) ─────────────────────────
201+
glpi-p06-cron:
202+
image: diouxx/glpi:latest
203+
container_name: glpi-p06-cron
204+
restart: unless-stopped
205+
entrypoint: ["/bin/bash", "-c", "while true; do php /var/www/html/front/cron.php > /dev/null 2>&1; sleep 60; done"]
206+
depends_on:
207+
glpi-p06-app:
208+
condition: service_healthy
209+
environment:
210+
IT_STACK_ENV: production
211+
IT_STACK_MODULE: glpi
212+
IT_STACK_LAB: "06"
213+
MARIADB_HOST: glpi-p06-db
214+
MARIADB_PORT: "3306"
215+
MARIADB_DATABASE: glpi
216+
MARIADB_USER: glpi
217+
MARIADB_PASSWORD: GlpiProd06!
218+
volumes:
219+
- glpi-p06-app-data:/var/www/html/files
220+
networks:
221+
- glpi-p06-net
222+
deploy:
223+
resources:
224+
limits:
225+
cpus: "0.25"
226+
memory: 256M
227+
reservations:
228+
cpus: "0.05"
229+
memory: 64M
230+
231+
# ── Networks ───────────────────────────────────────────────────────────────────
232+
networks:
233+
glpi-p06-net:
234+
name: glpi-p06-net
235+
driver: bridge
236+
237+
# ── Volumes ────────────────────────────────────────────────────────────────────
238+
volumes:
239+
glpi-p06-db-data:
240+
glpi-p06-ldap-data:
241+
glpi-p06-ldap-config:
242+
glpi-p06-app-data:
10243
environment:
11244
- IT_STACK_ENV=production
12245
- KEYCLOAK_URL=

0 commit comments

Comments
 (0)