-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcompose-helper.sh
More file actions
executable file
·160 lines (143 loc) · 5.29 KB
/
Copy pathcompose-helper.sh
File metadata and controls
executable file
·160 lines (143 loc) · 5.29 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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#!/bin/bash
# Github: https://github.com/jpbaking/compose-helper
# Author: jpbaking (https://github.com/jpbaking)
#
# Thin wrapper around docker compose that enforces consistent project naming,
# env file handling, and provides shorthand commands for common workflows.
# Must live alongside docker-compose.yaml. Safe to call via symlink.
#
# WARNING: Intended for local development use only. Do not use in production
# or CI/CD pipelines without careful review — commands like 'down' remove
# volumes, env files are sourced and exported into the process, and there is
# no access control or dry-run mode.
# Resolve through symlinks so the working directory is always the script's
# real location, not where the symlink lives or where the caller is.
SCRIPT_PATH="$(readlink -f "${BASH_SOURCE[0]}")"
SCRIPT_DIR="$(dirname "$SCRIPT_PATH")"
SCRIPT_NAME="$(basename "$SCRIPT_PATH")"
SCRIPT_BASE="${SCRIPT_NAME%.*}"
cd "$SCRIPT_DIR"
# Prefer the v2 plugin ("docker compose") over the standalone v1 binary.
# DC is an array so it expands safely regardless of whether it's one or two words.
if docker compose version &>/dev/null 2>&1; then
DC=(docker compose)
elif command -v docker-compose &>/dev/null 2>&1; then
DC=(docker-compose)
else
echo "Error: neither 'docker compose' nor 'docker-compose' found" >&2
exit 1
fi
if [[ -f "docker-compose.yaml" ]]; then
COMPOSE_FILE="docker-compose.yaml"
elif [[ -f "docker-compose.yml" ]]; then
COMPOSE_FILE="docker-compose.yml"
else
echo "Error: no docker-compose.yaml or docker-compose.yml found in $SCRIPT_DIR" >&2
exit 1
fi
# (script_name).env configures DCH itself (timeouts, tail length, etc.).
# Sourced early so DCH_PROJECT_NAME can override the directory-derived project name.
# set -a exports every variable so child processes (docker compose) see them too.
# Note: if DCH_* vars are already in the calling shell's environment, sourcing
# this file will overwrite them — the file takes precedence over the caller.
if [[ -f "${SCRIPT_BASE}.env" ]]; then
set -a
# shellcheck source=/dev/null
source "${SCRIPT_BASE}.env"
set +a
fi
# DCH_PROJECT_NAME (from compose-helper.env) overrides the directory-derived name.
# Pinning the project name prevents docker compose from deriving it from the
# current working directory, which can vary by caller.
PROJECT_NAME="${DCH_PROJECT_NAME:-$(basename "$SCRIPT_DIR")}"
DC_OPTS=(-p "$PROJECT_NAME" -f "$COMPOSE_FILE")
# .env is passed to docker compose for container variable substitution.
# .config/.env is the fallback for projects that keep config out of the root.
if [[ -f ".env" ]]; then
DC_OPTS+=(--env-file ".env")
elif [[ -f ".config/.env" ]]; then
DC_OPTS+=(--env-file ".config/.env")
fi
DCH_STOP_TIMEOUT="${DCH_STOP_TIMEOUT:-30}"
DCH_LOGS_TAIL="${DCH_LOGS_TAIL:-10}"
run_dc() {
"${DC[@]}" "${DC_OPTS[@]}" "$@"
}
usage() {
cat <<EOF
Usage: $(basename "$0") <command> [args]
Commands:
up Rebuild, start detached, then follow logs
rebuild Rebuild, start detached
build Rebuild only (no start)
pull Pull images
start Start detached (no pull/build)
restart Stop then start detached (no pull/build)
stop Stop with ${DCH_STOP_TIMEOUT}s timeout, remove orphans
down Stop with ${DCH_STOP_TIMEOUT}s timeout, remove orphans and volumes
logs Follow logs from last ${DCH_LOGS_TAIL} lines
reset-auth Reset owner authentication (password + TOTP) in the running container
claude-auth Authenticate Claude Code in the running container (interactive)
<other> Pass-through to docker compose
Note: passing 2 or more arguments always bypasses named commands and routes
directly to docker compose (e.g. 'up --build' skips the 'up' shorthand).
Environment (set in ${SCRIPT_BASE}.env):
DCH_PROJECT_NAME Override project name (default: directory name)
DCH_STOP_TIMEOUT Shutdown timeout in seconds (default: 30)
DCH_LOGS_TAIL Log tail line count (default: 10)
Project: $PROJECT_NAME Compose: $COMPOSE_FILE
EOF
}
if [[ $# -gt 1 ]]; then
run_dc "$@"
exit
fi
case "${1:-}" in
""|--help)
usage
;;
up)
# --profile build targets services with a build: block, which by convention
# are always placed under the "build" profile in docker-compose.yaml.
# --pull ensures base images are refreshed, not served from the layer cache.
run_dc --profile build build --pull
run_dc up -d
run_dc logs -f --tail="$DCH_LOGS_TAIL"
;;
start)
run_dc up -d
;;
pull)
run_dc pull
;;
build)
run_dc --profile build build --pull
;;
rebuild)
run_dc --profile build build --pull
run_dc up -d
;;
restart)
run_dc down -t "$DCH_STOP_TIMEOUT" --remove-orphans
run_dc up -d
;;
stop)
run_dc down -t "$DCH_STOP_TIMEOUT" --remove-orphans
;;
down)
# -v removes named volumes — use when a clean-slate data reset is intended.
run_dc down -t "$DCH_STOP_TIMEOUT" --remove-orphans -v
;;
logs)
run_dc logs -f --tail="$DCH_LOGS_TAIL"
;;
reset-auth)
run_dc exec second-brain-web node server/dist/cli/reset-auth.js /data
;;
claude-auth)
run_dc exec second-brain-web claude auth login
;;
*)
run_dc "$@"
;;
esac