De la Docker Compose la GitOps: migrarea graduală a unei aplicații full-stack către Kubernetes și Argo CD

Dată proiect:
2 februarie 2026

Proiectul implementează migrarea aplicației Contapics — o aplicație full-stack containerizată (frontend web, backend API, serviciu OCR cu Tesseract, PostgreSQL și MinIO ca object storage compatibil S3) — de la un mediu de dezvoltare local bazat pe Docker Compose, provizionat automat printr-un playbook Ansible, către un cluster Kubernetes local (Minikube), cu chart-uri Helm dedicate fiecărui serviciu. Deployment-ul este gestionat prin GitOps cu Argo CD, cu repository-uri separate pentru codul aplicației și configurația de deployment și sincronizare automată a clusterului cu starea din Git, iar monitorizarea si observabilitatea sunt asigurate prin kube-prometheus-stack (Prometheus, Grafana) și loguri centralizate cu Grafana Loki.

Proiect realizat de
Picture of Matei Ranga
Matei Ranga
În cadrul programului de studiu:
1

Înțelegem arhitectura aplicației

Contapics este o aplicație full-stack structurată ca un set de servicii containerizate: un backend API (port 8080) pentru autentificare și gestionarea datelor contabile, un frontend web (port 80), un serviciu OCR (Tesseract, comunicare REST cu backend-ul), PostgreSQL (port 5432) și MinIO — object storage compatibil S3 (port 9000/9001) — pentru fișierele rezultate din OCR. Fiecare componentă a fost dezvoltată și testată izolat local, urmând ca aceleași servicii să fie mutate ulterior în Kubernetes doar prin adaptări de configurare, fără schimbări majore de cod.
2

Construim mediul de dezvoltare local

Mediul de dezvoltare a fost complet containerizat cu Docker și Docker Compose: fiecare componentă (backend, frontend, OCR) are propriul Dockerfile, iar `docker-compose.yml` definește rețeaua comună, volumele (de exemplu pentru datele PostgreSQL) și variabilele necesare mediului local, centralizate într-un fișier `.env`. Pentru a elimina pașii manuali repetitivi la fiecare pornire a mediului — crearea utilizatorului admin în PostgreSQL și a bucket-ului dedicat în MinIO — a fost scris un playbook Ansible idempotent, care așteaptă ca Postgres și MinIO să fie „up & running” înainte de a rula, iar dacă utilizatorul sau bucket-ul există deja, nu produce erori. Practic, cu o singură comandă (`docker-compose up -d && ansible-playbook dev-setup.yml`), orice coechipier obține un mediu complet configurat, fără să creeze manual conturi sau resurse — reducând diferențele de configurare între stațiile de lucru și scurtând onboarding-ul dezvoltatorilor noi.
3

Migrarea la Kubernetes

Proiectul a fost portat pe un cluster Kubernetes local cu Minikube: imaginile Docker sunt construite direct în engine-ul intern (`minikube docker-env`, fără registry extern). Patru dintre servicii — backend, frontend, OCR și MinIO — primesc fiecare un chart Helm propriu, iar configurația din `.env` este adaptată manual pentru Kubernetes prin `values.yaml`, ConfigMaps și Secrets; PostgreSQL rulează separat, printr-un chart Helm Bitnami. Migrarea a impus și corectarea rezolvării hostname-urilor, de la numele de container (Docker Compose) la DNS de Service (Kubernetes, ex. `minio-service:9000`).
4

Deployment declarativ prin GitOps cu Argo CD

Deployment-ul este gestionat declarativ prin GitOps: Helm descrie resursele Kubernetes, iar Argo CD reconciliază clusterul cu starea din Git. Proiectul folosește două repository-uri separate — `contapics-app` (cod sursă, Dockerfile-uri) și un repo GitOps (chart-uri Helm, `values.yaml`, definiții Argo CD) — separând codul aplicației de configurația de deployment, cu promovare explicită prin pull request-uri. Argo CD, instalat în namespace propriu, monitorizează branch-ul de deployment și, cu auto-sync activat pe cele patru aplicații, aplică automat orice diferență (`OutOfSync`); fără auto-sync, aceasta ar rămâne doar semnalată. Un revert de commit aduce resursele Kubernetes la starea declarată anterior, dar rollback-ul nu acoperă migrațiile de schemă sau datele din PostgreSQL.
5

Monitorizare și observabilitate

Stack-ul de monitorizare, instalat într-un namespace dedicat, folosește chart-ul `kube-prometheus-stack` (Prometheus Operator, Prometheus, Alertmanager, Grafana). Pentru loguri centralizate s-a adăugat Grafana Loki cu Promtail, care indexează doar metadatele și consumă mult mai puține resurse decât un ELK complet pe un Minikube single-node — deși Promtail este depreciat în favoarea Grafana Alloy. Backend-ul expune metrici pe `/actuator/prometheus`, iar Grafana, cu Prometheus și Loki ca surse de date, permite corelarea manuală a metricilor cu logurile filtrate prin LogQL — de exemplu corelarea logurilor provenite din componentele implicate în procesarea unui request eșuat — fără a fi însă un tracing automat end-to-end (pentru care ar fi nevoie de OpenTelemetry/Tempo). Accesul s-a făcut prin `kubectl port-forward`, urmând ca în producție să fie folosit un Service de tip LoadBalancer sau un Ingress Controller.
6

Considerații privind costurile

Pentru estimarea costurilor, am comparat rularea on-premise și AWS pentru un scenariu ipotetic de ~1000 utilizatori/zi. O estimare simplificată arată ~800 USD/an on-premise (amortizat pe 3 ani) față de ~2.400 USD/an în AWS (EC2 + RDS + S3) — deci varianta cloud costă de trei ori mai mult anual în configurația evaluată, dar transferă către furnizor administrarea infrastructurii fizice și, în cazul serviciilor managed, o parte din sarcinile de mentenanță.

Descoperă proiecte similare