tuanchris пре 2 месеци
родитељ
комит
02b92659cb
4 измењених фајлова са 42 додато и 17 уклоњено
  1. 10 0
      Dockerfile
  2. 5 1
      docker-compose.yml
  3. 14 14
      main.py
  4. 13 2
      modules/update/update_manager.py

+ 10 - 0
Dockerfile

@@ -15,8 +15,18 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
         python3-dev python3-pip \
         libgpiod2 libgpiod-dev \
         scons \
+        systemd \
+        # Docker CLI for container self-restart/update
+        ca-certificates curl gnupg \
     && pip install --upgrade pip \
     && pip install --no-cache-dir -r requirements.txt \
+    # Install Docker CLI from official Docker repo
+    && install -m 0755 -d /etc/apt/keyrings \
+    && curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg \
+    && chmod a+r /etc/apt/keyrings/docker.gpg \
+    && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable" > /etc/apt/sources.list.d/docker.list \
+    && apt-get update \
+    && apt-get install -y --no-install-recommends docker-ce-cli docker-compose-plugin \
     && apt-get purge -y gcc g++ make scons \
     && rm -rf /var/lib/apt/lists/*
 

+ 5 - 1
docker-compose.yml

@@ -6,12 +6,16 @@ services:
     # ports:
     #   - "8080:8080" # Map port 8080 of the container to 8080 of the host (access via http://localhost:8080)
     network_mode: "host" # Use host network for device access
+    environment:
+      # Pass host project directory for Docker commands from inside container
+      - HOST_PROJECT_DIR=${PWD}
     volumes:
       - .:/app
+      # Mount Docker socket to allow container to restart itself
+      - /var/run/docker.sock:/var/run/docker.sock
       # Mount timezone file from host for Still Sands scheduling
       - /etc/timezone:/etc/host-timezone:ro
       # Mount systemd to allow host shutdown
-      - /bin/systemctl:/bin/systemctl:ro
       - /run/systemd/system:/run/systemd/system:ro
       - /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket:ro
       - /sys/fs/cgroup:/sys/fs/cgroup:ro

+ 14 - 14
main.py

@@ -1858,7 +1858,7 @@ async def get_app_name():
 @app.post("/api/app-name", deprecated=True, tags=["settings-deprecated"])
 async def set_app_name(request: dict):
     """DEPRECATED: Use PATCH /api/settings instead. Update application name."""
-    app_name = request.get("app_name", "").strip()
+    app_name = (request.get("app_name") or "").strip()
     if not app_name:
         app_name = "Dune Weaver"  # Reset to default if empty
 
@@ -2055,14 +2055,14 @@ async def set_mqtt_config(request: dict):
     try:
         # Update state with new values
         state.mqtt_enabled = request.get("enabled", False)
-        state.mqtt_broker = request.get("broker", "").strip()
-        state.mqtt_port = int(request.get("port", 1883))
-        state.mqtt_username = request.get("username", "").strip()
-        state.mqtt_password = request.get("password", "").strip()
-        state.mqtt_client_id = request.get("client_id", "dune_weaver").strip()
-        state.mqtt_discovery_prefix = request.get("discovery_prefix", "homeassistant").strip()
-        state.mqtt_device_id = request.get("device_id", "dune_weaver").strip()
-        state.mqtt_device_name = request.get("device_name", "Dune Weaver").strip()
+        state.mqtt_broker = (request.get("broker") or "").strip()
+        state.mqtt_port = int(request.get("port") or 1883)
+        state.mqtt_username = (request.get("username") or "").strip()
+        state.mqtt_password = (request.get("password") or "").strip()
+        state.mqtt_client_id = (request.get("client_id") or "dune_weaver").strip()
+        state.mqtt_discovery_prefix = (request.get("discovery_prefix") or "homeassistant").strip()
+        state.mqtt_device_id = (request.get("device_id") or "dune_weaver").strip()
+        state.mqtt_device_name = (request.get("device_name") or "Dune Weaver").strip()
 
         # Validate required fields when enabled
         if state.mqtt_enabled and not state.mqtt_broker:
@@ -2096,11 +2096,11 @@ async def test_mqtt_connection(request: dict):
     """Test MQTT connection with provided settings."""
     import paho.mqtt.client as mqtt_client
 
-    broker = request.get("broker", "").strip()
-    port = int(request.get("port", 1883))
-    username = request.get("username", "").strip()
-    password = request.get("password", "").strip()
-    client_id = request.get("client_id", "dune_weaver_test").strip()
+    broker = (request.get("broker") or "").strip()
+    port = int(request.get("port") or 1883)
+    username = (request.get("username") or "").strip()
+    password = (request.get("password") or "").strip()
+    client_id = (request.get("client_id") or "dune_weaver_test").strip()
 
     if not broker:
         return JSONResponse(

+ 13 - 2
modules/update/update_manager.py

@@ -76,8 +76,19 @@ def update_software():
         return False, error_msg, error_log
 
     run_command(["git", "checkout", latest_remote_tag, '--force'], f"Failed to checkout version {latest_remote_tag}")
-    run_command(["docker", "compose", "pull"], "Failed to fetch Docker containers")
-    run_command(["docker", "compose", "up", "-d"], "Failed to restart Docker containers")
+
+    # Get host project directory for docker compose commands
+    # When running inside a container, we need to use the host path for docker compose
+    host_project_dir = os.environ.get("HOST_PROJECT_DIR")
+    if host_project_dir:
+        compose_cmd = ["docker", "compose", "-f", f"{host_project_dir}/docker-compose.yml"]
+        logger.info(f"Using host project directory: {host_project_dir}")
+    else:
+        compose_cmd = ["docker", "compose"]
+        logger.warning("HOST_PROJECT_DIR not set, using default docker compose")
+
+    run_command(compose_cmd + ["pull"], "Failed to fetch Docker containers")
+    run_command(compose_cmd + ["up", "-d"], "Failed to restart Docker containers")
 
     update_status = check_git_updates()