fix: resolve 4 P0 DevOps blockers — image tags, alertmanager, port conflicts

DEVOPS-C-01: Replace hardcoded :latest with IMAGE_TAG placeholder in all 8
production K8s manifests. Update deploy-production.yml to sed-replace
IMAGE_TAG with commit SHA before kubectl apply (remove now-redundant
kubectl set image step).

DEVOPS-C-02: Configure Alertmanager — create alertmanager.yml with Slack +
email receivers (critical/warning/infra routes, inhibition rules). Add
alertmanager:v0.27.0 service to both docker-compose.observability.yml and
deployments/local/docker-compose.yml. Enable prometheus.yml target
(alertmanager:9093).

DEVOPS-C-03: Remove :latest from docker-build.yml main branch push. Now
only SHA tag is pushed for main; :staging+SHA for develop.

DEVOPS-C-04: Add 4 mkt-* services to deployments/local/docker-compose.yml
with unique host ports (facebook:5021, whatsapp:5022, x:5023, zalo:5024)
to eliminate port 5000 conflicts. Add corresponding Traefik routers and
load-balancer entries in infra/traefik/dynamic/routes.yml
(/api/v1/mkt/{facebook,whatsapp,x,zalo}).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-03-23 09:46:32 +07:00
parent cdc67d768f
commit 6d0ca5bee5
15 changed files with 438 additions and 20 deletions

View File

@@ -1227,6 +1227,190 @@ services:
- "traefik.http.routers.ads-tracking-admin.service=ads-tracking-service"
# Marketing Services - Social Media Integrations
# EN: Each service gets unique host port to avoid port 5000 conflicts
# VI: Moi service duoc cap port host rieng de tranh xung dot port 5000
mkt-facebook-service-net:
build:
context: ../../services/mkt-facebook-service-net
dockerfile: Dockerfile
image: goodgo/mkt-facebook-service-net:latest
container_name: mkt-facebook-service-net-local
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://+:8080
- ConnectionStrings__DefaultConnection=${MKT_FACEBOOK_DATABASE_URL}
- IamService__BaseUrl=http://iam-service-net:8080
- Jwt__Authority=http://iam-service-net:8080
- Jwt__Audience=goodgo-api
- Jwt__RequireHttpsMetadata=false
- Redis__Host=${REDIS_HOST}
- Redis__Port=${REDIS_PORT}
- Redis__Password=${REDIS_PASSWORD}
- RabbitMQ__Host=rabbitmq
- RabbitMQ__Port=5672
- RabbitMQ__Username=${RABBITMQ_USERNAME}
- RabbitMQ__Password=${RABBITMQ_PASSWORD}
ports:
- "5021:8080"
depends_on:
iam-service-net:
condition: service_healthy
traefik:
condition: service_started
networks:
- microservices-network
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
labels:
- "traefik.enable=true"
- "traefik.http.routers.mkt-facebook.rule=PathPrefix(`/api/v1/mkt/facebook`)"
- "traefik.http.routers.mkt-facebook.entrypoints=web"
- "traefik.http.services.mkt-facebook-service.loadbalancer.server.port=8080"
- "traefik.http.services.mkt-facebook-service.loadbalancer.healthcheck.path=/health/live"
- "traefik.http.services.mkt-facebook-service.loadbalancer.healthcheck.interval=10s"
mkt-whatsapp-service-net:
build:
context: ../../services/mkt-whatsapp-service-net
dockerfile: Dockerfile
image: goodgo/mkt-whatsapp-service-net:latest
container_name: mkt-whatsapp-service-net-local
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://+:8080
- ConnectionStrings__DefaultConnection=${MKT_WHATSAPP_DATABASE_URL}
- IamService__BaseUrl=http://iam-service-net:8080
- Jwt__Authority=http://iam-service-net:8080
- Jwt__Audience=goodgo-api
- Jwt__RequireHttpsMetadata=false
- Redis__Host=${REDIS_HOST}
- Redis__Port=${REDIS_PORT}
- Redis__Password=${REDIS_PASSWORD}
- RabbitMQ__Host=rabbitmq
- RabbitMQ__Port=5672
- RabbitMQ__Username=${RABBITMQ_USERNAME}
- RabbitMQ__Password=${RABBITMQ_PASSWORD}
ports:
- "5022:8080"
depends_on:
iam-service-net:
condition: service_healthy
traefik:
condition: service_started
networks:
- microservices-network
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
labels:
- "traefik.enable=true"
- "traefik.http.routers.mkt-whatsapp.rule=PathPrefix(`/api/v1/mkt/whatsapp`)"
- "traefik.http.routers.mkt-whatsapp.entrypoints=web"
- "traefik.http.services.mkt-whatsapp-service.loadbalancer.server.port=8080"
- "traefik.http.services.mkt-whatsapp-service.loadbalancer.healthcheck.path=/health/live"
- "traefik.http.services.mkt-whatsapp-service.loadbalancer.healthcheck.interval=10s"
mkt-x-service-net:
build:
context: ../../services/mkt-x-service-net
dockerfile: Dockerfile
image: goodgo/mkt-x-service-net:latest
container_name: mkt-x-service-net-local
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://+:8080
- ConnectionStrings__DefaultConnection=${MKT_X_DATABASE_URL}
- IamService__BaseUrl=http://iam-service-net:8080
- Jwt__Authority=http://iam-service-net:8080
- Jwt__Audience=goodgo-api
- Jwt__RequireHttpsMetadata=false
- Redis__Host=${REDIS_HOST}
- Redis__Port=${REDIS_PORT}
- Redis__Password=${REDIS_PASSWORD}
- RabbitMQ__Host=rabbitmq
- RabbitMQ__Port=5672
- RabbitMQ__Username=${RABBITMQ_USERNAME}
- RabbitMQ__Password=${RABBITMQ_PASSWORD}
ports:
- "5023:8080"
depends_on:
iam-service-net:
condition: service_healthy
traefik:
condition: service_started
networks:
- microservices-network
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
labels:
- "traefik.enable=true"
- "traefik.http.routers.mkt-x.rule=PathPrefix(`/api/v1/mkt/x`)"
- "traefik.http.routers.mkt-x.entrypoints=web"
- "traefik.http.services.mkt-x-service.loadbalancer.server.port=8080"
- "traefik.http.services.mkt-x-service.loadbalancer.healthcheck.path=/health/live"
- "traefik.http.services.mkt-x-service.loadbalancer.healthcheck.interval=10s"
mkt-zalo-service-net:
build:
context: ../../services/mkt-zalo-service-net
dockerfile: Dockerfile
image: goodgo/mkt-zalo-service-net:latest
container_name: mkt-zalo-service-net-local
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://+:8080
- ConnectionStrings__DefaultConnection=${MKT_ZALO_DATABASE_URL}
- IamService__BaseUrl=http://iam-service-net:8080
- Jwt__Authority=http://iam-service-net:8080
- Jwt__Audience=goodgo-api
- Jwt__RequireHttpsMetadata=false
- Redis__Host=${REDIS_HOST}
- Redis__Port=${REDIS_PORT}
- Redis__Password=${REDIS_PASSWORD}
- RabbitMQ__Host=rabbitmq
- RabbitMQ__Port=5672
- RabbitMQ__Username=${RABBITMQ_USERNAME}
- RabbitMQ__Password=${RABBITMQ_PASSWORD}
ports:
- "5024:8080"
depends_on:
iam-service-net:
condition: service_healthy
traefik:
condition: service_started
networks:
- microservices-network
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
labels:
- "traefik.enable=true"
- "traefik.http.routers.mkt-zalo.rule=PathPrefix(`/api/v1/mkt/zalo`)"
- "traefik.http.routers.mkt-zalo.entrypoints=web"
- "traefik.http.services.mkt-zalo-service.loadbalancer.server.port=8080"
- "traefik.http.services.mkt-zalo-service.loadbalancer.healthcheck.path=/health/live"
- "traefik.http.services.mkt-zalo-service.loadbalancer.healthcheck.interval=10s"
# Jaeger - Distributed Tracing
# jaeger:
# image: jaegertracing/all-in-one:1.47
@@ -1240,6 +1424,32 @@ services:
# - microservices-network
# restart: unless-stopped
# Alertmanager - Alert Routing & Notification Delivery
alertmanager:
image: prom/alertmanager:v0.27.0
container_name: alertmanager-local
command:
- '--config.file=/etc/alertmanager/alertmanager.yml'
- '--storage.path=/alertmanager'
- '--web.external-url=http://localhost:9093'
ports:
- "9093:9093"
volumes:
- ../../infra/observability/alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
- alertmanager_data:/alertmanager
environment:
- ALERTMANAGER_SLACK_WEBHOOK_URL=${ALERTMANAGER_SLACK_WEBHOOK_URL:-}
- ALERTMANAGER_SMTP_USER=${ALERTMANAGER_SMTP_USER:-}
- ALERTMANAGER_SMTP_PASSWORD=${ALERTMANAGER_SMTP_PASSWORD:-}
networks:
- microservices-network
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:9093/-/healthy || exit 1"]
interval: 30s
timeout: 10s
retries: 3
# Prometheus - Metrics Collection
prometheus:
image: prom/prometheus:v2.51.0
@@ -1402,6 +1612,8 @@ volumes:
driver: local
loki_data:
driver: local
alertmanager_data:
driver: local
# =============================================================================
# NETWORKS
# =============================================================================

View File

@@ -40,7 +40,7 @@ spec:
topologyKey: kubernetes.io/hostname
containers:
- name: booking-service
image: goodgo/booking-service-net:latest
image: goodgo/booking-service-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080

View File

@@ -40,7 +40,7 @@ spec:
topologyKey: kubernetes.io/hostname
containers:
- name: catalog-service
image: goodgo/catalog-service-net:latest
image: goodgo/catalog-service-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080

View File

@@ -40,7 +40,7 @@ spec:
topologyKey: kubernetes.io/hostname
containers:
- name: fnb-engine
image: goodgo/fnb-engine-net:latest
image: goodgo/fnb-engine-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080

View File

@@ -42,7 +42,7 @@ spec:
topologyKey: kubernetes.io/hostname
containers:
- name: iam-service
image: goodgo/iam-service-net:latest
image: goodgo/iam-service-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080

View File

@@ -40,7 +40,7 @@ spec:
topologyKey: kubernetes.io/hostname
containers:
- name: inventory-service
image: goodgo/inventory-service-net:latest
image: goodgo/inventory-service-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080

View File

@@ -40,7 +40,7 @@ spec:
topologyKey: kubernetes.io/hostname
containers:
- name: merchant-service
image: goodgo/merchant-service-net:latest
image: goodgo/merchant-service-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080

View File

@@ -40,7 +40,7 @@ spec:
topologyKey: kubernetes.io/hostname
containers:
- name: order-service
image: goodgo/order-service-net:latest
image: goodgo/order-service-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080

View File

@@ -40,7 +40,7 @@ spec:
topologyKey: kubernetes.io/hostname
containers:
- name: wallet-service
image: goodgo/wallet-service-net:latest
image: goodgo/wallet-service-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080