@alchemy.run/docker 2.0.0-beta.84 → 2.0.0-beta.86

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.
Files changed (98) hide show
  1. package/README.md +16 -0
  2. package/lib/Bootstrap.d.ts.map +1 -1
  3. package/lib/Bootstrap.js +2 -1
  4. package/lib/Bootstrap.js.map +1 -1
  5. package/lib/BuildCache.d.ts +87 -0
  6. package/lib/BuildCache.d.ts.map +1 -0
  7. package/lib/BuildCache.js +39 -0
  8. package/lib/BuildCache.js.map +1 -0
  9. package/lib/BuildHash.d.ts +20 -3
  10. package/lib/BuildHash.d.ts.map +1 -1
  11. package/lib/BuildHash.js +60 -21
  12. package/lib/BuildHash.js.map +1 -1
  13. package/lib/BuildPlan.d.ts +202 -0
  14. package/lib/BuildPlan.d.ts.map +1 -0
  15. package/lib/BuildPlan.js +514 -0
  16. package/lib/BuildPlan.js.map +1 -0
  17. package/lib/Container.d.ts +122 -1
  18. package/lib/Container.d.ts.map +1 -1
  19. package/lib/Container.js +232 -4
  20. package/lib/Container.js.map +1 -1
  21. package/lib/Context.d.ts +20 -1
  22. package/lib/Context.d.ts.map +1 -1
  23. package/lib/Context.js +15 -0
  24. package/lib/Context.js.map +1 -1
  25. package/lib/Docker.d.ts +113 -1
  26. package/lib/Docker.d.ts.map +1 -1
  27. package/lib/Docker.js +50 -8
  28. package/lib/Docker.js.map +1 -1
  29. package/lib/Dockerfile.d.ts +0 -2
  30. package/lib/Dockerfile.d.ts.map +1 -1
  31. package/lib/Dockerfile.js.map +1 -1
  32. package/lib/DockerfileParser.d.ts +125 -0
  33. package/lib/DockerfileParser.d.ts.map +1 -0
  34. package/lib/DockerfileParser.js +1040 -0
  35. package/lib/DockerfileParser.js.map +1 -0
  36. package/lib/HealthcheckCommand.d.ts.map +1 -1
  37. package/lib/HealthcheckCommand.js.map +1 -1
  38. package/lib/Image.d.ts +69 -13
  39. package/lib/Image.d.ts.map +1 -1
  40. package/lib/Image.js +59 -9
  41. package/lib/Image.js.map +1 -1
  42. package/lib/ImageArchive.d.ts +41 -0
  43. package/lib/ImageArchive.d.ts.map +1 -0
  44. package/lib/ImageArchive.js +54 -0
  45. package/lib/ImageArchive.js.map +1 -0
  46. package/lib/ImageSource.d.ts +151 -8
  47. package/lib/ImageSource.d.ts.map +1 -1
  48. package/lib/ImageSource.js +247 -72
  49. package/lib/ImageSource.js.map +1 -1
  50. package/lib/Network.d.ts +175 -3
  51. package/lib/Network.d.ts.map +1 -1
  52. package/lib/Network.js +296 -8
  53. package/lib/Network.js.map +1 -1
  54. package/lib/Providers.d.ts.map +1 -1
  55. package/lib/Providers.js.map +1 -1
  56. package/lib/Registry.d.ts.map +1 -1
  57. package/lib/Registry.js.map +1 -1
  58. package/lib/RegistryError.d.ts.map +1 -1
  59. package/lib/RegistryError.js.map +1 -1
  60. package/lib/RemoteImage.d.ts.map +1 -1
  61. package/lib/RemoteImage.js +1 -1
  62. package/lib/RemoteImage.js.map +1 -1
  63. package/lib/Service.d.ts +24 -3
  64. package/lib/Service.d.ts.map +1 -1
  65. package/lib/Service.js +154 -12
  66. package/lib/Service.js.map +1 -1
  67. package/lib/ServiceImage.d.ts.map +1 -1
  68. package/lib/ServiceImage.js.map +1 -1
  69. package/lib/ShellWord.d.ts +28 -0
  70. package/lib/ShellWord.d.ts.map +1 -0
  71. package/lib/ShellWord.js +301 -0
  72. package/lib/ShellWord.js.map +1 -0
  73. package/lib/Swarm.d.ts.map +1 -1
  74. package/lib/Swarm.js.map +1 -1
  75. package/lib/Volume.d.ts +24 -1
  76. package/lib/Volume.d.ts.map +1 -1
  77. package/lib/Volume.js +16 -0
  78. package/lib/Volume.js.map +1 -1
  79. package/lib/index.d.ts.map +1 -1
  80. package/lib/index.js.map +1 -1
  81. package/package.json +9 -9
  82. package/src/Bootstrap.ts +2 -0
  83. package/src/BuildCache.ts +111 -0
  84. package/src/BuildHash.ts +85 -26
  85. package/src/BuildPlan.ts +758 -0
  86. package/src/Container.ts +361 -5
  87. package/src/Context.ts +27 -1
  88. package/src/Docker.ts +157 -9
  89. package/src/Dockerfile.ts +0 -2
  90. package/src/DockerfileParser.ts +1152 -0
  91. package/src/Image.ts +75 -15
  92. package/src/ImageArchive.ts +77 -0
  93. package/src/ImageSource.ts +391 -99
  94. package/src/Network.ts +432 -10
  95. package/src/RemoteImage.ts +1 -1
  96. package/src/Service.ts +246 -62
  97. package/src/ShellWord.ts +326 -0
  98. package/src/Volume.ts +33 -1
package/src/Docker.ts CHANGED
@@ -85,6 +85,42 @@ export class Docker extends Context.Service<
85
85
  network?: string | undefined;
86
86
  /** Linux capabilities to add. */
87
87
  "cap-add"?: Array<string> | undefined;
88
+ /** Linux capabilities to drop. */
89
+ "cap-drop"?: Array<string> | undefined;
90
+ /** Hard memory limit in Docker's byte-suffix format. */
91
+ memory?: string | undefined;
92
+ /** Combined memory-and-swap limit in Docker's byte-suffix format. */
93
+ "memory-swap"?: string | undefined;
94
+ /** Soft memory reservation for memory contention. */
95
+ "memory-reservation"?: string | undefined;
96
+ /** CPU quota, in cores. */
97
+ cpus?: number | undefined;
98
+ /** Per-container process and thread limit. */
99
+ "pids-limit"?: number | undefined;
100
+ /** Mount the root filesystem read-only. */
101
+ "read-only"?: boolean | undefined;
102
+ /** Security options such as `no-new-privileges` and seccomp/AppArmor profiles. */
103
+ "security-opt"?: Array<string> | undefined;
104
+ /** Per-container user namespace; "host" disables daemon user remapping. */
105
+ userns?: string | undefined;
106
+ /** Supplemental Linux groups. */
107
+ "group-add"?: Array<string> | undefined;
108
+ /** Per-process soft/hard resource limits. */
109
+ ulimit?: Array<string> | undefined;
110
+ /** Docker log driver. */
111
+ "log-driver"?: string | undefined;
112
+ /** Driver-specific Docker logging options. */
113
+ "log-opt"?: Array<string> | undefined;
114
+ /** Kernel OOM score adjustment. */
115
+ "oom-score-adj"?: number | undefined;
116
+ /** Signal used on container stop. */
117
+ "stop-signal"?: string | undefined;
118
+ /** Run Docker's tiny init process. */
119
+ init?: boolean | undefined;
120
+ /** Runtime UID/GID or named user. */
121
+ user?: string | undefined;
122
+ /** Docker tmpfs mount expressions (target[:options]). */
123
+ tmpfs?: Array<string> | undefined;
88
124
  /** Host devices in Docker's `host:container[:permissions]` form. */
89
125
  device?: Array<string> | undefined;
90
126
  command: Array<string> | undefined;
@@ -130,6 +166,12 @@ export class Docker extends Context.Service<
130
166
  platform?: string;
131
167
  target?: string;
132
168
  "build-arg"?: Record<string, string>;
169
+ /**
170
+ * BuildKit secrets, keyed by id (`RUN --mount=type=secret,id=<id>`).
171
+ * Values reach `docker` through its environment, never its argv,
172
+ * and are not written to the image.
173
+ */
174
+ secrets?: Record<string, string | Redacted.Redacted<string>>;
133
175
  "cache-from"?: Array<string>;
134
176
  "cache-to"?: Array<string>;
135
177
  args?: Array<string>;
@@ -229,7 +271,26 @@ export class Docker extends Context.Service<
229
271
  readonly create: (options: {
230
272
  name: string;
231
273
  driver: string;
274
+ /** Whether the network is isolated from external connectivity. */
275
+ internal?: boolean;
276
+ /** Whether standalone containers may attach to the network. */
277
+ attachable?: boolean;
278
+ /** Explicitly enable or disable IPv4 address allocation. */
279
+ ipv4?: boolean;
232
280
  ipv6?: boolean;
281
+ /** Network driver options, passed as repeated `--opt` arguments. */
282
+ opt?: Record<string, string>;
283
+ /** Network IP Address Management settings. */
284
+ ipam?: {
285
+ driver?: string;
286
+ options?: Record<string, string>;
287
+ config?: Array<{
288
+ subnet: string;
289
+ gateway?: string;
290
+ ipRange?: string;
291
+ auxAddresses?: Record<string, string>;
292
+ }>;
293
+ };
233
294
  label?: Record<string, string>;
234
295
  context?: string;
235
296
  }) => Effect.Effect<CommandOutput, PlatformError>;
@@ -327,10 +388,12 @@ export class Docker extends Context.Service<
327
388
  context?: string;
328
389
  replicas?: number;
329
390
  "endpoint-mode"?: "vip" | "dnsrr";
391
+ /** Networks to detach, by name or id; applied before `network-add`. */
392
+ "network-rm"?: string[];
393
+ "network-add"?: string[];
330
394
  "constraint-add"?: string[];
331
395
  "constraint-rm"?: string[];
332
396
  "replicas-max-per-node"?: number;
333
- "placement-pref"?: string[];
334
397
  "update-parallelism"?: number;
335
398
  "update-delay"?: string;
336
399
  "update-monitor"?: string;
@@ -356,13 +419,23 @@ export class Docker extends Context.Service<
356
419
  "health-start-period"?: string;
357
420
  "stop-grace-period"?: string;
358
421
  "mount-add"?: string[];
422
+ /** Mount targets to remove. */
423
+ "mount-rm"?: string[];
359
424
  "secret-add"?: string[];
425
+ /** Secret names to remove; applied before `secret-add`. */
426
+ "secret-rm"?: string[];
360
427
  "config-add"?: string[];
428
+ /** Config names to remove; applied before `config-add`. */
429
+ "config-rm"?: string[];
361
430
  "read-only"?: boolean;
362
431
  "publish-add"?: string[];
432
+ /** Published ports to remove, as `target=<port>,protocol=<p>,mode=<m>`. */
433
+ "publish-rm"?: string[];
363
434
  "label-add"?: Record<string, string>;
364
435
  "label-rm"?: string[];
365
436
  "env-add"?: Record<string, string>;
437
+ /** Environment variable names to remove. */
438
+ "env-rm"?: string[];
366
439
  args?: string;
367
440
  }) => Effect.Effect<CommandOutput, PlatformError>;
368
441
  /** Inspects a service. */
@@ -423,6 +496,8 @@ export declare namespace Docker {
423
496
  Image: string;
424
497
  Cmd: string[] | null;
425
498
  Env: string[] | null;
499
+ User?: string;
500
+ StopSignal?: string;
426
501
  Labels: Record<string, string> | null;
427
502
  StopTimeout?: number;
428
503
  Healthcheck?: {
@@ -442,12 +517,28 @@ export declare namespace Docker {
442
517
  AutoRemove: boolean;
443
518
  NetworkMode?: string;
444
519
  CapAdd?: string[] | null;
520
+ CapDrop?: string[] | null;
521
+ Memory?: number;
522
+ MemorySwap?: number;
523
+ MemoryReservation?: number;
524
+ NanoCpus?: number;
525
+ PidsLimit?: number;
526
+ ReadonlyRootfs?: boolean;
527
+ SecurityOpt?: string[] | null;
528
+ UsernsMode?: string;
529
+ GroupAdd?: string[] | null;
530
+ Ulimits?: Array<{ Name: string; Soft: number; Hard: number }> | null;
531
+ LogConfig?: { Type: string; Config: Record<string, string> | null };
532
+ OomScoreAdj?: number;
533
+ Init?: boolean | null;
534
+ Tmpfs?: Record<string, string> | null;
445
535
  Devices?: Array<{
446
536
  PathOnHost: string;
447
537
  PathInContainer: string;
448
538
  CgroupPermissions: string;
449
539
  }> | null;
450
540
  };
541
+ AppArmorProfile?: string;
451
542
  NetworkSettings: {
452
543
  Networks: Record<string, { NetworkID: string; Aliases: string[] | null }> | null;
453
544
  Ports?: Record<string, Array<{ HostIp: string; HostPort: string }> | null> | null;
@@ -483,7 +574,21 @@ export declare namespace Docker {
483
574
  Created: string;
484
575
  Scope: string;
485
576
  Driver: string;
577
+ Internal?: boolean;
578
+ Attachable?: boolean;
579
+ EnableIPv4?: boolean;
486
580
  EnableIPv6: boolean;
581
+ Options?: Record<string, string> | null;
582
+ IPAM?: {
583
+ Driver?: string;
584
+ Options?: Record<string, string> | null;
585
+ Config?: Array<{
586
+ Subnet: string;
587
+ Gateway?: string;
588
+ IPRange?: string;
589
+ AuxiliaryAddresses?: Record<string, string> | null;
590
+ }> | null;
591
+ };
487
592
  Labels: Record<string, string> | null;
488
593
  }
489
594
  }
@@ -832,17 +937,21 @@ const makeDocker = (options: DockerOptions) =>
832
937
  },
833
938
  image: {
834
939
  build: Effect.fn("Docker.image.build")(function* (
835
- { context: buildContext, engineContext, args, credentials, ...options },
940
+ { context: buildContext, engineContext, args, credentials, secrets, ...options },
836
941
  session,
837
942
  registry,
838
943
  ) {
839
944
  const tap = outputTap(session);
840
- const buildArgs = [buildContext, ...formatArgs(options), ...(args ?? [])];
945
+ const secret = buildSecrets(secrets);
946
+ const buildArgs = [buildContext, ...formatArgs(options), ...secret.args, ...(args ?? [])];
841
947
  const engine = formatArgs({ context: engineContext });
842
948
  if (registry === undefined) {
843
949
  return yield* run(
844
950
  [...engine, "image", "build", ...buildArgs],
845
- credentials ? yield* registryEnvironment(credentials) : undefined,
951
+ {
952
+ ...(credentials ? yield* registryEnvironment(credentials) : undefined),
953
+ ...secret.env,
954
+ },
846
955
  tap,
847
956
  );
848
957
  }
@@ -853,7 +962,7 @@ const makeDocker = (options: DockerOptions) =>
853
962
  const env = yield* registryEnvironment(registry);
854
963
  return yield* run(
855
964
  [...engine, "buildx", "build", "--push", ...buildArgs],
856
- env,
965
+ { ...env, ...secret.env },
857
966
  tap,
858
967
  ).pipe(Effect.mapError(classifyDockerRegistryError));
859
968
  }
@@ -869,7 +978,7 @@ const makeDocker = (options: DockerOptions) =>
869
978
  ...(mode === "load" ? ["buildx", "build", "--load"] : ["image", "build"]),
870
979
  ...buildArgs,
871
980
  ],
872
- undefined,
981
+ secret.env,
873
982
  tap,
874
983
  );
875
984
  const [tag, ...tags] =
@@ -924,13 +1033,34 @@ const makeDocker = (options: DockerOptions) =>
924
1033
  remove: (name, force) => run(["context", "rm", ...(force ? ["-f"] : []), name]),
925
1034
  },
926
1035
  network: {
927
- create: ({ name, driver, ipv6, label, context }) =>
1036
+ create: ({ name, driver, internal, attachable, ipv4, ipv6, opt, ipam, label, context }) =>
928
1037
  run([
929
1038
  ...formatArgs({ context }),
930
1039
  "network",
931
1040
  "create",
1041
+ ...formatArgs({
1042
+ driver,
1043
+ internal,
1044
+ attachable,
1045
+ ipv6,
1046
+ opt,
1047
+ "ipam-driver": ipam?.driver,
1048
+ "ipam-opt": ipam?.options,
1049
+ label,
1050
+ }),
1051
+ // Docker's boolean --ipv4=false needs an equals sign; the generic
1052
+ // CLI formatter intentionally skips false values elsewhere.
1053
+ ...(ipv4 === undefined ? [] : [`--ipv4=` + String(ipv4)]),
1054
+ ...(ipam?.config ?? []).flatMap(({ subnet, gateway, ipRange, auxAddresses }) => [
1055
+ "--subnet",
1056
+ subnet,
1057
+ ...(gateway === undefined ? [] : ["--gateway", gateway]),
1058
+ ...(ipRange === undefined ? [] : ["--ip-range", ipRange]),
1059
+ ...Object.entries(auxAddresses ?? {})
1060
+ .sort(([a], [b]) => a.localeCompare(b))
1061
+ .flatMap(([key, value]) => ["--aux-address", key + "=" + value]),
1062
+ ]),
932
1063
  name,
933
- ...formatArgs({ driver, ipv6, label }),
934
1064
  ]),
935
1065
  connect: ({ network, container, alias, context }) =>
936
1066
  run([
@@ -1048,6 +1178,22 @@ const systemError = (input: {
1048
1178
  }),
1049
1179
  );
1050
1180
 
1181
+ /**
1182
+ * `--secret id=<id>,env=<var>` per secret, with each value under a generated
1183
+ * variable name: an id is the Dockerfile author's choice and may collide with
1184
+ * the environment Docker itself reads (`PATH`, `DOCKER_HOST`).
1185
+ */
1186
+ const buildSecrets = (secrets: Record<string, string | Redacted.Redacted<string>> | undefined) => {
1187
+ const args: Array<string> = [];
1188
+ const env: Record<string, string> = {};
1189
+ Object.entries(secrets ?? {}).forEach(([id, value], index) => {
1190
+ const variable = `ALCHEMY_BUILD_SECRET_${index}`;
1191
+ args.push("--secret", `id=${id},env=${variable}`);
1192
+ env[variable] = Redacted.isRedacted(value) ? Redacted.value(value) : value;
1193
+ });
1194
+ return { args, env };
1195
+ };
1196
+
1051
1197
  /** Formats a set of options into a list of command-line arguments. */
1052
1198
  const formatArgs = (
1053
1199
  options: Record<
@@ -1057,7 +1203,9 @@ const formatArgs = (
1057
1203
  ) => {
1058
1204
  const args: Array<string> = [];
1059
1205
  for (const [key, value] of Object.entries(options)) {
1060
- if (!value) continue;
1206
+ // `0` is meaningful (`--replicas 0`, `--update-parallelism 0`), so only
1207
+ // absent, `false` and empty values are omitted.
1208
+ if (value === undefined || value === false || value === "") continue;
1061
1209
  const prefix = key.length > 1 ? `--${key}` : `-${key}`;
1062
1210
  if (value === true) {
1063
1211
  args.push(prefix);
package/src/Dockerfile.ts CHANGED
@@ -20,7 +20,6 @@
20
20
  * const worker = yield* AWS.ECS.Task(
21
21
  * "Transcoder",
22
22
  * {
23
- * cluster,
24
23
  * main: import.meta.url,
25
24
  * dockerfile: Dockerfile.inline`
26
25
  * FROM oven/bun:1
@@ -38,7 +37,6 @@
38
37
  * const trainer = yield* AWS.ECS.Task(
39
38
  * "Trainer",
40
39
  * {
41
- * cluster,
42
40
  * main: import.meta.url,
43
41
  * dockerfile: Dockerfile.inline`
44
42
  * FROM ${base.imageUri}