Skip to content

Commit 29c7491

Browse files
DAdjadjclaude
andcommitted
Fix self-update: recreate container with docker run instead of compose
docker compose up -d fails from inside the container because it can't stop itself (name conflict). Now reads mount/port config from the running container and uses docker stop + rm + run to recreate. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 9f685d3 commit 29c7491

File tree

1 file changed

+27
-4
lines changed

1 file changed

+27
-4
lines changed

app/web/server.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -764,10 +764,33 @@ def update_run():
764764
if image_is_same and container_current:
765765
return jsonify({"up_to_date": True})
766766
logger.info("Recreating container (new_image=%s, container_outdated=%s)", not image_is_same, not container_current)
767-
subprocess.Popen(
768-
["sh", "-c", "sleep 2 && cd /compose && docker compose up -d"],
769-
start_new_session=True
770-
)
767+
# docker compose up -d can't work from inside the container because it
768+
# can't stop itself. Read mount/port config from the running container
769+
# and recreate with docker run.
770+
import json as _json
771+
mounts_json = subprocess.run(
772+
["docker", "inspect", "--format", "{{json .Mounts}}", CONTAINER_NAME],
773+
capture_output=True, text=True, timeout=5
774+
).stdout.strip()
775+
ports_json = subprocess.run(
776+
["docker", "inspect", "--format", "{{json .HostConfig.PortBindings}}", CONTAINER_NAME],
777+
capture_output=True, text=True, timeout=5
778+
).stdout.strip()
779+
vol_args = []
780+
for m in _json.loads(mounts_json or "[]"):
781+
ro = ":ro" if not m.get("RW", True) else ""
782+
vol_args += ["-v", f"{m['Source']}:{m['Destination']}{ro}"]
783+
port_args = []
784+
for container_port, bindings in _json.loads(ports_json or "{}").items():
785+
for b in (bindings or []):
786+
host_port = b.get("HostPort", "")
787+
if host_port:
788+
port_args += ["-p", f"{host_port}:{container_port.split('/')[0]}"]
789+
run_parts = ["docker", "run", "-d", "--name", CONTAINER_NAME, "--restart", "unless-stopped"] + port_args + vol_args + [IMAGE_NAME]
790+
run_cmd = " ".join(run_parts)
791+
full_cmd = f"sleep 2 && docker stop {CONTAINER_NAME} && docker rm {CONTAINER_NAME} && {run_cmd}"
792+
logger.info("Update command: %s", full_cmd)
793+
subprocess.Popen(["sh", "-c", full_cmd], start_new_session=True)
771794
db.set_setting("update_available", "0")
772795
return jsonify({"updating": True})
773796
except FileNotFoundError:

0 commit comments

Comments
 (0)