Files
rlabadmin 788eaa390f
Build & Deploy / build (push) Successful in 5s
Build & Deploy / deploy (push) Successful in 5s
CI owns the whole stack — deploy via docker stack deploy
- stack.yml: parameterize image tag with ${IMAGE_TAG:-latest} so callers
  can pin the SHA; falls back to :latest for manual invocations
- flow.yml: replace service update with `docker stack deploy -c -`
  piped over SSH. Handles both first-time deploy and rolling updates.
  No more manual `docker stack deploy` on the manager before CI works.

Portainer can still view the stack but should not auto-update the same
one from git — two writers will conflict.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 15:31:14 +02:00

34 lines
1.1 KiB
YAML

# stack.yml — generic Swarm deploy file
# Deploy once: docker stack deploy -c stack.yml myapp
# After that, CI updates the image via `docker service update` — no redeploy needed
version: "3.9"
networks:
traefik-public:
external: true
services:
web:
image: git.dev.serso.org/test/testsite:${IMAGE_TAG:-latest}
networks:
- traefik-public
deploy:
replicas: 2
placement:
constraints:
- node.role == worker # run on node01/node02, not cp
update_config:
parallelism: 1
order: start-first # zero-downtime (spin new up, then down old)
failure_action: rollback
restart_policy:
condition: on-failure
labels:
- "traefik.enable=true"
- "traefik.http.routers.testwebsite.rule=Host(`testwebsite.dev.serso.org`)"
- "traefik.http.routers.testwebsite.entrypoints=websecure"
- "traefik.http.routers.testwebsite.tls.certresolver=letsencrypt"
# Port that your app listens on INSIDE the container
- "traefik.http.services.testwebsite.loadbalancer.server.port=8080"