]> git.giorgioravera.it Git - network-manager.git/commitdiff
migrated to distroless & python entrypoint
authorGiorgio Ravera <giorgio.ravera@gmail.com>
Mon, 5 Jan 2026 15:02:54 +0000 (16:02 +0100)
committerGiorgio Ravera <giorgio.ravera@gmail.com>
Mon, 5 Jan 2026 15:02:54 +0000 (16:02 +0100)
Dockerfile
backend/main.py
entrypoint.py [new file with mode: 0755]
entrypoint.sh [deleted file]

index 63aadd3d687b17b1f55e8480257ce3cd88a46313..f70afbe4c8cfa6f4668de470f36a27b02d1dcdde 100644 (file)
@@ -1,8 +1,6 @@
 # ---------- STAGE 1: BUILD ----------
 FROM python:3.12-slim AS builder
 
-WORKDIR /app
-
 # Install build dependencies
 RUN apt-get update && \
     apt-get install -y --no-install-recommends sqlite3 && \
@@ -12,23 +10,40 @@ RUN apt-get update && \
 COPY requirements.txt .
 RUN pip install --prefix=/install -r requirements.txt
 
-# ---------- STAGE 2: RUNTIME ----------
-FROM python:3.12-slim
+WORKDIR /app
+
+# Copy backend, frontend, entrypoint
+COPY backend backend
+COPY frontend frontend
+COPY entrypoint.py entrypoint.py
+RUN chmod 755 entrypoint.py
 
-WORKDIR /var/www/network-manager
+# ---------- STAGE 2: DISTROLESS ----------
+FROM gcr.io/distroless/base-debian13
 
-# Copy only installed packages
+# Copy Python runtime from builder
+COPY --from=builder /usr/local /usr/local
+
+# Copy libs
+COPY --from=builder /lib/x86_64-linux-gnu/libsqlite3.so.0 /lib/x86_64-linux-gnu/
+COPY --from=builder /lib/x86_64-linux-gnu/libz.so.1 /lib/x86_64-linux-gnu/
+COPY --from=builder /lib/x86_64-linux-gnu/libbz2.so.1.0 /lib/x86_64-linux-gnu/
+COPY --from=builder /lib/x86_64-linux-gnu/liblzma.so.5 /lib/x86_64-linux-gnu/
+COPY --from=builder /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib/x86_64-linux-gnu/
+
+# Copy installed Python packages
 COPY --from=builder /install /usr/local
 
-# Copy backend and frontend
-COPY backend/ /var/www/network-manager/backend/
-COPY frontend/ /var/www/network-manager/frontend/
+WORKDIR /app
+
+# Copy application
+COPY --from=builder /app/backend backend
+COPY --from=builder /app/frontend frontend
+COPY --from=builder /app/entrypoint.py /usr/local/bin/entrypoint.py
 
-# Copy entrypoint
-COPY entrypoint.sh /entrypoint.sh
-RUN chmod +x /entrypoint.sh
+# Ensure Python sees the installed packages 
+ENV PYTHONPATH="/usr/local/lib/python3.12/site-packages"
 
-# Default environment variables
 ENV DB_PATH=/data/database.db
 ENV DB_RESET=0
 ENV HTTP_PORT=8000
@@ -40,6 +55,5 @@ ENV PUBLIC_IP=127.0.0.1
 # Expose the port dynamically
 EXPOSE ${HTTP_PORT}
 
-# Use the env var in the startup command
-ENTRYPOINT ["/entrypoint.sh"]
-CMD ["sh", "-c", "uvicorn backend.main:app --host 0.0.0.0 --port ${HTTP_PORT} --proxy-headers"]
+ENTRYPOINT ["/usr/local/bin/entrypoint.py"]
+CMD ["python3", "-u", "-m", "uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "8000", "--proxy-headers"]
index bbdd1d15fc045c15288b5c366eb5dd71b2b5a704..4d5cc8162d4dfdc4520acb1fbceabc0454a577c8 100644 (file)
@@ -70,7 +70,7 @@ def check_rate_limit(ip: str):
 # FRONTEND PATHS (absolute paths inside Docker)
 # ---------------------------------------------------------
 
-FRONTEND_DIR = "/var/www/network-manager/frontend"
+FRONTEND_DIR = "/app/frontend"
 
 # Homepage
 @app.get("/")
diff --git a/entrypoint.py b/entrypoint.py
new file mode 100755 (executable)
index 0000000..e115de0
--- /dev/null
@@ -0,0 +1,137 @@
+#!/usr/local/bin/python3
+
+import os
+import sys
+import sqlite3
+import subprocess
+
+# ================================
+# Variables
+# ================================
+DB_FILE = os.environ.get("DB_PATH", "database.db")
+DB_RESET = os.environ.get("DB_RESET", "0") == "1"
+DOMAIN = os.environ.get("DOMAIN", "example.com")
+PUBLIC_IP = os.environ.get("PUBLIC_IP", "127.0.0.1")
+
+IMAGE_NAME = "network-manager-distroless"
+IMAGE_VERSION = "1.0"
+
+# ================================
+# Create DB if needed
+# ================================
+def create_db():
+    # Reset database if requested
+    if DB_RESET and os.path.exists(DB_FILE):
+        print("INFO:     Removing existing database...")
+        os.remove(DB_FILE)
+
+    # Skip creation if DB already exists
+    if os.path.exists(DB_FILE):
+        print("INFO:     Database already exists. Nothing to do.")
+        return
+
+    print(f"INFO:     Creating database: {DB_FILE}.")
+
+    # Ensure directory exists
+    os.makedirs(os.path.dirname(DB_FILE) or ".", exist_ok=True)
+
+    conn = sqlite3.connect(DB_FILE)
+    cur = conn.cursor()
+
+    # Enable foreign keys
+    cur.execute("PRAGMA foreign_keys = ON;")
+
+    # GLOBAL SETTINGS
+    cur.execute("""
+        CREATE TABLE settings (
+            key TEXT PRIMARY KEY,
+            value TEXT
+        );
+    """)
+    cur.execute("INSERT INTO settings (key, value) VALUES (?, ?)", ("domain", DOMAIN))
+    cur.execute("INSERT INTO settings (key, value) VALUES (?, ?)", ("external_ipv4", PUBLIC_IP))
+
+    # HOSTS
+    cur.execute("""
+        CREATE TABLE hosts (
+            id INTEGER PRIMARY KEY AUTOINCREMENT,
+            name TEXT NOT NULL UNIQUE,
+            ipv4 TEXT,
+            ipv6 TEXT,
+            mac TEXT,
+            note TEXT,
+            ssl_enabled INTEGER NOT NULL DEFAULT 0
+        );
+    """)
+    cur.execute("CREATE INDEX idx_hosts_name ON hosts(name);")
+
+    # ALIASES
+    cur.execute("""
+        CREATE TABLE aliases (
+            id INTEGER PRIMARY KEY AUTOINCREMENT,
+            host_id INTEGER NOT NULL,
+            alias TEXT NOT NULL,
+            note TEXT,
+            ssl_enabled INTEGER NOT NULL DEFAULT 0,
+            FOREIGN KEY (host_id) REFERENCES hosts(id)
+        );
+    """)
+    cur.execute("CREATE INDEX idx_aliases_host ON aliases(host_id);")
+
+    # TXT RECORDS
+    cur.execute("""
+        CREATE TABLE txt_records (
+            id INTEGER PRIMARY KEY AUTOINCREMENT,
+            name TEXT NOT NULL,
+            value TEXT NOT NULL,
+            note TEXT,
+            host_id INTEGER,
+            FOREIGN KEY (host_id) REFERENCES hosts(id)
+        );
+    """)
+    cur.execute("CREATE INDEX idx_txt_host ON txt_records(host_id);")
+
+    conn.commit()
+    conn.close()
+
+    print(f"INFO:     Database initialized successfully for {DOMAIN}.")
+    print(f"INFO:     Public IP: {PUBLIC_IP}.")
+
+# ================================
+# Entry Point
+# ================================
+
+# Force flush
+sys.stdout.reconfigure(line_buffering=True)
+
+print(f"INFO:     Starting {IMAGE_NAME} docker image version {IMAGE_VERSION}.")
+
+
+# Parse arguments
+args = sys.argv[1:]
+i = 0
+while i < len(args):
+    if args[i] == "--reset":
+        DB_RESET = True
+        i += 1
+    elif args[i] == "--domain" and i + 1 < len(args):
+        DOMAIN = args[i + 1]
+        i += 2
+    elif args[i] == "--public-ip" and i + 1 < len(args):
+        PUBLIC_IP = args[i + 1]
+        i += 2
+    elif args[i] == "--":
+        args = args[i + 1:]
+        break
+    else:
+        break
+
+# Create DB
+create_db()
+
+# Continue to CMD
+if not args:
+    print("ERROR:      No command provided to exec.")
+    sys.exit(1)
+
+os.execvp(args[0], args)
diff --git a/entrypoint.sh b/entrypoint.sh
deleted file mode 100755 (executable)
index 098c29c..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-#!/bin/bash
-set -euo pipefail
-
-# ================================
-# Variables
-# ================================
-DB_FILE="${DB_PATH:-database.db}"
-DB_RESET="${DB_RESET:-0}"
-DOMAIN="${DOMAIN:-example.com}"
-PUBLIC_IP="${PUBLIC_IP:-127.0.0.1}"
-
-IMAGE_NAME="network-manager"
-IMAGE_VERSION="0.0"
-
-function create_db() {
-    # Reset database if requested
-    if [[ $DB_RESET -eq 1 && -f "$DB_FILE" ]]; then
-        echo "INFO:     [✓]] Removing existing database."
-        rm -f "$DB_FILE"
-    fi
-
-    # Skip creation if DB already exists
-    if [[ -f "$DB_FILE" ]]; then
-        echo "INFO:     [✓] Database already exists. Nothing to do."
-        return 0
-    fi
-
-    echo "INFO:     [✓] Creating database: $DB_FILE"
-
-    # Create DB with dynamic settings
-    sqlite3 "$DB_FILE" <<EOF
-PRAGMA foreign_keys = ON;
-
--- ============================================
---  GLOBAL SETTINGS
--- ============================================
-CREATE TABLE settings (
-    key TEXT PRIMARY KEY,
-    value TEXT
-);
-
-INSERT INTO settings (key, value) VALUES ('domain', '${DOMAIN}');
-INSERT INTO settings (key, value) VALUES ('external_ipv4', '${PUBLIC_IP}');
-
--- ============================================
---  HOSTS
--- ============================================
-CREATE TABLE hosts (
-    id INTEGER PRIMARY KEY AUTOINCREMENT,
-    name TEXT NOT NULL UNIQUE,
-    ipv4 TEXT,
-    ipv6 TEXT,
-    mac TEXT,
-    note TEXT,
-    ssl_enabled INTEGER NOT NULL DEFAULT 0
-);
-
-CREATE INDEX idx_hosts_name ON hosts(name);
-
--- ============================================
---  ALIASES
--- ============================================
-CREATE TABLE aliases (
-    id INTEGER PRIMARY KEY AUTOINCREMENT,
-    host_id INTEGER NOT NULL,
-    alias TEXT NOT NULL,
-    note TEXT,
-    ssl_enabled INTEGER NOT NULL DEFAULT 0,
-    FOREIGN KEY (host_id) REFERENCES hosts(id)
-);
-
-CREATE INDEX idx_aliases_host ON aliases(host_id);
-
--- ============================================
---  TXT RECORDS
--- ============================================
-CREATE TABLE txt_records (
-    id INTEGER PRIMARY KEY AUTOINCREMENT,
-    name TEXT NOT NULL,
-    value TEXT NOT NULL,
-    note TEXT,
-    host_id INTEGER,
-    FOREIGN KEY (host_id) REFERENCES hosts(id)
-);
-
-CREATE INDEX idx_txt_host ON txt_records(host_id);
-EOF
-
-    echo "INFO:     [✓] Database initialized successfully for $DOMAIN."
-    echo "INFO:     [✓] Public IP: $PUBLIC_IP."
-}
-
-# ================================
-# Entry Point
-# ================================
-
-echo "INFO:     Starting $IMAGE_NAME docker image version $IMAGE_VERSION."
-
-# Parse arguments
-while [[ $# -gt 0 ]]; do
-    case "$1" in
-        --reset)
-            DB_RESET=1
-            shift
-            ;;
-        --domain)
-            DOMAIN="$2"
-            shift 2
-            ;;
-        --public-ip)
-            PUBLIC_IP="$2"
-            shift 2
-            ;;
-        --)
-            shift
-            break
-            ;;
-        *)
-            break
-            ;;
-    esac
-done
-
-create_db
-
-# ================================
-# Continue to CMD
-# ================================
-exec "$@"