#!/usr/bin/env bash set -euo pipefail cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." command -v docker >/dev/null || { echo 'Docker가 필요합니다.' >&2; exit 1; } docker compose version >/dev/null # Compose가 해석한 설정만 사용합니다. .env를 셸 코드로 실행하지 않습니다. resolved="$(docker compose config --environment)" while IFS='=' read -r key value; do case "$key" in TRILIUM_KO_PORT|TRILIUM_KO_BIND|TRILIUM_KO_DATA_DIR|TRILIUM_KO_IMAGE) export "$key=$value" ;; esac done <<< "$resolved" unset resolved export TRILIUM_KO_PORT="${TRILIUM_KO_PORT:-8082}" export TRILIUM_KO_BIND="${TRILIUM_KO_BIND:-127.0.0.1}" export TRILIUM_KO_DATA_DIR="${TRILIUM_KO_DATA_DIR:-./data}" [[ "$TRILIUM_KO_PORT" =~ ^[0-9]+$ ]] && ((TRILIUM_KO_PORT>0 && TRILIUM_KO_PORT<65536)) || { echo '포트는 1~65535의 숫자여야 합니다.' >&2; exit 1; } docker compose config --quiet if [[ -d "$TRILIUM_KO_DATA_DIR" ]]; then data_absolute="$(cd -- "$TRILIUM_KO_DATA_DIR" && pwd)" own="$(docker compose ps -q trilium)" for running in $(docker ps -q --no-trunc); do [[ "$running" == "$own" ]] && continue mounted="$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/home/node/trilium-data"}}{{.Source}}{{end}}{{end}}' "$running")" if [[ "$mounted" == "$data_absolute" ]]; then echo '다른 컨테이너가 이 데이터를 사용 중입니다. 해당 컨테이너를 먼저 중지하세요.' >&2; exit 1; fi done fi old_container="$(docker compose ps -aq trilium)" old_image='' rollback_image='' if [[ -n "$old_container" ]]; then old_image="$(docker inspect --format '{{.Image}}' "$old_container")" rollback_image="trilium-korean-rollback:$(date -u +%Y%m%dT%H%M%SZ)-$$" docker image tag "$old_image" "$rollback_image" fi echo '검증된 버전의 한국어 이미지를 빌드합니다.' docker compose build trilium backup='' stopped=0 trap 'if [[ "$stopped" == 1 && -n "$old_container" ]]; then docker start "$old_container" >/dev/null || true; fi' ERR if [[ -d "$TRILIUM_KO_DATA_DIR" ]]; then if [[ -n "$old_container" ]]; then docker compose stop trilium; stopped=1; fi backup="$PWD/backups/$(date -u +%Y%m%dT%H%M%SZ)-$$" mkdir -p -- "$backup"; chmod 700 "$backup" data_absolute="$(cd -- "$TRILIUM_KO_DATA_DIR" && pwd)" docker run --rm --user 0 --entrypoint sh -v "$data_absolute:/backup-source:ro" -v "$backup:/backup-target" "${TRILIUM_KO_IMAGE:-trilium-korean:2.0.0}" -c 'umask 077; tar -czpf /backup-target/data.tar.gz -C /backup-source .' printf '%s\n' "$rollback_image" > "$backup/previous-image.txt" printf '%s\n' "$old_image" > "$backup/previous-image-id.txt" cp docker-compose.yml "$backup/docker-compose.yml" [[ ! -f .env ]] || cp .env "$backup/.env" echo "데이터 백업: $backup" fi if docker compose up -d --no-build --wait --wait-timeout 180; then stopped=0 echo "배포 완료: http://${TRILIUM_KO_BIND}:${TRILIUM_KO_PORT}" echo '새 설치라면 초기 설정에서 새 문서를 만든 뒤 한국어를 선택하세요.' else stopped=0 echo '기동 검증에 실패했습니다.' >&2 if [[ -n "$old_image" ]]; then echo '이전 이미지로 되돌립니다. 데이터 백업은 유지합니다.' >&2 TRILIUM_KO_IMAGE="$rollback_image" docker compose up -d --no-build --pull never --wait --wait-timeout 180 || true fi [[ -z "$backup" ]] || echo "데이터 복구용 백업: $backup/data.tar.gz" >&2 exit 1 fi