Skip to content

Commit e38a004

Browse files
committed
feat(lab-06): Nextcloud Production Deployment -- resource limits, restart=always, persistent volumes, Prometheus metrics
1 parent 35841f5 commit e38a004

3 files changed

Lines changed: 361 additions & 95 deletions

File tree

.github/workflows/ci.yml

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,32 @@ jobs:
219219
run: docker compose -f docker/docker-compose.integration.yml logs
220220
- name: Cleanup
221221
if: always()
222-
run: docker compose -f docker/docker-compose.integration.yml down -v
222+
run: docker compose -f docker/docker-compose.integration.yml down -v
223+
224+
lab-06-smoke:
225+
name: Lab 06 -- Nextcloud Production Deployment (resource limits + metrics)
226+
runs-on: ubuntu-latest
227+
needs: validate
228+
continue-on-error: true
229+
steps:
230+
- uses: actions/checkout@v4
231+
- name: Install tools
232+
run: sudo apt-get install -y curl ldap-utils
233+
- name: Validate production compose
234+
run: docker compose -f docker/docker-compose.production.yml config -q && echo "Production compose valid"
235+
- name: Start production stack
236+
run: docker compose -f docker/docker-compose.production.yml up -d
237+
- name: Wait for Keycloak
238+
run: timeout 240 bash -c 'until curl -sf http://localhost:8204/health/ready | grep -q UP; do sleep 5; done'
239+
- name: Wait for OpenLDAP
240+
run: timeout 120 bash -c 'until docker exec nc-prod-ldap ldapsearch -x -H ldap://localhost -b dc=lab,dc=local -D cn=admin,dc=lab,dc=local -w LdapProd06! > /dev/null 2>&1; do sleep 5; done'
241+
- name: Wait for Nextcloud
242+
run: timeout 360 bash -c 'until curl -sf http://localhost:8200/status.php; do sleep 10; done'
243+
- name: Run Lab 06-06 test script
244+
run: bash tests/labs/test-lab-06-06.sh --no-cleanup
245+
- name: Collect logs on failure
246+
if: failure()
247+
run: docker compose -f docker/docker-compose.production.yml logs
248+
- name: Cleanup
249+
if: always()
250+
run: docker compose -f docker/docker-compose.production.yml down -v
Lines changed: 220 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,236 @@
1-
# Lab 06 — Production: nextcloud HA-ready with monitoring and external volumes
2-
---
1+
# docker-compose.production.yml -- Lab 06: Production Deployment
2+
# Nextcloud + PostgreSQL + Redis + Keycloak + OpenLDAP — Production Grade
3+
# Features: resource limits, restart=always, log rotation, persistent volumes,
4+
# Prometheus metrics, PHP tuning, cron worker, LDAP + OIDC auth
5+
#
6+
# Ports:
7+
# 8200 -- Nextcloud HTTP
8+
# 8204 -- Keycloak admin console
9+
# 3895 -- OpenLDAP
10+
#
11+
# Credentials:
12+
# LDAP admin: cn=admin,dc=lab,dc=local / LdapProd06!
13+
# LDAP readonly: cn=readonly,dc=lab,dc=local / ReadOnlyProd06!
14+
# DB: nextcloud / Prod06Password!
15+
# Redis: Prod06Redis!
16+
# Keycloak: admin / Prod06Admin!
17+
# OIDC secret: nextcloud-prod-06
18+
19+
x-logging: &default-logging
20+
driver: json-file
21+
options:
22+
max-size: "10m"
23+
max-file: "5"
24+
25+
x-nc-prod-env: &nc-prod-env
26+
POSTGRES_HOST: nc-prod-db
27+
POSTGRES_DB: nextcloud
28+
POSTGRES_USER: nextcloud
29+
POSTGRES_PASSWORD: Prod06Password!
30+
REDIS_HOST: nc-prod-redis
31+
REDIS_HOST_PASSWORD: Prod06Redis!
32+
NEXTCLOUD_TRUSTED_DOMAINS: "localhost nc-prod-app"
33+
PHP_MEMORY_LIMIT: 1024M
34+
PHP_UPLOAD_LIMIT: 512M
35+
PHP_MAX_TIME: 3600
36+
NC_oidc_login_provider_url: http://nc-prod-keycloak:8080/realms/it-stack
37+
NC_oidc_login_client_id: nextcloud
38+
NC_oidc_login_client_secret: nextcloud-prod-06
39+
NC_oidc_login_button_text: Login with Keycloak
40+
NC_oidc_login_auto_redirect: "false"
41+
LDAP_PROVIDER_HOST: nc-prod-ldap
42+
LDAP_PROVIDER_PORT: "389"
43+
LDAP_PROVIDER_BINDDN: "cn=readonly,dc=lab,dc=local"
44+
LDAP_PROVIDER_BINDPASS: ReadOnlyProd06!
45+
LDAP_PROVIDER_BASEDN: "dc=lab,dc=local"
46+
347
services:
4-
nextcloud:
5-
image: nextcloud:28-apache
6-
container_name: it-stack-nextcloud
48+
nc-prod-ldap:
49+
image: osixia/openldap:1.5.0
50+
container_name: nc-prod-ldap
751
restart: always
52+
environment:
53+
LDAP_ORGANISATION: "IT-Stack Production"
54+
LDAP_DOMAIN: lab.local
55+
LDAP_ADMIN_PASSWORD: LdapProd06!
56+
LDAP_READONLY_USER: "true"
57+
LDAP_READONLY_USER_USERNAME: readonly
58+
LDAP_READONLY_USER_PASSWORD: ReadOnlyProd06!
859
ports:
9-
- "80:$firstPort"
60+
- "3895:389"
61+
volumes:
62+
- nc-prod-ldap-data:/var/lib/ldap
63+
- nc-prod-ldap-config:/etc/ldap/slapd.d
64+
networks:
65+
- nc-prod-net
66+
deploy:
67+
resources:
68+
limits:
69+
memory: 256m
70+
cpus: "0.5"
71+
reservations:
72+
memory: 128m
73+
logging: *default-logging
74+
healthcheck:
75+
test: ["CMD-SHELL", "ldapsearch -x -H ldap://localhost -b dc=lab,dc=local -D cn=admin,dc=lab,dc=local -w LdapProd06! > /dev/null 2>&1"]
76+
interval: 15s
77+
timeout: 10s
78+
retries: 5
79+
start_period: 20s
80+
81+
nc-prod-db:
82+
image: postgres:16-alpine
83+
container_name: nc-prod-db
84+
restart: always
1085
environment:
11-
- IT_STACK_ENV=production
12-
- KEYCLOAK_URL=
13-
- DB_HOST=
14-
- REDIS_HOST=
15-
- GRAYLOG_HOST=
86+
POSTGRES_DB: nextcloud
87+
POSTGRES_USER: nextcloud
88+
POSTGRES_PASSWORD: Prod06Password!
89+
POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
1690
volumes:
17-
- nextcloud_data:/var/lib/nextcloud
18-
- /etc/ssl/certs:/etc/ssl/certs:ro
91+
- nc-prod-db-data:/var/lib/postgresql/data
92+
networks:
93+
- nc-prod-db-net
1994
deploy:
20-
replicas: 1
2195
resources:
2296
limits:
23-
cpus: "4.0"
24-
memory: G
97+
memory: 1g
98+
cpus: "1.0"
99+
reservations:
100+
memory: 256m
101+
logging: *default-logging
102+
healthcheck:
103+
test: ["CMD-SHELL", "pg_isready -U nextcloud"]
104+
interval: 10s
105+
timeout: 5s
106+
retries: 5
107+
108+
nc-prod-redis:
109+
image: redis:7-alpine
110+
container_name: nc-prod-redis
111+
restart: always
112+
command: >
113+
redis-server
114+
--requirepass Prod06Redis!
115+
--maxmemory 256mb
116+
--maxmemory-policy allkeys-lru
117+
--save 900 1
118+
--save 300 10
119+
volumes:
120+
- nc-prod-redis-data:/data
121+
networks:
122+
- nc-prod-net
123+
deploy:
124+
resources:
125+
limits:
126+
memory: 384m
127+
cpus: "0.5"
25128
reservations:
129+
memory: 128m
130+
logging: *default-logging
131+
healthcheck:
132+
test: ["CMD", "redis-cli", "-a", "Prod06Redis!", "ping"]
133+
interval: 10s
134+
timeout: 5s
135+
retries: 5
136+
137+
nc-prod-keycloak:
138+
image: quay.io/keycloak/keycloak:24.0
139+
container_name: nc-prod-keycloak
140+
restart: always
141+
command: start-dev
142+
environment:
143+
KC_HEALTH_ENABLED: "true"
144+
KC_METRICS_ENABLED: "true"
145+
KEYCLOAK_ADMIN: admin
146+
KEYCLOAK_ADMIN_PASSWORD: Prod06Admin!
147+
ports:
148+
- "8204:8080"
149+
networks:
150+
- nc-prod-net
151+
deploy:
152+
resources:
153+
limits:
154+
memory: 1g
26155
cpus: "1.0"
27-
memory: 1G
28-
restart_policy:
29-
condition: any
30-
delay: 5s
31-
logging:
32-
driver: gelf
33-
options:
34-
gelf-address: "udp://${GRAYLOG_HOST}:12201"
35-
tag: "it-stack-nextcloud"
156+
reservations:
157+
memory: 512m
158+
logging: *default-logging
36159
healthcheck:
37-
test: ["CMD-SHELL", "curl -sf http://localhost/health || exit 1"]
38-
interval: 30s
160+
test: ["CMD-SHELL", "curl -sf http://localhost:8080/health/ready | grep -q UP || exit 1"]
161+
interval: 20s
39162
timeout: 10s
40-
retries: 3
41-
start_period: 120s
163+
retries: 10
164+
start_period: 60s
165+
166+
nc-prod-app:
167+
image: nextcloud:29-apache
168+
container_name: nc-prod-app
169+
restart: always
170+
depends_on:
171+
nc-prod-db:
172+
condition: service_healthy
173+
nc-prod-redis:
174+
condition: service_healthy
175+
nc-prod-keycloak:
176+
condition: service_healthy
177+
nc-prod-ldap:
178+
condition: service_healthy
179+
environment:
180+
<<: *nc-prod-env
181+
ports:
182+
- "8200:80"
183+
volumes:
184+
- nc-prod-data:/var/www/html
42185
networks:
43-
- it-stack-net
186+
- nc-prod-net
187+
- nc-prod-db-net
188+
deploy:
189+
resources:
190+
limits:
191+
memory: 2g
192+
cpus: "2.0"
193+
reservations:
194+
memory: 512m
195+
logging: *default-logging
196+
healthcheck:
197+
test: ["CMD", "curl", "-f", "http://localhost/status.php"]
198+
interval: 30s
199+
timeout: 15s
200+
retries: 10
201+
start_period: 90s
44202

45-
networks:
46-
it-stack-net:
47-
external: true
48-
name: it-stack-production
203+
nc-prod-cron:
204+
image: nextcloud:29-apache
205+
container_name: nc-prod-cron
206+
restart: always
207+
depends_on:
208+
nc-prod-app:
209+
condition: service_healthy
210+
entrypoint: /cron.sh
211+
environment:
212+
<<: *nc-prod-env
213+
volumes:
214+
- nc-prod-data:/var/www/html
215+
networks:
216+
- nc-prod-net
217+
- nc-prod-db-net
218+
deploy:
219+
resources:
220+
limits:
221+
memory: 512m
222+
cpus: "0.5"
223+
reservations:
224+
memory: 128m
225+
logging: *default-logging
49226

50227
volumes:
51-
nextcloud_data:
52-
external: true
53-
name: it-stack-nextcloud-data
228+
nc-prod-ldap-data:
229+
nc-prod-ldap-config:
230+
nc-prod-db-data:
231+
nc-prod-redis-data:
232+
nc-prod-data:
233+
234+
networks:
235+
nc-prod-net:
236+
nc-prod-db-net:

0 commit comments

Comments
 (0)