1+ {% set NODE_IXS = range (1, (RABBIT_CLUSTER_NODE_COUNT | int ) + 1) -%}
2+
13services:
2- rabbit01:
4+ {% for ix in NODE_IXS %}
5+ rabbit0{{ ix }}:
36 image: itisfoundation/rabbitmq:4.1.2-management
47 init: true
58 # https://docs.docker.com/reference/cli/docker/service/create/#create-services-using-templates
@@ -8,32 +11,91 @@ services:
811 RABBITMQ_DEFAULT_USER: ${RABBIT_USER}
912 RABBITMQ_DEFAULT_PASS: ${RABBIT_PASSWORD}
1013 RABBITMQ_NODENAME: {% raw %} "rabbit@{{.Service.Name}}"{% endraw %}
14+ # https://docs.docker.com/reference/compose-file/services/#long-syntax-5
15+ # https://hub.docker.com/_/rabbitmq#erlang-cookie
16+ {% if ix == 1 %}
17+ # TODO: remove
18+ ports:
19+ - "15672:15672" # management UI
20+ {% endif %}
21+ secrets:
22+ # https://github.com/docker-library/rabbitmq/issues/279
23+ - source: rabbit_erlang_cookie
24+ target: /var/lib/rabbitmq/.erlang.cookie
25+ mode: 0600
26+ # as long as "default" user is used (no user explicitly specified)
27+ uid: "999"
28+ gid: "999"
29+ configs:
30+ - source: rabbitmq.conf
31+ target: /etc/rabbitmq/rabbitmq.conf
32+ mode: 0600
33+ uid: "999"
34+ gid: "999"
1135 volumes:
12- - rabbit_data :/var/lib/rabbitmq
36+ - rabbit0{{ ix }}_data :/var/lib/rabbitmq
1337 # TODO: sync with existing rabbit attached networks
1438 networks:
1539 - rabbit
1640 # TODO: consider another healthcheck (e.g. check kubernetes operator)
1741 healthcheck:
18- # see https://www.rabbitmq.com/monitoring.html#individual-checks for info about health-checks available in rabbitmq
19- test: rabbitmq-diagnostics -q status
20- interval: 5s
21- timeout: 30s
22- retries: 5
23- start_period: 5s
42+ # see https://hub.docker.com/_/rabbitmq#healthlivenessreadiness-checking
43+ # https://www.rabbitmq.com/docs/clustering#restarting-readiness-probes
44+ # we must have a healthcheck that does not require node to be fully booted (i.e. joined a cluster)
45+ # because it creates a deadlock: docker swarm will not route to the node until it is healthy
46+ # node is not healthy until it is part of a cluster (other node can talk to it)
47+ test: rabbitmq-diagnostics ping
48+ interval: 60s
49+ timeout: 10s
50+ retries: 2
51+ start_period: 30s
52+ start_interval: 10s
53+ {% endfor %}
2454
25- busybox:
26- image: ubuntu:22.04
27- command: /bin/sh -c "sleep infinity"
55+ subscriber:
56+ image: python:3.11
57+ command: sh -c "pip install pika && python /app/sub.py"
58+ environment:
59+ - RABBIT_HOSTS=rabbit_rabbit01,rabbit_rabbit02,rabbit_rabbit03
60+ - RABBIT_USER=${RABBIT_USER}
61+ - RABBIT_PASS=${RABBIT_PASSWORD}
62+ networks:
63+ - rabbit
64+ volumes:
65+ - ./test/sub.py:/app/sub.py
66+
67+ publisher:
68+ image: python:3.11
69+ command: sh -c "pip install pika && python /app/pub.py"
70+ environment:
71+ - RABBIT_HOSTS=rabbit_rabbit01,rabbit_rabbit02,rabbit_rabbit03
72+ - RABBIT_USER=${RABBIT_USER}
73+ - RABBIT_PASS=${RABBIT_PASSWORD}
2874 networks:
2975 - rabbit
76+ volumes:
77+ - ./test/pub.py:/app/pub.py
78+
79+ volumes:
80+ {% for ix in NODE_IXS %}
81+ rabbit0{{ ix }}_data:
82+ name: ${STACK_NAME}0{{ ix }}_data
83+ {% - endfor %}
84+
3085networks:
3186 # TODO: consider creating it externally for better control over subnets size and ip ranges
3287 rabbit:
3388 name: ${RABBIT_DOCKER_SWARM_NETWORK_NAME}
3489 driver: overlay
3590 attachable: true
3691
37- volumes:
38- rabbit_data:
39- name: ${STACK_NAME}_rabbit_data
92+ configs:
93+ rabbitmq.conf:
94+ file: ./rabbitmq.conf
95+ name: ${STACK_NAME}_rabbitmq_conf_{{ "./rabbitmq.conf" | sha256file | substring(0,10) }}
96+
97+ secrets:
98+ rabbit_erlang_cookie:
99+ # TODO: rolling secrets update?
100+ name: ${STACK_NAME}_erlang_cookie
101+ file: ./erlang.cookie.secret
0 commit comments