Refactor Docker setup: remove Nginx and TLS configurations, update service dependencies, and adjust health check endpoints
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -158,42 +158,17 @@ jobs:
|
||||
- name: Create release-only docker bundle
|
||||
run: |
|
||||
mkdir -p release-bundle
|
||||
mkdir -p release-bundle/docker/nginx
|
||||
cat > release-bundle/docker-compose.yml <<EOF
|
||||
services:
|
||||
nginx:
|
||||
image: nginx:1.27-alpine
|
||||
container_name: inventarsystem-nginx
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- app
|
||||
ports:
|
||||
- "${INVENTAR_HTTP_PORT:-80}:80"
|
||||
- "${INVENTAR_HTTPS_PORT:-443}:443"
|
||||
volumes:
|
||||
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
- ./certs:/etc/nginx/certs:ro
|
||||
|
||||
mongodb:
|
||||
image: mongo:7.0
|
||||
container_name: inventarsystem-mongodb
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- mongodb_data:/data/db
|
||||
healthcheck:
|
||||
test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
app:
|
||||
image: ${INVENTAR_APP_IMAGE:-ghcr.io/aiirondev/legendary-octo-garbanzo:latest}
|
||||
pull_policy: never
|
||||
image: ${INVENTAR_APP_IMAGE:-ghcr.io/aiirondev/legendary-octo-garbanzo:${{ steps.meta.outputs.tag }}}
|
||||
container_name: inventarsystem-app
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${INVENTAR_HTTP_PORT:-10000}:8000"
|
||||
depends_on:
|
||||
mongodb:
|
||||
condition: service_healthy
|
||||
- mongodb
|
||||
- redis
|
||||
environment:
|
||||
INVENTAR_MONGODB_HOST: mongodb
|
||||
INVENTAR_MONGODB_PORT: "27017"
|
||||
@@ -211,6 +186,33 @@ jobs:
|
||||
- app_backups:/data/backups
|
||||
- app_logs:/data/logs
|
||||
|
||||
mongodb:
|
||||
image: mongo:7.0
|
||||
container_name: inventarsystem-mongodb
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- mongodb_data:/data/db
|
||||
healthcheck:
|
||||
test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: inventarsystem-redis
|
||||
restart: unless-stopped
|
||||
command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru
|
||||
ports:
|
||||
- "6379:6379"
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
mongodb_data:
|
||||
app_uploads:
|
||||
@@ -219,9 +221,9 @@ jobs:
|
||||
app_qrcodes:
|
||||
app_backups:
|
||||
app_logs:
|
||||
redis_data:
|
||||
EOF
|
||||
|
||||
cp docker/nginx/default.conf release-bundle/docker/nginx/default.conf
|
||||
cp start.sh release-bundle/start.sh
|
||||
cp stop.sh release-bundle/stop.sh
|
||||
cp restart.sh release-bundle/restart.sh
|
||||
@@ -232,7 +234,6 @@ jobs:
|
||||
|
||||
# Multitenant scripts & docs
|
||||
cp docker-compose-multitenant.yml release-bundle/docker-compose-multitenant.yml
|
||||
cp docker/nginx/multitenant.conf release-bundle/docker/nginx/multitenant.conf
|
||||
cp manage-tenant.sh release-bundle/manage-tenant.sh
|
||||
cp run-tenant-cmd.sh release-bundle/run-tenant-cmd.sh
|
||||
cp MULTITENANT_DEPLOYMENT.md release-bundle/MULTITENANT_DEPLOYMENT.md
|
||||
|
||||
@@ -1,28 +1,14 @@
|
||||
# Multi-Tenant Optimized Docker Compose
|
||||
# Supports running multiple isolated app instances per subdomain
|
||||
# Supports running multiple isolated app instances with direct Docker host port binding
|
||||
# Each instance: ~50MB base + 20-30MB per 20 users
|
||||
#
|
||||
# Usage:
|
||||
# docker-compose -f docker-compose-multitenant.yml up -d
|
||||
#
|
||||
# Scale example: To support 10 tenants with 20 users each:
|
||||
# docker-compose -f docker-compose-multitenant.yml up -d --scale app=10
|
||||
# Example: Start the stack and expose the app on host port 10000
|
||||
# INVENTAR_HTTP_PORT=10000 docker-compose -f docker-compose-multitenant.yml up -d
|
||||
|
||||
services:
|
||||
cloudflared:
|
||||
image: cloudflare/cloudflared:latest
|
||||
container_name: cloudflared
|
||||
restart: unless-stopped
|
||||
command: tunnel run homeserver # 'homeserver' must match your tunnel name
|
||||
volumes:
|
||||
- ./docker/cloudflared/config.yml:/etc/cloudflared/config.yml:ro
|
||||
- /etc/cloudflared/credentials.json:/etc/cloudflared/credentials.json:ro
|
||||
depends_on:
|
||||
nginx:
|
||||
condition: service_started
|
||||
networks:
|
||||
- inventar-net
|
||||
|
||||
# Management Container for multi-tenant scripts
|
||||
tenant-manager:
|
||||
image: docker:cli
|
||||
@@ -35,33 +21,6 @@ services:
|
||||
- .:/workspace
|
||||
entrypoint: ["sh", "-c", "cd /workspace && ./manage-tenant.sh \"$$@\"", "--"]
|
||||
|
||||
nginx:
|
||||
image: nginx:1.27-alpine
|
||||
container_name: inventarsystem-nginx
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
app:
|
||||
condition: service_started
|
||||
redis:
|
||||
condition: service_started
|
||||
ports:
|
||||
- "${INVENTAR_HTTP_PORT:-10000}:80"
|
||||
- "${INVENTAR_HTTPS_PORT:-10001}:8000"
|
||||
volumes:
|
||||
- ./docker/nginx/multitenant.conf:/etc/nginx/conf.d/default.conf
|
||||
- ./certs:/etc/nginx/certs:ro
|
||||
- ./docker/nginx/acme:/etc/nginx/acme:ro
|
||||
networks:
|
||||
- inventar-net
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "-O-", "http://localhost/health"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
environment:
|
||||
NGINX_WORKER_PROCESSES: auto
|
||||
NGINX_WORKER_CONNECTIONS: 1024
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: inventarsystem-redis
|
||||
@@ -115,6 +74,8 @@ services:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- "${INVENTAR_HTTP_PORT:-10000}:8000"
|
||||
networks:
|
||||
- inventar-net
|
||||
expose:
|
||||
|
||||
@@ -38,11 +38,6 @@ case "$COMMAND" in
|
||||
exit 1
|
||||
fi
|
||||
echo "Adding new tenant '$TENANT_ID'..."
|
||||
# Add Nginx configuration
|
||||
if [ -f "docker/nginx/multitenant.conf" ]; then
|
||||
echo "Assuming dynamic routing based on subdomain ($TENANT_ID)..."
|
||||
fi
|
||||
|
||||
# Initialize tenant database via Python inside container
|
||||
echo "Initializing database for $TENANT_ID..."
|
||||
APP_CONTAINER=$(docker ps -qf "name=app" | head -n 1)
|
||||
|
||||
@@ -16,9 +16,7 @@ fi
|
||||
|
||||
NUITKA_BUILD_VALUE="0"
|
||||
HTTP_PORT_VALUE="10000"
|
||||
HTTPS_PORT_VALUE="10001"
|
||||
DEFAULT_TENANT_PORT_START="${INVENTAR_TENANT_PORT_START:-10000}"
|
||||
DEFAULT_TENANT_TLS_OFFSET="${INVENTAR_TENANT_TLS_OFFSET:-1}"
|
||||
CRON_SETUP_VALUE="${INVENTAR_SETUP_CRON:-1}"
|
||||
APP_IMAGE_VALUE="${INVENTAR_APP_IMAGE:-$APP_IMAGE_REPO:latest}"
|
||||
COMPOSE_FILE="docker-compose-multitenant.yml"
|
||||
@@ -231,81 +229,6 @@ setup_scheduled_jobs() {
|
||||
echo "Nightly auto-update scheduled at 03:00"
|
||||
}
|
||||
|
||||
ensure_tls_certificates() {
|
||||
local cert_dir cert_path key_path cn
|
||||
cert_dir="$SCRIPT_DIR/certs"
|
||||
cert_path="$cert_dir/inventarsystem.crt"
|
||||
key_path="$cert_dir/inventarsystem.key"
|
||||
|
||||
mkdir -p "$cert_dir"
|
||||
|
||||
if [ -f "$cert_path" ] && [ -f "$key_path" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
cn="${TLS_CN:-localhost}"
|
||||
echo "No TLS certificates found. Generating self-signed certificate for CN=$cn"
|
||||
|
||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||||
-keyout "$key_path" \
|
||||
-out "$cert_path" \
|
||||
-subj "/C=DE/ST=NA/L=NA/O=Inventarsystem/OU=IT/CN=$cn" >/dev/null 2>&1
|
||||
|
||||
chmod 600 "$key_path"
|
||||
chmod 644 "$cert_path"
|
||||
}
|
||||
|
||||
ensure_nginx_config_mount_source() {
|
||||
local nginx_dir config_path backup_path
|
||||
nginx_dir="$SCRIPT_DIR/docker/nginx"
|
||||
config_path="$nginx_dir/default.conf"
|
||||
|
||||
mkdir -p "$nginx_dir"
|
||||
|
||||
if [ -d "$config_path" ]; then
|
||||
backup_path="${config_path}.dir.$(date +%Y%m%d-%H%M%S).bak"
|
||||
mv "$config_path" "$backup_path"
|
||||
echo "Warning: moved unexpected directory $config_path to $backup_path"
|
||||
fi
|
||||
|
||||
if [ ! -f "$config_path" ]; then
|
||||
cat > "$config_path" <<'EOF'
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name _;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/inventarsystem.crt;
|
||||
ssl_certificate_key /etc/nginx/certs/inventarsystem.key;
|
||||
|
||||
client_max_body_size 50M;
|
||||
|
||||
location / {
|
||||
proxy_pass http://app:8000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 300;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
default_type text/html;
|
||||
return 200 '<!doctype html><html><head><meta charset="utf-8"><title>Server Error</title></head><body><h1>Server Error</h1><p>The service is temporarily unavailable.</p></body></html>';
|
||||
}
|
||||
}
|
||||
EOF
|
||||
echo "Recreated missing nginx config at $config_path"
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_runtime_config_json() {
|
||||
local config_path backup_path
|
||||
config_path="$SCRIPT_DIR/config.json"
|
||||
@@ -322,7 +245,7 @@ ensure_runtime_config_json() {
|
||||
"ver": "2.6.5",
|
||||
"dbg": false,
|
||||
"host": "0.0.0.0",
|
||||
"port": 443,
|
||||
"port": 8000,
|
||||
"mongodb": {
|
||||
"host": "mongodb",
|
||||
"port": 27017,
|
||||
@@ -443,16 +366,6 @@ resolve_app_image() {
|
||||
fi
|
||||
}
|
||||
|
||||
configure_cloudflared_profile() {
|
||||
if [ -f /etc/cloudflared/credentials.json ]; then
|
||||
COMPOSE_PROFILES_VALUE="cloudflare"
|
||||
echo "Cloudflared tunnel: enabled (homeserver)"
|
||||
else
|
||||
COMPOSE_PROFILES_VALUE=""
|
||||
echo "Cloudflared tunnel: disabled (missing /etc/cloudflared/credentials.json)"
|
||||
fi
|
||||
}
|
||||
|
||||
port_in_use() {
|
||||
local port="$1"
|
||||
|
||||
@@ -471,89 +384,25 @@ find_free_port() {
|
||||
echo "$port"
|
||||
}
|
||||
|
||||
stack_owns_host_port() {
|
||||
local requested_port="$1"
|
||||
local container_port="$2"
|
||||
local mapped_port
|
||||
|
||||
mapped_port="$(docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" port nginx "$container_port" 2>/dev/null | tail -n1 || true)"
|
||||
if [ -z "$mapped_port" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
mapped_port="${mapped_port##*:}"
|
||||
[ "$mapped_port" = "$requested_port" ]
|
||||
}
|
||||
|
||||
stop_host_nginx_services() {
|
||||
local stopped_any=false
|
||||
local service_name
|
||||
|
||||
if ! command -v systemctl >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
while IFS= read -r service_name; do
|
||||
[ -z "$service_name" ] && continue
|
||||
echo "Stopping host service $service_name to free web ports..."
|
||||
$SUDO systemctl stop "$service_name" >/dev/null 2>&1 || true
|
||||
stopped_any=true
|
||||
done < <(systemctl list-units --type=service --state=active --no-pager 2>/dev/null | awk '{print $1}' | grep -E '(^nginx\.service$|nginx)' || true)
|
||||
|
||||
if [ "$stopped_any" = true ]; then
|
||||
sleep 2
|
||||
fi
|
||||
|
||||
if [ "$stopped_any" = true ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
find_free_port_pair() {
|
||||
local port="${1:-$DEFAULT_TENANT_PORT_START}"
|
||||
|
||||
while port_in_use "$port" || port_in_use "$((port + DEFAULT_TENANT_TLS_OFFSET))"; do
|
||||
port=$((port + 2))
|
||||
done
|
||||
|
||||
echo "$port"
|
||||
}
|
||||
|
||||
configure_host_ports() {
|
||||
local requested_http requested_https base_port
|
||||
local requested_http
|
||||
|
||||
requested_http=""
|
||||
requested_https=""
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
requested_http="$(awk -F= '/^INVENTAR_HTTP_PORT=/{print $2}' "$ENV_FILE" | tr -d ' ' || true)"
|
||||
requested_https="$(awk -F= '/^INVENTAR_HTTPS_PORT=/{print $2}' "$ENV_FILE" | tr -d ' ' || true)"
|
||||
fi
|
||||
|
||||
if [ -z "$requested_http" ]; then
|
||||
requested_http="$DEFAULT_TENANT_PORT_START"
|
||||
fi
|
||||
if [ -z "$requested_https" ]; then
|
||||
requested_https="$((requested_http + DEFAULT_TENANT_TLS_OFFSET))"
|
||||
fi
|
||||
|
||||
if stack_owns_host_port "$requested_http" "80" && stack_owns_host_port "$requested_https" "443"; then
|
||||
if ! port_in_use "$requested_http"; then
|
||||
HTTP_PORT_VALUE="$requested_http"
|
||||
HTTPS_PORT_VALUE="$requested_https"
|
||||
return
|
||||
fi
|
||||
|
||||
if ! port_in_use "$requested_http" && ! port_in_use "$requested_https"; then
|
||||
HTTP_PORT_VALUE="$requested_http"
|
||||
HTTPS_PORT_VALUE="$requested_https"
|
||||
return
|
||||
fi
|
||||
|
||||
base_port="$(find_free_port_pair "$DEFAULT_TENANT_PORT_START")"
|
||||
HTTP_PORT_VALUE="$base_port"
|
||||
HTTPS_PORT_VALUE="$((base_port + DEFAULT_TENANT_TLS_OFFSET))"
|
||||
echo "Tenant host ports are already occupied. Assigned new tenant ports: $HTTP_PORT_VALUE and $HTTPS_PORT_VALUE"
|
||||
HTTP_PORT_VALUE="$(find_free_port "$DEFAULT_TENANT_PORT_START")"
|
||||
echo "Host port $requested_http is already occupied. Assigned new tenant port: $HTTP_PORT_VALUE"
|
||||
}
|
||||
|
||||
ensure_min_docker_disk_space() {
|
||||
@@ -591,7 +440,6 @@ write_env_file() {
|
||||
cat > "$ENV_FILE" <<EOF
|
||||
NUITKA_BUILD=$NUITKA_BUILD_VALUE
|
||||
INVENTAR_HTTP_PORT=$HTTP_PORT_VALUE
|
||||
INVENTAR_HTTPS_PORT=$HTTPS_PORT_VALUE
|
||||
INVENTAR_APP_IMAGE=$APP_IMAGE_VALUE
|
||||
EOF
|
||||
}
|
||||
@@ -621,10 +469,10 @@ verify_stack_health() {
|
||||
for _ in $(seq 1 60); do
|
||||
running_services="$(docker compose "${compose_args[@]}" ps --status running --services 2>/dev/null || true)"
|
||||
if printf '%s\n' "$running_services" | grep -Fxq app && \
|
||||
printf '%s\n' "$running_services" | grep -Fxq nginx && \
|
||||
printf '%s\n' "$running_services" | grep -Fxq redis && \
|
||||
printf '%s\n' "$running_services" | grep -Fxq mongodb; then
|
||||
if docker compose "${compose_args[@]}" exec -T app python3 -c "import flask, pymongo" >/dev/null 2>&1; then
|
||||
if curl -kfsSL "https://127.0.0.1:$HTTPS_PORT_VALUE/health" >/dev/null 2>&1; then
|
||||
if curl -fsS "http://127.0.0.1:$HTTP_PORT_VALUE/health" >/dev/null 2>&1; then
|
||||
echo "Health check passed."
|
||||
return 0
|
||||
fi
|
||||
@@ -637,8 +485,8 @@ verify_stack_health() {
|
||||
if [[ $retry_count -eq 0 ]]; then
|
||||
echo "Health check failed. Attempting to restart containers..."
|
||||
docker compose "${compose_args[@]}" ps || true
|
||||
docker compose "${compose_args[@]}" logs --tail=120 app nginx mongodb || true
|
||||
docker compose "${compose_args[@]}" restart app nginx mongodb
|
||||
docker compose "${compose_args[@]}" logs --tail=120 app redis mongodb || true
|
||||
docker compose "${compose_args[@]}" restart app redis mongodb
|
||||
sleep 3
|
||||
((retry_count++))
|
||||
else
|
||||
@@ -649,7 +497,7 @@ verify_stack_health() {
|
||||
# Final failure
|
||||
echo "Error: stack health check failed after restart attempt."
|
||||
docker compose "${compose_args[@]}" ps || true
|
||||
docker compose "${compose_args[@]}" logs --tail=120 app nginx mongodb || true
|
||||
docker compose "${compose_args[@]}" logs --tail=120 app redis mongodb || true
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -657,13 +505,10 @@ parse_args "$@"
|
||||
|
||||
ensure_runtime_dependencies
|
||||
setup_boot_autostart_service
|
||||
ensure_tls_certificates
|
||||
ensure_nginx_config_mount_source
|
||||
ensure_runtime_config_json
|
||||
setup_scheduled_jobs
|
||||
configure_nuitka_mode
|
||||
resolve_app_image
|
||||
configure_cloudflared_profile
|
||||
configure_host_ports
|
||||
ensure_min_docker_disk_space
|
||||
ensure_app_image_loaded
|
||||
@@ -688,4 +533,4 @@ fi
|
||||
verify_stack_health
|
||||
|
||||
echo "Stack started."
|
||||
echo "Open: https://<server-ip>:$HTTPS_PORT_VALUE"
|
||||
echo "Open: http://<server-ip>:$HTTP_PORT_VALUE"
|
||||
|
||||
@@ -76,81 +76,6 @@ ensure_runtime_dependencies() {
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_tls_certificates() {
|
||||
local cert_dir cert_path key_path cn
|
||||
cert_dir="$PROJECT_DIR/certs"
|
||||
cert_path="$cert_dir/inventarsystem.crt"
|
||||
key_path="$cert_dir/inventarsystem.key"
|
||||
|
||||
mkdir -p "$cert_dir"
|
||||
|
||||
if [ -f "$cert_path" ] && [ -f "$key_path" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
cn="${TLS_CN:-localhost}"
|
||||
log_message "No TLS certificates found. Generating self-signed certificate for CN=$cn"
|
||||
|
||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||||
-keyout "$key_path" \
|
||||
-out "$cert_path" \
|
||||
-subj "/C=DE/ST=NA/L=NA/O=Inventarsystem/OU=IT/CN=$cn" >/dev/null 2>&1
|
||||
|
||||
chmod 600 "$key_path"
|
||||
chmod 644 "$cert_path"
|
||||
}
|
||||
|
||||
ensure_nginx_config_mount_source() {
|
||||
local nginx_dir config_path backup_path
|
||||
nginx_dir="$PROJECT_DIR/docker/nginx"
|
||||
config_path="$nginx_dir/default.conf"
|
||||
|
||||
mkdir -p "$nginx_dir"
|
||||
|
||||
if [ -d "$config_path" ]; then
|
||||
backup_path="${config_path}.dir.$(date +%Y%m%d-%H%M%S).bak"
|
||||
mv "$config_path" "$backup_path"
|
||||
log_message "WARNING: Moved unexpected directory $config_path to $backup_path"
|
||||
fi
|
||||
|
||||
if [ ! -f "$config_path" ]; then
|
||||
cat > "$config_path" <<'EOF'
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name _;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/inventarsystem.crt;
|
||||
ssl_certificate_key /etc/nginx/certs/inventarsystem.key;
|
||||
|
||||
client_max_body_size 50M;
|
||||
|
||||
location / {
|
||||
proxy_pass http://app:8000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 300;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
default_type text/html;
|
||||
return 200 '<!doctype html><html><head><meta charset="utf-8"><title>Server Error</title></head><body><h1>Server Error</h1><p>The service is temporarily unavailable.</p></body></html>';
|
||||
}
|
||||
}
|
||||
EOF
|
||||
log_message "Recreated missing nginx config at $config_path"
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_min_root_disk_space() {
|
||||
local available_kb available_mb
|
||||
|
||||
@@ -408,9 +333,7 @@ download_and_extract_bundle() {
|
||||
tar -xzf "$archive" -C "$tmp_dir"
|
||||
|
||||
# The bundle must contain docker deployment files only.
|
||||
mkdir -p "$PROJECT_DIR/docker/nginx"
|
||||
cp -f "$tmp_dir/docker-compose.yml" "$PROJECT_DIR/docker-compose.yml"
|
||||
cp -f "$tmp_dir/docker/nginx/default.conf" "$PROJECT_DIR/docker/nginx/default.conf"
|
||||
cp -f "$tmp_dir/start.sh" "$PROJECT_DIR/start.sh"
|
||||
cp -f "$tmp_dir/stop.sh" "$PROJECT_DIR/stop.sh"
|
||||
|
||||
@@ -426,9 +349,6 @@ download_and_extract_bundle() {
|
||||
if [ -f "$tmp_dir/docker-compose-multitenant.yml" ]; then
|
||||
cp -f "$tmp_dir/docker-compose-multitenant.yml" "$PROJECT_DIR/docker-compose-multitenant.yml"
|
||||
fi
|
||||
if [ -f "$tmp_dir/docker/nginx/multitenant.conf" ]; then
|
||||
cp -f "$tmp_dir/docker/nginx/multitenant.conf" "$PROJECT_DIR/docker/nginx/multitenant.conf"
|
||||
fi
|
||||
if [ -f "$tmp_dir/manage-tenant.sh" ]; then
|
||||
cp -f "$tmp_dir/manage-tenant.sh" "$PROJECT_DIR/manage-tenant.sh"
|
||||
fi
|
||||
@@ -470,7 +390,6 @@ deploy() {
|
||||
cat > "$ENV_FILE" <<EOF
|
||||
NUITKA_BUILD=0
|
||||
INVENTAR_HTTP_PORT=10000
|
||||
INVENTAR_HTTPS_PORT=10001
|
||||
INVENTAR_APP_IMAGE=$app_image
|
||||
EOF
|
||||
elif grep -q '^INVENTAR_APP_IMAGE=' "$ENV_FILE"; then
|
||||
@@ -489,27 +408,27 @@ EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
docker compose -f "$compose_path" --env-file "$ENV_FILE" pull nginx mongodb >> "$LOG_FILE" 2>&1
|
||||
docker compose -f "$compose_path" --env-file "$ENV_FILE" pull app mongodb >> "$LOG_FILE" 2>&1
|
||||
docker compose -f "$compose_path" --env-file "$ENV_FILE" up -d --remove-orphans >> "$LOG_FILE" 2>&1
|
||||
docker tag "$app_image" "$APP_IMAGE_REPO:latest" >> "$LOG_FILE" 2>&1 || true
|
||||
}
|
||||
|
||||
verify_stack_health() {
|
||||
local compose_args running_services
|
||||
local https_port
|
||||
local http_port
|
||||
compose_args=(-f "$PROJECT_DIR/$COMPOSE_FILE" --env-file "$ENV_FILE")
|
||||
https_port="$(awk -F= '/^INVENTAR_HTTPS_PORT=/{print $2}' "$ENV_FILE" | tr -d ' ')"
|
||||
if [ -z "$https_port" ]; then
|
||||
https_port="443"
|
||||
http_port="$(awk -F= '/^INVENTAR_HTTP_PORT=/{print $2}' "$ENV_FILE" | tr -d ' ')"
|
||||
if [ -z "$http_port" ]; then
|
||||
http_port="10000"
|
||||
fi
|
||||
|
||||
for _ in $(seq 1 60); do
|
||||
running_services="$(docker compose "${compose_args[@]}" ps --status running --services 2>/dev/null || true)"
|
||||
if printf '%s\n' "$running_services" | grep -Fxq app && \
|
||||
printf '%s\n' "$running_services" | grep -Fxq nginx && \
|
||||
printf '%s\n' "$running_services" | grep -Fxq redis && \
|
||||
printf '%s\n' "$running_services" | grep -Fxq mongodb; then
|
||||
# Primary check: health endpoint responds (most reliable)
|
||||
if curl -kfsSL "https://127.0.0.1:$https_port/health" >/dev/null 2>&1; then
|
||||
if curl -fsS "http://127.0.0.1:$http_port/health" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
@@ -517,7 +436,7 @@ verify_stack_health() {
|
||||
done
|
||||
|
||||
docker compose "${compose_args[@]}" ps >> "$LOG_FILE" 2>&1 || true
|
||||
docker compose "${compose_args[@]}" logs --tail=120 app nginx mongodb >> "$LOG_FILE" 2>&1 || true
|
||||
docker compose "${compose_args[@]}" logs --tail=120 app redis mongodb >> "$LOG_FILE" 2>&1 || true
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -545,8 +464,6 @@ main() {
|
||||
cleanup_server_space
|
||||
|
||||
ensure_runtime_dependencies
|
||||
ensure_tls_certificates
|
||||
ensure_nginx_config_mount_source
|
||||
|
||||
require_cmd curl
|
||||
require_cmd tar
|
||||
|
||||
Reference in New Issue
Block a user