You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Three related fixes for the template-deploy path:
1) PARSER (latent bug since forever): the Docker-API deploy returned
"(HTTP code 400) bad parameter - no command specified" for any template
with a top-level volumes: block — i.e. every template with a named
volume (postgres, redis, mariadb, mongo, every LSIO image). The hand-
rolled line parser treated ANY 2-space-indented name: as a service, so
volumes: -> redis-data: produced a phantom service with empty Image.
Rewritten to use the yaml package — extracts only doc.services.*,
ignores volumes/configs/networks. Also now supports map-form
environment, long-form ports, string|array command, container_name,
and IP-prefixed ports ("127.0.0.1:2375:2375"). Imageless services
produce a clear 400 instead of the cryptic generic Docker error.
2) UNIFI TEMPLATE: the v8.6.2 inline configs: content: script for Mongo
user creation is a Compose-CLI-only feature the API deploy cannot
apply. Switched to root Mongo credentials (MONGO_INITDB_ROOT_USERNAME
/ PASSWORD + MONGO_AUTHSOURCE=admin) so the stack deploys cleanly via
the API.
3) PERSISTENT ERROR DIALOG: Toast.error fades in 4s so deploy failures
were undebuggable. Replaced with a persistent sub-modal showing full
Docker error + failing service/container + partial deploys + the
compose YAML sent, with a Copy button. Backend now returns structured
{ error, service, containerName, partial } on failure; api.js attaches
.body and .status to the thrown Error so the dialog has all of it.
Browser-verified: deploys lsio-prowlarr cleanly (response {ok:true,
containers:[{name:"prowlarr",...}]}, 0 console errors); error modal
renders correctly with full block + Copy. Suite green 1444.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The Docker-API template deploy was returning **"(HTTP code 400) bad parameter - no command specified"** for any template with a top-level `volumes:` (or `configs:` / `networks:`) block — that includes **every template with a named volume** (postgres, redis, mariadb, mongo, every LSIO template, …). The hand-rolled line parser at `_parseComposeServices` treated any 2-space-indented `name:` as a service, so `volumes:\n redis-data:` produced a phantom "redis-data" service with empty `Image`, which Docker rejected with the cryptic "no command specified".
9
+
10
+
-**Parser rewritten** to use the project's `yaml` package — now correctly extracts only `doc.services.*`, ignoring `volumes` / `configs` / `networks` top-level blocks. Supports both array and map forms of `environment`, both short-form strings and long-form `{ target, published, protocol }` for ports, both string and array forms of `command`, and `container_name` overrides.
11
+
-**`command:` is honored** in `createOpts.Cmd` (string `command:` runs via `/bin/sh -c`, array form passes through). Templates that relied on a `command:` override (litellm) now actually use it.
12
+
-**IP-prefixed ports** (e.g. `"127.0.0.1:2375:2375"` in `lsio-socket-proxy`) now parsed and bound to the right interface via `HostConfig.PortBindings[…].HostIp`.
13
+
- Imageless services produce a **clear 400** with the offending service name, instead of letting Docker return the cryptic generic error.
14
+
15
+
### Persistent deploy-error dialog
16
+
Replaces the 4-second `Toast.error` (which made deploy failures essentially undebuggable) with a **persistent sub-modal** showing the full Docker error, the failing service + container, any partial deploys, and the compose YAML that was sent — with a **Copy** button. Closes only when the user clicks Close or the X.
17
+
18
+
The backend now returns structured `{ error, service, containerName, partial: [...] }` on failure, and `api.js` attaches `.body` and `.status` to the thrown `Error` so the dialog can show all of it.
19
+
20
+
### UniFi template simplified
21
+
The v8.6.2 UniFi template used Compose `configs:` with `content:` for the inline Mongo init script — a Compose-CLI feature the API-based deploy can't apply. Switched to **root Mongo credentials** (`MONGO_INITDB_ROOT_USERNAME` / `MONGO_INITDB_ROOT_PASSWORD` on mongo + `MONGO_AUTHSOURCE=admin` on the app) so the stack now deploys cleanly via the Docker API without any external file or healthcheck. The first-start race is handled by `restart: unless-stopped` (unifi may crash once before Mongo is ready, then restarts).
22
+
23
+
### Verified
24
+
End-to-end browser test deploys `lsio-prowlarr` cleanly through the new code path (response: `{ ok: true, containers: [{ name: "prowlarr", ... }] }`, zero console errors); the persistent error modal renders correctly with the full error block + Copy/Close. Suite green (1444), template-tests pass, every template's YAML round-trips through the new parser.
With 84 built-in templates now in **Containers → Templates**, scanning the grid for a specific image was painful. Adds a live search field above the category buttons.
<p class="text-muted text-sm" style="margin-bottom:8px">The Docker API returned an error. The full message is below — copy it before closing if you want to debug or report it.</p>
1941
+
${body.partial&&body.partial.length ? `<div class="empty-msg is-warning" style="margin-bottom:10px"><i class="fas fa-triangle-exclamation"></i><p><strong>Partial deploy:</strong> ${body.partial.length} container(s) were created before the failure. Stop/remove them from the Containers page if you need to start clean.</p></div>` : ''}
{type: 'fix',text: 'Fixed a long-standing latent bug: the Docker-API template deploy returned "no command specified" for every template with a top-level volumes: block (postgres, redis, mariadb, every LSIO template…). The hand-rolled line parser treated any 2-space-indented name: as a service, so volumes: → redis-data: created a phantom service with no image. Rewritten to use the yaml package — extracts only doc.services.*, correctly ignores top-level volumes/configs/networks blocks.'},
18
+
{type: 'fix',text: 'Deploy errors no longer flash in a toast that disappears in 4 seconds. Failures now open a persistent sub-modal with the full Docker error, the failing service + container name, any partial deploys, the compose YAML that was sent, and a Copy button. Closes only on user action so you can actually read and debug what went wrong.'},
19
+
{type: 'improvement',text: 'Template deploy now honors command: (string form via /bin/sh -c, array form passed through), container_name: overrides, and IP-prefixed ports like "127.0.0.1:2375:2375" (lsio-socket-proxy). Imageless services produce a clear 400 with the offending service name instead of the cryptic generic Docker error. UniFi template simplified to root Mongo credentials so it deploys cleanly via the API (the prior inline configs script was a Compose-CLI-only feature).'},
0 commit comments