From f4802ece4dd853403ded8dd527568911f2970c8b Mon Sep 17 00:00:00 2001 From: Alex Blank Date: Thu, 28 May 2026 22:51:15 +0200 Subject: [PATCH] fix: build manifest image during create_instance instead of start_instance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The manifest-based flow was building the Docker image inside start_instance, which made the start HTTP request take 3-5 minutes (downloading ubuntu:24.04, apt-get update, installing packages, Node.js, npm packages). The frontend showed a spinner forever because the HTTP request was still pending. Move the image build to create_instance (same pattern as dockerfile types): 1. create_instance now compiles Dockerfile + entrypoint and builds the image 2. start_instance sees the image already exists and skips the build 3. Start is fast — just docker compose up + health checks This matches the UX expectation: creation has a spinner (can be slow), start should be quick. --- apps/api/src/api/tool_instances.py | 35 +++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/apps/api/src/api/tool_instances.py b/apps/api/src/api/tool_instances.py index c3c3b74..eb04078 100644 --- a/apps/api/src/api/tool_instances.py +++ b/apps/api/src/api/tool_instances.py @@ -748,7 +748,7 @@ services: write_compose_file(instance_dir, compose_content) elif tool_type.definition_type == "manifest": - # Manifest-based: generate compose from manifest definition + # Manifest-based: build image and generate compose from src.models.tool_definition_manifest import ToolDefinitionManifest manifest_def = await session.get( @@ -772,6 +772,39 @@ services: image_tag = compute_image_tag(tool_type.name, manifest) + # Build image during creation so start is fast + dockerfile = compile_dockerfile(manifest) + entrypoint = compile_entrypoint(manifest) + build_ctx = { + "Dockerfile": dockerfile, + ".headquarter/entrypoint.sh": entrypoint, + } + + returncode, stdout, stderr = await asyncio.to_thread( + build_image, + instance_dir=instance_dir, + dockerfile=dockerfile, + tag=image_tag, + build_context=build_ctx, + ) + + if returncode != 0: + logger.error( + "Failed to build image for manifest instance %s: %s", + instance_name, + stderr, + ) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Failed to build Docker image: {stderr[:500]}", + ) + + logger.info( + "Built manifest image %s for instance %s", + image_tag, + instance_name, + ) + variables = { "IMAGE_TAG": image_tag, "INSTANCE_NAME": instance_name.lower(),