Repository navigation
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
134 lines (129 loc) · 5.4 KB
/
Copy pathdocker-compose.yml
File metadata and controls
134 lines (129 loc) · 5.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
services:
# Runs to completion before the services below, copying any data/ file that is missing from the
# mount out of the image's pristine copy. A bind mount never inherits image content, so without
# this a host with no checkout mounts an empty directory over /app/data and the bot dies reading
# characters.json during module load.
dataseed:
image: ghcr.io/jmiln/swgohbot:${IMAGE_TAG:-latest}
build: .
container_name: swgoh-dataseed
# root: a bind-mount directory Docker just created is owned by root, and the seed has to write
# into it and then hand it to the runtime uid.
user: root
restart: "no"
command: ["node", "scripts/seedData.ts"]
env_file: .env
environment:
DATA_UID: "${DATA_UID:-1000}"
DATA_GID: "${DATA_GID:-1000}"
volumes:
- ${DATA_DIR:-./data}:/app/data
# Never started by `docker compose up` - `profiles:` keeps it out unless it is named explicitly.
# It exists so the host crontab can run the updater from the image instead of from a checkout:
# 0 4 * * * cd /srv/swgohbot && docker compose run --rm dataupdater >> <log> 2>&1
# Still run-once-and-exit, so the OS reclaims the cycle's large transient allocations between runs.
dataupdater:
image: ghcr.io/jmiln/swgohbot:${IMAGE_TAG:-latest}
build: .
profiles: ["updater"]
restart: "no"
command: ["node", "services/dataUpdater.ts", "--cleanup"]
env_file: .env
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- swgoh
volumes:
- ${DATA_DIR:-./data}:/app/data
bot:
image: ghcr.io/jmiln/swgohbot:${IMAGE_TAG:-latest}
# `build:` is for local iteration only. Anything deployed is built and published by CI.
build: .
container_name: swgohbot
restart: unless-stopped
command: ["node", "swgohBotShard.ts"]
env_file: .env
environment:
# tini's env equivalent of -g. Without it only its direct child is signalled, reaching the
# ShardingManager but not the shards, which Shard.spawn forks as separate processes.
TINI_KILL_PROCESS_GROUP: "1"
# Loopback inside a container is that container's own, so the healthcheck and the published
# port could not reach it. The host-side 127.0.0.1 prefix below is what keeps this off the
# network.
SHARD_STATUS_HOST: 0.0.0.0
init: true
# Shards need well past a second or two to finish closing Mongo. 15s is generous.
stop_grace_period: 15s
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- swgoh
depends_on:
dataseed:
condition: service_completed_successfully
volumes:
- ${DATA_DIR:-./data}:/app/data:ro
ports:
- "127.0.0.1:${SHARD_STATUS_PORT:-3810}:${SHARD_STATUS_PORT:-3810}"
healthcheck:
# Fails only on total fleet loss, which is the one case restarting fixes. A single sick shard
# shows in /status and is left to the ShardingManager's own respawn, since restarting here
# would kill every healthy shard to fix one.
test: ["CMD", "node", "-e", "fetch('http://localhost:'+(process.env.SHARD_STATUS_PORT||3810)+'/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
interval: 30s
timeout: 5s
# Past the 60s Manager.spawn timeout with room to spare. /health reports 200 while starting,
# so this only has to outlast the spawn itself.
start_period: 180s
eventserve:
image: ghcr.io/jmiln/swgohbot:${IMAGE_TAG:-latest}
build: .
container_name: swgohbot-eventserve
restart: unless-stopped
command: ["node", "services/eventServe.ts"]
env_file: .env
init: true
extra_hosts:
- "host.docker.internal:host-gateway"
ports:
- "127.0.0.1:${EVENT_SERVER_PORT:-3700}:${EVENT_SERVER_PORT:-3700}"
networks:
- swgoh
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://localhost:'+(process.env.EVENT_SERVER_PORT||3700)+'/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
interval: 30s
timeout: 5s
start_period: 30s
swapiserve:
image: ghcr.io/jmiln/swgohbot:${IMAGE_TAG:-latest}
build: .
container_name: swgohbot-swapiserve
restart: unless-stopped
command: ["node", "services/swapiServe/index.ts"]
env_file: .env
environment:
# Must listen on all of this container's interfaces to be reachable from the bot container.
# That is the container's own network namespace, not the host's: the published port below
# stays on loopback, and the control routes are guarded by SWAPI_SERVE_CONTROL_SECRET.
SWAPI_SERVE_HOST: "0.0.0.0"
init: true
# Past SHUTDOWN_GRACE_MS in services/swapiServe/index.ts, so the service finishes its own
# shutdown rather than being killed partway through it.
stop_grace_period: 15s
extra_hosts:
- "host.docker.internal:host-gateway"
ports:
- "127.0.0.1:${SWAPI_SERVE_PORT:-3800}:${SWAPI_SERVE_PORT:-3800}"
networks:
- swgoh
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://localhost:'+(process.env.SWAPI_SERVE_PORT||3800)+'/status').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
interval: 30s
timeout: 5s
start_period: 30s
# Owned by the separate `fake-help` compose project, which runs comlink, nginx and swgoh-ae2.
# That project must be up first; compose will neither create nor destroy this network.
networks:
swgoh:
name: fake-help_default
external: true