#!/usr/bin/env bash set -euo pipefail APP_DIR="${APP_DIR:-/opt/hw}" CONFIG_DIR="${CONFIG_DIR:-/opt/hw.conf.d}" ENV_FILE="${ENV_FILE:-$CONFIG_DIR/hw.env}" CONTAINER_NAME="${CONTAINER_NAME:-hw}" IMAGE_NAME="${IMAGE_NAME:-hw}" IMAGE_TAG="${IMAGE_TAG:-py313}" APP_PORT="${APP_PORT:-8000}" RUN_SEED_ALL="${RUN_SEED_ALL:-0}" HOST_PORT="${HOST_PORT:-8000}" ALLOW_NON_ROOT="${ALLOW_NON_ROOT:-0}" CONTAINER_UID="${CONTAINER_UID:-10001}" CONTAINER_GID="${CONTAINER_GID:-10001}" require_root() { if [[ "$ALLOW_NON_ROOT" == "1" ]]; then return fi if [[ "${EUID}" -ne 0 ]]; then printf 'Please run this script as root.\n' >&2 exit 1 fi } require_file() { local path="$1" if [[ ! -f "$path" ]]; then printf 'Required file not found: %s\n' "$path" >&2 exit 1 fi } require_docker_daemon() { if ! docker info >/dev/null 2>&1; then printf 'Docker daemon is not available. Please start Docker and re-run this script.\n' >&2 exit 1 fi } main() { require_root require_file "$ENV_FILE" require_file "$APP_DIR/Dockerfile" require_file "$APP_DIR/run.py" require_docker_daemon install -d -m 755 "$APP_DIR/instance" install -d -m 755 "$APP_DIR/instance/csv_previews" if [[ "$ALLOW_NON_ROOT" == "1" ]]; then chown -R "$CONTAINER_UID:$CONTAINER_GID" "$APP_DIR/instance" >/dev/null 2>&1 || true else chown -R "$CONTAINER_UID:$CONTAINER_GID" "$APP_DIR/instance" fi docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" "$APP_DIR" if docker ps -a --format '{{.Names}}' | grep -Fxq "$CONTAINER_NAME"; then docker rm -f "$CONTAINER_NAME" >/dev/null fi docker run -d \ --name "$CONTAINER_NAME" \ --env-file "$ENV_FILE" \ -e RUN_SEED_ALL="$RUN_SEED_ALL" \ -e HW_GUNICORN_PORT="$APP_PORT" \ -p "$HOST_PORT:$APP_PORT" \ -v "$APP_DIR/instance:/opt/hw/instance" \ -v "$CONFIG_DIR:/opt/hw.conf.d:ro" \ --restart unless-stopped \ "${IMAGE_NAME}:${IMAGE_TAG}" printf 'Container deployment completed.\n' printf 'Container: %s\n' "$CONTAINER_NAME" printf 'Image: %s:%s\n' "$IMAGE_NAME" "$IMAGE_TAG" printf 'Published port: %s -> %s\n' "$HOST_PORT" "$APP_PORT" } main "$@"