@esuyo/coding-container 1.0.10 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@esuyo/coding-container",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "CLI to build, publish and deploy SSH-accessible coding containers on k3s",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,5 +1,5 @@
1
1
  import fs from "node:fs";
2
- import { dockerExec, run } from "../utils/exec.js";
2
+ import { dockerExec, ensureDockerAvailable, run } from "../utils/exec.js";
3
3
  import { imageRef } from "../config.js";
4
4
 
5
5
  /**
@@ -27,8 +27,21 @@ export async function buildImage(cfg) {
27
27
  }
28
28
  args.push(cfg.image.contextPath);
29
29
  console.log(`Building image ${ref} ...`);
30
+ try {
31
+ ensureDockerAvailable();
32
+ } catch (err) {
33
+ throw new Error(
34
+ `${err.message}\n(Build of ${ref} did not start — no image was built.)`
35
+ );
36
+ }
30
37
  const { cmd, opts } = dockerExec();
31
- await run(cmd, args, opts);
38
+ try {
39
+ await run(cmd, args, opts);
40
+ } catch (err) {
41
+ throw new Error(
42
+ `${err.message}\n(Build of ${ref} failed. If the output above mentions the Docker API, npipe, or daemon, Docker isn't running — start Docker Desktop (or the Docker daemon) and try again.)`
43
+ );
44
+ }
32
45
  console.log(`Built ${ref}`);
33
46
  }
34
47
 
@@ -1,4 +1,4 @@
1
- import { dockerExec, run } from "../utils/exec.js";
1
+ import { dockerExec, ensureDockerAvailable, run } from "../utils/exec.js";
2
2
  import { imageRef } from "../config.js";
3
3
 
4
4
  /**
@@ -9,12 +9,19 @@ import { imageRef } from "../config.js";
9
9
  export async function pushImage(cfg) {
10
10
  const ref = imageRef(cfg);
11
11
  console.log(`Pushing ${ref} to ${cfg.image.registry} ...`);
12
+ try {
13
+ ensureDockerAvailable();
14
+ } catch (err) {
15
+ throw new Error(
16
+ `${err.message}\n(Push of ${ref} did not start — nothing was pushed.)`
17
+ );
18
+ }
12
19
  const { cmd, opts } = dockerExec();
13
20
  try {
14
21
  await run(cmd, ["push", ref], opts);
15
22
  } catch (err) {
16
23
  throw new Error(
17
- `Push failed for ${ref}. Make sure you are logged in to ${cfg.image.registry} (docker login ${cfg.image.registry}).\n${err.message}`
24
+ `Push failed for ${ref}. Make sure you are logged in to ${cfg.image.registry} (docker login ${cfg.image.registry}). If the output above mentions the Docker API, npipe, or daemon, Docker isn't running — start Docker Desktop (or the Docker daemon) and try again.\n${err.message}`
18
25
  );
19
26
  }
20
27
  console.log(`Pushed ${ref}`);
package/src/utils/exec.js CHANGED
@@ -12,6 +12,53 @@ export function dockerExec() {
12
12
  return { cmd, opts };
13
13
  }
14
14
 
15
+ /**
16
+ * True when a docker failure looks like the daemon isn't reachable
17
+ * (Docker Desktop stopped, engine pipe missing, connection refused).
18
+ */
19
+ export function isDockerDaemonError(text) {
20
+ const s = String(text ?? "");
21
+ return (
22
+ /failed to connect to the docker api/i.test(s) ||
23
+ /cannot connect to the docker daemon/i.test(s) ||
24
+ /docker.*daemon.*(not running|unreachable|refused)/i.test(s) ||
25
+ /npipe/i.test(s) ||
26
+ /dockerDesktopLinuxEngine/i.test(s) ||
27
+ /\/\/\.\/pipe\/docker/i.test(s) ||
28
+ /open \/\/\.\/pipe\/docker/i.test(s) ||
29
+ /The system cannot find the file specified/i.test(s) ||
30
+ /error during connect/i.test(s)
31
+ );
32
+ }
33
+
34
+ /**
35
+ * Friendly wrapper for docker-daemon failures. Keeps the original detail
36
+ * so the underlying cause isn't lost, but leads with what to do.
37
+ */
38
+ export function dockerUnavailableMessage(cause) {
39
+ const detail = String(cause?.message ?? cause ?? "").trim();
40
+ const lines = [
41
+ "Docker isn't running or can't be reached.",
42
+ "Start Docker Desktop (Windows/macOS) or start the Docker daemon (Linux), wait until it reports healthy, then try again.",
43
+ ];
44
+ if (detail) lines.push(`Details: ${detail}`);
45
+ return lines.join("\n");
46
+ }
47
+
48
+ /**
49
+ * Pre-flight check: fail fast with an actionable message when the docker
50
+ * daemon isn't reachable, instead of a raw `docker build` API error.
51
+ * Throws with a "Docker isn't running" message; resolves otherwise.
52
+ */
53
+ export function ensureDockerAvailable() {
54
+ const { cmd, opts } = dockerExec();
55
+ try {
56
+ exec(cmd, ["info"], opts);
57
+ } catch (err) {
58
+ throw new Error(dockerUnavailableMessage(err.message ?? err));
59
+ }
60
+ }
61
+
15
62
  /**
16
63
  * Run a command and return its stdout (trimmed). Throws on non-zero exit.
17
64
  */