@alchemy.run/docker 0.0.0-stage → 2.0.0-beta.84
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/LICENSE +201 -0
- package/README.md +50 -2
- package/lib/Bootstrap.d.ts +7 -0
- package/lib/Bootstrap.d.ts.map +1 -0
- package/lib/Bootstrap.js +25 -0
- package/lib/Bootstrap.js.map +1 -0
- package/lib/BuildHash.d.ts +47 -0
- package/lib/BuildHash.d.ts.map +1 -0
- package/lib/BuildHash.js +165 -0
- package/lib/BuildHash.js.map +1 -0
- package/lib/Container.d.ts +352 -0
- package/lib/Container.d.ts.map +1 -0
- package/lib/Container.js +531 -0
- package/lib/Container.js.map +1 -0
- package/lib/Context.d.ts +86 -0
- package/lib/Context.d.ts.map +1 -0
- package/lib/Context.js +146 -0
- package/lib/Context.js.map +1 -0
- package/lib/Docker.d.ts +448 -0
- package/lib/Docker.d.ts.map +1 -0
- package/lib/Docker.js +416 -0
- package/lib/Docker.js.map +1 -0
- package/lib/Dockerfile.d.ts +72 -0
- package/lib/Dockerfile.d.ts.map +1 -0
- package/lib/Dockerfile.js +12 -0
- package/lib/Dockerfile.js.map +1 -0
- package/lib/HealthcheckCommand.d.ts +17 -0
- package/lib/HealthcheckCommand.d.ts.map +1 -0
- package/lib/HealthcheckCommand.js +33 -0
- package/lib/HealthcheckCommand.js.map +1 -0
- package/lib/Image.d.ts +151 -0
- package/lib/Image.d.ts.map +1 -0
- package/lib/Image.js +192 -0
- package/lib/Image.js.map +1 -0
- package/lib/ImageSource.d.ts +234 -0
- package/lib/ImageSource.d.ts.map +1 -0
- package/lib/ImageSource.js +469 -0
- package/lib/ImageSource.js.map +1 -0
- package/lib/Network.d.ts +70 -0
- package/lib/Network.d.ts.map +1 -0
- package/lib/Network.js +111 -0
- package/lib/Network.js.map +1 -0
- package/lib/Providers.d.ts +21 -0
- package/lib/Providers.d.ts.map +1 -0
- package/lib/Providers.js +26 -0
- package/lib/Providers.js.map +1 -0
- package/lib/Registry.d.ts +47 -0
- package/lib/Registry.d.ts.map +1 -0
- package/lib/Registry.js +67 -0
- package/lib/Registry.js.map +1 -0
- package/lib/RegistryError.d.ts +21 -0
- package/lib/RegistryError.d.ts.map +1 -0
- package/lib/RegistryError.js +28 -0
- package/lib/RegistryError.js.map +1 -0
- package/lib/RemoteImage.d.ts +118 -0
- package/lib/RemoteImage.d.ts.map +1 -0
- package/lib/RemoteImage.js +164 -0
- package/lib/RemoteImage.js.map +1 -0
- package/lib/Service.d.ts +478 -0
- package/lib/Service.d.ts.map +1 -0
- package/lib/Service.js +588 -0
- package/lib/Service.js.map +1 -0
- package/lib/ServiceImage.d.ts +78 -0
- package/lib/ServiceImage.d.ts.map +1 -0
- package/lib/ServiceImage.js +162 -0
- package/lib/ServiceImage.js.map +1 -0
- package/lib/Swarm.d.ts +119 -0
- package/lib/Swarm.d.ts.map +1 -0
- package/lib/Swarm.js +148 -0
- package/lib/Swarm.js.map +1 -0
- package/lib/Volume.d.ts +94 -0
- package/lib/Volume.d.ts.map +1 -0
- package/lib/Volume.js +133 -0
- package/lib/Volume.js.map +1 -0
- package/lib/index.d.ts +14 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +13 -0
- package/lib/index.js.map +1 -0
- package/package.json +72 -3
- package/src/Bootstrap.ts +51 -0
- package/src/BuildHash.ts +255 -0
- package/src/Container.ts +792 -0
- package/src/Context.ts +215 -0
- package/src/Docker.ts +1079 -0
- package/src/Dockerfile.ts +81 -0
- package/src/HealthcheckCommand.ts +35 -0
- package/src/Image.ts +293 -0
- package/src/ImageSource.ts +769 -0
- package/src/Network.ts +169 -0
- package/src/Providers.ts +46 -0
- package/src/Registry.ts +91 -0
- package/src/RegistryError.ts +48 -0
- package/src/RemoteImage.ts +255 -0
- package/src/Service.ts +1080 -0
- package/src/ServiceImage.ts +252 -0
- package/src/Swarm.ts +221 -0
- package/src/Volume.ts +193 -0
- package/src/index.ts +17 -0
package/lib/Image.d.ts
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import * as Provider from "alchemy/Provider";
|
|
2
|
+
import { Resource } from "alchemy/Resource";
|
|
3
|
+
import * as FileSystem from "effect/FileSystem";
|
|
4
|
+
import * as Path from "effect/Path";
|
|
5
|
+
import { Docker } from "./Docker.ts";
|
|
6
|
+
import type { Providers } from "./Providers.ts";
|
|
7
|
+
import { type ImageRegistry } from "./Registry.ts";
|
|
8
|
+
export interface DockerBuildOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Build context directory.
|
|
11
|
+
*
|
|
12
|
+
* @default Current working directory.
|
|
13
|
+
*/
|
|
14
|
+
context?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Dockerfile path, relative to the context unless absolute.
|
|
17
|
+
*
|
|
18
|
+
* @default "Dockerfile"
|
|
19
|
+
*/
|
|
20
|
+
dockerfile?: string;
|
|
21
|
+
/** Target platform, e.g. `"linux/amd64"`. */
|
|
22
|
+
platform?: string;
|
|
23
|
+
/** Docker build arguments. */
|
|
24
|
+
args?: Record<string, string>;
|
|
25
|
+
/** Multi-stage build target. */
|
|
26
|
+
target?: string;
|
|
27
|
+
/** Cache sources passed as `--cache-from`. */
|
|
28
|
+
cacheFrom?: string[];
|
|
29
|
+
/** Cache destinations passed as `--cache-to`. */
|
|
30
|
+
cacheTo?: string[];
|
|
31
|
+
/** Additional Docker build options. */
|
|
32
|
+
options?: string[];
|
|
33
|
+
}
|
|
34
|
+
export interface ImageProps {
|
|
35
|
+
/**
|
|
36
|
+
* Repository/name for the built image.
|
|
37
|
+
*
|
|
38
|
+
* @default Generated from stack, stage, logical id, and instance id.
|
|
39
|
+
*/
|
|
40
|
+
name?: string;
|
|
41
|
+
/** Image tag. @default "latest" */
|
|
42
|
+
tag?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Registry credentials. The image is pushed to this registry (unless
|
|
45
|
+
* `skipPush`), and the build itself authenticates with them, so private
|
|
46
|
+
* base images and `type=registry` caches hosted there resolve without a
|
|
47
|
+
* host `docker login`. Credentials already in `DOCKER_AUTH_CONFIG` for
|
|
48
|
+
* other registries are kept. Build-time authentication needs Buildx 0.26+
|
|
49
|
+
* (Docker Desktop 4.44+) or the legacy builder; older Buildx plugins ignore
|
|
50
|
+
* it, so a private base image there still needs `docker login`.
|
|
51
|
+
*/
|
|
52
|
+
registry?: ImageRegistry;
|
|
53
|
+
/** Skip registry push even when `registry` is set. @default false */
|
|
54
|
+
skipPush?: boolean;
|
|
55
|
+
/** Docker context name or context resource. */
|
|
56
|
+
context?: Docker.ContextRef;
|
|
57
|
+
/** Docker build configuration. */
|
|
58
|
+
build: DockerBuildOptions;
|
|
59
|
+
}
|
|
60
|
+
export interface Image extends Resource<"Docker.Image", ImageProps, {
|
|
61
|
+
/** Image repository/name without tag. */
|
|
62
|
+
name: string;
|
|
63
|
+
/** Final image reference. Includes registry host when pushed there. */
|
|
64
|
+
imageRef: string;
|
|
65
|
+
/** Local image id after build/tag. */
|
|
66
|
+
imageId: string;
|
|
67
|
+
/** Registry digest after push when available. */
|
|
68
|
+
repoDigest?: string;
|
|
69
|
+
/** Tag used for the local image. */
|
|
70
|
+
tag: string;
|
|
71
|
+
/** Build timestamp in milliseconds since epoch. */
|
|
72
|
+
builtAt: number;
|
|
73
|
+
}, never, Providers> {
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Builds, tags, and optionally pushes Docker images through the active Docker
|
|
77
|
+
* context.
|
|
78
|
+
*
|
|
79
|
+
* This resource uses the Docker CLI and whatever daemon or remote context the
|
|
80
|
+
* CLI is configured to target. It is separate from `Cloudflare.Container`;
|
|
81
|
+
* registry image references are the boundary between Docker-managed images and
|
|
82
|
+
* cloud container platforms.
|
|
83
|
+
*
|
|
84
|
+
* `Image` always builds from a Dockerfile. To pull (and optionally re-tag and
|
|
85
|
+
* push) an existing registry image, use `Docker.RemoteImage`.
|
|
86
|
+
*
|
|
87
|
+
*
|
|
88
|
+
* ### Building Images
|
|
89
|
+
* **Example:** Build from a Dockerfile
|
|
90
|
+
* ```typescript
|
|
91
|
+
* const image = yield* Docker.Image("app", {
|
|
92
|
+
* name: "my-app",
|
|
93
|
+
* tag: "latest",
|
|
94
|
+
* build: {
|
|
95
|
+
* context: "./app",
|
|
96
|
+
* dockerfile: "Dockerfile",
|
|
97
|
+
* args: { NODE_ENV: "production" },
|
|
98
|
+
* },
|
|
99
|
+
* });
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* ### Registry Push
|
|
103
|
+
* **Example:** Push with Redacted credentials
|
|
104
|
+
* ```typescript
|
|
105
|
+
* const image = yield* Docker.Image("app", {
|
|
106
|
+
* name: "my-app",
|
|
107
|
+
* build: { context: "./app" },
|
|
108
|
+
* registry: {
|
|
109
|
+
* server: "ghcr.io",
|
|
110
|
+
* username: "octocat",
|
|
111
|
+
* password: Config.Redacted("GITHUB_TOKEN"),
|
|
112
|
+
* },
|
|
113
|
+
* });
|
|
114
|
+
* ```
|
|
115
|
+
*
|
|
116
|
+
* ### Private Base Images and Registry Caches
|
|
117
|
+
* **Example:** Build FROM a private base image with a registry cache
|
|
118
|
+
* ```typescript
|
|
119
|
+
* // Dockerfile: FROM registry.example.com/base:v1
|
|
120
|
+
* const image = yield* Docker.Image("app", {
|
|
121
|
+
* name: "registry.example.com/app",
|
|
122
|
+
* build: {
|
|
123
|
+
* context: "./app",
|
|
124
|
+
* cacheFrom: ["type=registry,ref=registry.example.com/app:buildcache"],
|
|
125
|
+
* cacheTo: ["type=registry,ref=registry.example.com/app:buildcache,mode=max"],
|
|
126
|
+
* },
|
|
127
|
+
* // Authenticates the base-image pull and cache import/export, then the push.
|
|
128
|
+
* registry: {
|
|
129
|
+
* server: "registry.example.com",
|
|
130
|
+
* username: "deploy",
|
|
131
|
+
* password: Config.Redacted("REGISTRY_PASSWORD"),
|
|
132
|
+
* },
|
|
133
|
+
* });
|
|
134
|
+
* ```
|
|
135
|
+
*
|
|
136
|
+
* ### Docker Context
|
|
137
|
+
* **Example:** Build in a named Docker context
|
|
138
|
+
* ```typescript
|
|
139
|
+
* const image = yield* Docker.Image("app", {
|
|
140
|
+
* name: "my-app",
|
|
141
|
+
* context: "remote-build",
|
|
142
|
+
* build: { context: "./app" },
|
|
143
|
+
* });
|
|
144
|
+
* ```
|
|
145
|
+
*
|
|
146
|
+
* @resource
|
|
147
|
+
* @product Image
|
|
148
|
+
*/
|
|
149
|
+
export declare const Image: import("alchemy/Resource").ResourceClass<Image>;
|
|
150
|
+
export declare const ImageProvider: () => import("effect/Layer").Layer<Provider.Provider<Image>, never, Docker | FileSystem.FileSystem | Path.Path | import("alchemy/Stack").Stack | import("alchemy/Stage").Stage>;
|
|
151
|
+
//# sourceMappingURL=Image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../src/Image.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,IAAI,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,MAAM,EAAyC,MAAM,aAAa,CAAC;AAC5E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EACL,KAAK,aAAa,EAKnB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,gCAAgC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAC5B,kCAAkC;IAClC,KAAK,EAAE,kBAAkB,CAAC;CAC3B;AAED,MAAM,WAAW,KAAM,SAAQ,QAAQ,CACrC,cAAc,EACd,UAAU,EACV;IACE,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;CACjB,EACD,KAAK,EACL,SAAS,CACV;CAAG;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyEG;AACH,eAAO,MAAM,KAAK,iDAAkC,CAAC;AAErD,eAAO,MAAM,aAAa,iLA4HvB,CAAC"}
|
package/lib/Image.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import * as Artifacts from "alchemy/Artifacts";
|
|
2
|
+
import { isResolved } from "alchemy/Diff";
|
|
3
|
+
import * as Provider from "alchemy/Provider";
|
|
4
|
+
import { Resource } from "alchemy/Resource";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as FileSystem from "effect/FileSystem";
|
|
7
|
+
import * as Path from "effect/Path";
|
|
8
|
+
import { Docker, dockerContextName, dockerPhysicalName } from "./Docker.js";
|
|
9
|
+
import { parseCreatedAt, publishedRepoDigest, repositoryFromImageRef, withRegistryHost, } from "./Registry.js";
|
|
10
|
+
/**
|
|
11
|
+
* Builds, tags, and optionally pushes Docker images through the active Docker
|
|
12
|
+
* context.
|
|
13
|
+
*
|
|
14
|
+
* This resource uses the Docker CLI and whatever daemon or remote context the
|
|
15
|
+
* CLI is configured to target. It is separate from `Cloudflare.Container`;
|
|
16
|
+
* registry image references are the boundary between Docker-managed images and
|
|
17
|
+
* cloud container platforms.
|
|
18
|
+
*
|
|
19
|
+
* `Image` always builds from a Dockerfile. To pull (and optionally re-tag and
|
|
20
|
+
* push) an existing registry image, use `Docker.RemoteImage`.
|
|
21
|
+
*
|
|
22
|
+
*
|
|
23
|
+
* ### Building Images
|
|
24
|
+
* **Example:** Build from a Dockerfile
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const image = yield* Docker.Image("app", {
|
|
27
|
+
* name: "my-app",
|
|
28
|
+
* tag: "latest",
|
|
29
|
+
* build: {
|
|
30
|
+
* context: "./app",
|
|
31
|
+
* dockerfile: "Dockerfile",
|
|
32
|
+
* args: { NODE_ENV: "production" },
|
|
33
|
+
* },
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* ### Registry Push
|
|
38
|
+
* **Example:** Push with Redacted credentials
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const image = yield* Docker.Image("app", {
|
|
41
|
+
* name: "my-app",
|
|
42
|
+
* build: { context: "./app" },
|
|
43
|
+
* registry: {
|
|
44
|
+
* server: "ghcr.io",
|
|
45
|
+
* username: "octocat",
|
|
46
|
+
* password: Config.Redacted("GITHUB_TOKEN"),
|
|
47
|
+
* },
|
|
48
|
+
* });
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* ### Private Base Images and Registry Caches
|
|
52
|
+
* **Example:** Build FROM a private base image with a registry cache
|
|
53
|
+
* ```typescript
|
|
54
|
+
* // Dockerfile: FROM registry.example.com/base:v1
|
|
55
|
+
* const image = yield* Docker.Image("app", {
|
|
56
|
+
* name: "registry.example.com/app",
|
|
57
|
+
* build: {
|
|
58
|
+
* context: "./app",
|
|
59
|
+
* cacheFrom: ["type=registry,ref=registry.example.com/app:buildcache"],
|
|
60
|
+
* cacheTo: ["type=registry,ref=registry.example.com/app:buildcache,mode=max"],
|
|
61
|
+
* },
|
|
62
|
+
* // Authenticates the base-image pull and cache import/export, then the push.
|
|
63
|
+
* registry: {
|
|
64
|
+
* server: "registry.example.com",
|
|
65
|
+
* username: "deploy",
|
|
66
|
+
* password: Config.Redacted("REGISTRY_PASSWORD"),
|
|
67
|
+
* },
|
|
68
|
+
* });
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* ### Docker Context
|
|
72
|
+
* **Example:** Build in a named Docker context
|
|
73
|
+
* ```typescript
|
|
74
|
+
* const image = yield* Docker.Image("app", {
|
|
75
|
+
* name: "my-app",
|
|
76
|
+
* context: "remote-build",
|
|
77
|
+
* build: { context: "./app" },
|
|
78
|
+
* });
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* @resource
|
|
82
|
+
* @product Image
|
|
83
|
+
*/
|
|
84
|
+
export const Image = Resource("Docker.Image");
|
|
85
|
+
export const ImageProvider = () => Provider.effect(Image, Effect.gen(function* () {
|
|
86
|
+
const fs = yield* FileSystem.FileSystem;
|
|
87
|
+
const path = yield* Path.Path;
|
|
88
|
+
const docker = yield* Docker;
|
|
89
|
+
const buildAndInspectImage = Effect.fn(function* (id, props, instanceId) {
|
|
90
|
+
const name = yield* dockerPhysicalName(id, props, instanceId);
|
|
91
|
+
const engineContext = dockerContextName(props.context);
|
|
92
|
+
const tag = props.tag ?? "latest";
|
|
93
|
+
const ref = `${name}:${tag}`;
|
|
94
|
+
const paths = yield* resolveBuildPaths(props.build);
|
|
95
|
+
yield* docker.image.build({
|
|
96
|
+
tag: ref,
|
|
97
|
+
context: paths.context,
|
|
98
|
+
file: paths.dockerfile,
|
|
99
|
+
platform: props.build.platform,
|
|
100
|
+
target: props.build.target,
|
|
101
|
+
"build-arg": props.build.args,
|
|
102
|
+
"cache-from": props.build.cacheFrom,
|
|
103
|
+
"cache-to": props.build.cacheTo,
|
|
104
|
+
args: props.build.options,
|
|
105
|
+
engineContext,
|
|
106
|
+
// Base images and registry caches may live in the same registry;
|
|
107
|
+
// the push itself stays in `reconcile`.
|
|
108
|
+
credentials: props.registry,
|
|
109
|
+
});
|
|
110
|
+
// Read the freshly built image's id and creation time straight from
|
|
111
|
+
// Docker rather than synthesizing a wall-clock timestamp.
|
|
112
|
+
return {
|
|
113
|
+
name,
|
|
114
|
+
tag,
|
|
115
|
+
image: yield* docker.image.inspect(ref, engineContext),
|
|
116
|
+
ref,
|
|
117
|
+
};
|
|
118
|
+
}, Artifacts.cached("build"));
|
|
119
|
+
const resolveBuildPaths = Effect.fn(function* (build) {
|
|
120
|
+
const cwd = yield* Effect.sync(() => process.cwd());
|
|
121
|
+
const context = path.resolve(build.context ?? cwd);
|
|
122
|
+
const dockerfile = build.dockerfile
|
|
123
|
+
? path.isAbsolute(build.dockerfile)
|
|
124
|
+
? build.dockerfile
|
|
125
|
+
: path.resolve(context, build.dockerfile)
|
|
126
|
+
: path.resolve(context, "Dockerfile");
|
|
127
|
+
if (!(yield* fs.exists(context))) {
|
|
128
|
+
return yield* Effect.die(`Docker build context does not exist: ${context}`);
|
|
129
|
+
}
|
|
130
|
+
if (!(yield* fs.exists(dockerfile))) {
|
|
131
|
+
return yield* Effect.die(`Dockerfile does not exist: ${dockerfile}`);
|
|
132
|
+
}
|
|
133
|
+
return { context, dockerfile };
|
|
134
|
+
});
|
|
135
|
+
return Image.Provider.of({
|
|
136
|
+
list: () => Effect.succeed([]),
|
|
137
|
+
read: Effect.fn(function* ({ id, instanceId, olds, output }) {
|
|
138
|
+
const context = dockerContextName(olds.context);
|
|
139
|
+
const ref = output?.imageRef ??
|
|
140
|
+
(yield* dockerPhysicalName(id, olds, instanceId).pipe(Effect.map((name) => `${name}:${olds.tag ?? "latest"}`)));
|
|
141
|
+
const image = yield* docker.image
|
|
142
|
+
.inspect(ref, context)
|
|
143
|
+
.pipe(Effect.catchReason("PlatformError", "NotFound", () => Effect.undefined));
|
|
144
|
+
if (!image)
|
|
145
|
+
return undefined;
|
|
146
|
+
return {
|
|
147
|
+
name: output?.name ?? repositoryFromImageRef(ref),
|
|
148
|
+
imageRef: ref,
|
|
149
|
+
imageId: image.Id,
|
|
150
|
+
repoDigest: output?.repoDigest,
|
|
151
|
+
tag: output?.tag ?? olds.tag ?? "latest",
|
|
152
|
+
builtAt: output?.builtAt ?? parseCreatedAt(image.Created),
|
|
153
|
+
};
|
|
154
|
+
}),
|
|
155
|
+
diff: Effect.fn(function* ({ id, instanceId, news, output, olds }) {
|
|
156
|
+
if (!isResolved(news) || !output)
|
|
157
|
+
return undefined;
|
|
158
|
+
if (dockerContextName(olds.context) !== dockerContextName(news.context)) {
|
|
159
|
+
return { action: "update" };
|
|
160
|
+
}
|
|
161
|
+
const { image } = yield* buildAndInspectImage(id, news, instanceId);
|
|
162
|
+
if (output?.imageId !== image.Id) {
|
|
163
|
+
return { action: "update" };
|
|
164
|
+
}
|
|
165
|
+
}),
|
|
166
|
+
reconcile: Effect.fn(function* ({ id, instanceId, news, session }) {
|
|
167
|
+
const context = dockerContextName(news.context);
|
|
168
|
+
const { name, tag, image, ref } = yield* buildAndInspectImage(id, news, instanceId);
|
|
169
|
+
let repoDigest;
|
|
170
|
+
let targetImageRef = ref;
|
|
171
|
+
if (news.registry && !news.skipPush) {
|
|
172
|
+
yield* session.note(`Pushing image to registry "${news.registry.server}"`);
|
|
173
|
+
targetImageRef = withRegistryHost(ref, news.registry);
|
|
174
|
+
const pushed = yield* docker.image.push(ref, news.registry, undefined, context);
|
|
175
|
+
const published = yield* docker.image.inspect(ref, context);
|
|
176
|
+
repoDigest = publishedRepoDigest(ref, pushed, published.RepoDigests, targetImageRef);
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
name,
|
|
180
|
+
imageRef: targetImageRef,
|
|
181
|
+
imageId: image.Id,
|
|
182
|
+
repoDigest,
|
|
183
|
+
tag,
|
|
184
|
+
builtAt: parseCreatedAt(image.Created),
|
|
185
|
+
};
|
|
186
|
+
}),
|
|
187
|
+
delete: Effect.fn(({ olds, output }) => docker.image
|
|
188
|
+
.remove(output.imageRef, undefined, dockerContextName(olds.context))
|
|
189
|
+
.pipe(Effect.catchReason("PlatformError", "NotFound", () => Effect.void))),
|
|
190
|
+
});
|
|
191
|
+
}));
|
|
192
|
+
//# sourceMappingURL=Image.js.map
|
package/lib/Image.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Image.js","sourceRoot":"","sources":["../src/Image.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { AlchemyContext } from "alchemy/AlchemyContext";
|
|
2
|
+
import * as Bundle from "alchemy/Bundle/Bundle";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as FileSystem from "effect/FileSystem";
|
|
5
|
+
import * as Path from "effect/Path";
|
|
6
|
+
import type * as rolldown from "rolldown";
|
|
7
|
+
import { Docker, type RegistryCredentials } from "./Docker.ts";
|
|
8
|
+
import { type InlineDockerfile } from "./Dockerfile.ts";
|
|
9
|
+
/**
|
|
10
|
+
* INTERNAL — registry-agnostic container image-source machinery shared by
|
|
11
|
+
* the container platforms (`AWS.ECS.*`, `AWS.EKS.*` via ECR, and
|
|
12
|
+
* `Kubernetes.*` workloads pushing to any registry).
|
|
13
|
+
*
|
|
14
|
+
* NOT exported from any barrel. Consumers import the module path directly.
|
|
15
|
+
*
|
|
16
|
+
* A platform's props separate the ENVIRONMENT (what the container is) from
|
|
17
|
+
* the PROGRAM (`main` — "and run my bundled Effect program in it"):
|
|
18
|
+
*
|
|
19
|
+
* - environment (at most one): `image` (registry ref) | `context` +
|
|
20
|
+
* `dockerfile`-as-path (docker build) | inline `dockerfile` content
|
|
21
|
+
* (`Dockerfile.inline`) | the default bun base when `main` stands alone.
|
|
22
|
+
* - `main` present → the bundle is injected into the environment (COPY +
|
|
23
|
+
* ENTRYPOINT) and pushed as a derived image. `main` absent → the
|
|
24
|
+
* environment runs verbatim: `image` is mirrored (docker pull → tag →
|
|
25
|
+
* push, content-addressed on the ref), a Dockerfile builds as-is.
|
|
26
|
+
*
|
|
27
|
+
* Where images land is an {@link ImageRegistryTarget}: ECR supplies one that
|
|
28
|
+
* auto-creates a private repository; a plain registry (a local `registry`
|
|
29
|
+
* container, GHCR, Docker Hub, …) supplies one that pushes to
|
|
30
|
+
* `<server>/<name>`.
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* Bundle an Effect program into a generated image. Alchemy bundles `main`
|
|
34
|
+
* with rolldown and bakes it into a Dockerfile generated from the
|
|
35
|
+
* environment (`image`, `dockerfile`, or the default bun base).
|
|
36
|
+
*/
|
|
37
|
+
export interface BundledImageSource {
|
|
38
|
+
/**
|
|
39
|
+
* Module entrypoint for the bundled program. This should typically be
|
|
40
|
+
* `import.meta.url` from an inline Effect program.
|
|
41
|
+
*/
|
|
42
|
+
main: string;
|
|
43
|
+
/**
|
|
44
|
+
* Environment image: used as the generated Dockerfile's `FROM`. Any
|
|
45
|
+
* registry ref works (private non-ECR registries require docker
|
|
46
|
+
* credentials on the build machine); the image must be able to run the
|
|
47
|
+
* bun runtime. Exclusive with {@link dockerfile} / {@link context}.
|
|
48
|
+
* @default "oven/bun:1"
|
|
49
|
+
*/
|
|
50
|
+
image?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Environment Dockerfile: a string is a PATH (built in {@link context},
|
|
53
|
+
* then the bundle is layered on top in a second stage); an
|
|
54
|
+
* {@link InlineDockerfile} is inline content used as the environment
|
|
55
|
+
* preamble (built with no context — its own `COPY`s are unsupported).
|
|
56
|
+
* The resulting environment must be able to run the bun runtime.
|
|
57
|
+
* Exclusive with {@link image}.
|
|
58
|
+
*/
|
|
59
|
+
dockerfile?: string | InlineDockerfile;
|
|
60
|
+
/**
|
|
61
|
+
* Build context for a path {@link dockerfile} environment. Exclusive
|
|
62
|
+
* with {@link image} and inline dockerfiles.
|
|
63
|
+
*/
|
|
64
|
+
context?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Named export to load from `main`.
|
|
67
|
+
* @default "default"
|
|
68
|
+
*/
|
|
69
|
+
handler?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Bundler configuration for the entrypoint. Unused code is tree-shaken.
|
|
72
|
+
* `effect`, alchemy, and `@distilled.cloud` are marked pure so unused
|
|
73
|
+
* parts prune more aggressively. List extra packages with
|
|
74
|
+
* `pure.packages`, or disable with `pure: false`.
|
|
75
|
+
*/
|
|
76
|
+
build?: Bundle.BundleConfig;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Build the image from the user's own Dockerfile and build context — no
|
|
80
|
+
* Effect program is bundled.
|
|
81
|
+
*/
|
|
82
|
+
export interface DockerfileImageSource {
|
|
83
|
+
/**
|
|
84
|
+
* Docker build context directory. Optional when {@link dockerfile} is
|
|
85
|
+
* inline content (which builds with an empty context).
|
|
86
|
+
*/
|
|
87
|
+
context?: string;
|
|
88
|
+
/**
|
|
89
|
+
* Path to the Dockerfile relative to the cwd (NOT the context), or
|
|
90
|
+
* {@link InlineDockerfile} content. The Dockerfile must define its own
|
|
91
|
+
* `CMD`/`ENTRYPOINT` (no program is injected).
|
|
92
|
+
* @default `${context}/Dockerfile`
|
|
93
|
+
*/
|
|
94
|
+
dockerfile?: string | InlineDockerfile;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Run a pre-built registry image. Registry-backed platforms may mirror it
|
|
98
|
+
* into their own registry (ECR: docker pull → tag → push).
|
|
99
|
+
*/
|
|
100
|
+
export interface RegistryImageSource {
|
|
101
|
+
/**
|
|
102
|
+
* A pre-built image reference, e.g.
|
|
103
|
+
* `public.ecr.aws/docker/library/busybox:stable`.
|
|
104
|
+
*/
|
|
105
|
+
image: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The image-source union. Discriminated by presence: exactly one of
|
|
109
|
+
* `main`, `context`, or `image`.
|
|
110
|
+
*/
|
|
111
|
+
export type ImageSourceProps = BundledImageSource | DockerfileImageSource | RegistryImageSource;
|
|
112
|
+
/** Loose bag shape used to sniff which source variant a props object is. */
|
|
113
|
+
export interface ImageSourceLike {
|
|
114
|
+
main?: string;
|
|
115
|
+
handler?: string;
|
|
116
|
+
build?: BundledImageSource["build"];
|
|
117
|
+
context?: string;
|
|
118
|
+
dockerfile?: string | InlineDockerfile;
|
|
119
|
+
image?: string;
|
|
120
|
+
}
|
|
121
|
+
export type ImageSourceKind = "main" | "context" | "image";
|
|
122
|
+
/**
|
|
123
|
+
* Which image source a props bag declares. `main` always wins (the other
|
|
124
|
+
* fields then describe its ENVIRONMENT); without `main`, `image` is the
|
|
125
|
+
* mirrored-verbatim source and any `context`/`dockerfile` (path or inline)
|
|
126
|
+
* is an external docker build.
|
|
127
|
+
*/
|
|
128
|
+
export declare const imageSourceKind: (source: ImageSourceLike) => ImageSourceKind | undefined;
|
|
129
|
+
/**
|
|
130
|
+
* Validate environment-source exclusivity. Dies (plan-time defect) on
|
|
131
|
+
* `image`+`dockerfile`, `image`+`context`, or inline-`dockerfile`+`context`.
|
|
132
|
+
*/
|
|
133
|
+
export declare const validateImageSource: (id: string, source: ImageSourceLike) => Effect.Effect<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Where a resolved image is pushed. Each field is an Effect so a target can
|
|
136
|
+
* create resources lazily (ECR creates the repository on first use).
|
|
137
|
+
*/
|
|
138
|
+
export interface ImageRegistryTarget<R = never> {
|
|
139
|
+
/** The repository URI images are tagged into (`<repositoryUri>:<hash>`). */
|
|
140
|
+
readonly repositoryUri: Effect.Effect<string, any, R>;
|
|
141
|
+
/**
|
|
142
|
+
* Whether the content-addressed tag is already in the registry. `true`
|
|
143
|
+
* skips the build and push entirely.
|
|
144
|
+
*/
|
|
145
|
+
readonly hasTag: (tag: string) => Effect.Effect<boolean, any, R>;
|
|
146
|
+
/**
|
|
147
|
+
* Push credentials. `undefined` pushes with the build machine's own
|
|
148
|
+
* Docker configuration (`docker login`, credential helpers).
|
|
149
|
+
*/
|
|
150
|
+
readonly credentials: Effect.Effect<RegistryCredentials | undefined, any, R>;
|
|
151
|
+
}
|
|
152
|
+
export interface ResolveContainerImageOptions {
|
|
153
|
+
/** Logical resource id — keys the stable build-context directory. */
|
|
154
|
+
id: string;
|
|
155
|
+
/**
|
|
156
|
+
* The props bag carrying the image source fields (`main` / `context` /
|
|
157
|
+
* `image` plus their modifiers).
|
|
158
|
+
*/
|
|
159
|
+
source: ImageSourceLike;
|
|
160
|
+
/**
|
|
161
|
+
* Target image platform.
|
|
162
|
+
* @default "linux/amd64"
|
|
163
|
+
*/
|
|
164
|
+
platform?: string;
|
|
165
|
+
/**
|
|
166
|
+
* Port the generated Dockerfile should `ENV PORT=` + `EXPOSE`
|
|
167
|
+
* (`main` source only).
|
|
168
|
+
*/
|
|
169
|
+
port?: number;
|
|
170
|
+
/**
|
|
171
|
+
* True when the resource was declared without an inline Effect impl —
|
|
172
|
+
* `main` is then bundled as-is without the virtual-entry bootstrap.
|
|
173
|
+
*/
|
|
174
|
+
isExternal?: boolean;
|
|
175
|
+
/**
|
|
176
|
+
* The virtual-entry bootstrap wrapped around `main` for Effect-native
|
|
177
|
+
* programs: receives the resolved entry import path and returns the
|
|
178
|
+
* generated entry module source.
|
|
179
|
+
*/
|
|
180
|
+
bootstrap: (importPath: string) => string;
|
|
181
|
+
/** Plan-status session used to emit build/push progress notes. */
|
|
182
|
+
session: {
|
|
183
|
+
note: (message: string) => Effect.Effect<void>;
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Content hash for the sources whose identity is computable WITHOUT running
|
|
188
|
+
* a bundler:
|
|
189
|
+
*
|
|
190
|
+
* - `context` — hash of the build-context directory + Dockerfile content +
|
|
191
|
+
* platform.
|
|
192
|
+
* - `image` — hash of the image reference + platform (re-mirror only when
|
|
193
|
+
* the ref changes).
|
|
194
|
+
* - `main` — `undefined`: the hash comes from the bundle output, so it is
|
|
195
|
+
* only known inside `resolve`.
|
|
196
|
+
*
|
|
197
|
+
* Providers use this in `diff` to surface content drift (files changed under
|
|
198
|
+
* an unchanged `context` path) as an update.
|
|
199
|
+
*/
|
|
200
|
+
export declare const computeStaticSourceHash: (source: ImageSourceLike, platform?: string | undefined) => Effect.Effect<string | undefined, import("effect/PlatformError").PlatformError, FileSystem.FileSystem | Path.Path>;
|
|
201
|
+
/**
|
|
202
|
+
* Init-time constructor for the image-source resolver. Resolves the services
|
|
203
|
+
* that are only available at provider-layer construction (Docker, the
|
|
204
|
+
* `.alchemy` directory, the rolldown virtual-entry plugin) and returns
|
|
205
|
+
* `resolve` (build/mirror + push to an {@link ImageRegistryTarget}), `hash`,
|
|
206
|
+
* and `watchMain`.
|
|
207
|
+
*/
|
|
208
|
+
export declare const makeContainerImageSource: Effect.Effect<{
|
|
209
|
+
resolve: <R>(options: ResolveContainerImageOptions, target: ImageRegistryTarget<R>) => Effect.Effect<{
|
|
210
|
+
imageUri: string;
|
|
211
|
+
repositoryUri: string;
|
|
212
|
+
codeHash: string;
|
|
213
|
+
}, any, R | FileSystem.FileSystem | Path.Path | import("alchemy/Stack").Stack | import("alchemy/Stage").Stage>;
|
|
214
|
+
hash: (options: {
|
|
215
|
+
source: ImageSourceLike;
|
|
216
|
+
platform?: string;
|
|
217
|
+
port?: number;
|
|
218
|
+
isExternal?: boolean;
|
|
219
|
+
bootstrap: (importPath: string) => string;
|
|
220
|
+
}) => Effect.Effect<string | undefined, Bundle.BundleError | import("effect/PlatformError").PlatformError, FileSystem.FileSystem | Path.Path>;
|
|
221
|
+
watchMain: (options: {
|
|
222
|
+
source: BundledImageSource;
|
|
223
|
+
isExternal?: boolean;
|
|
224
|
+
bootstrap: (importPath: string) => string;
|
|
225
|
+
}) => Effect.Effect<{
|
|
226
|
+
inputOptions: rolldown.InputOptions;
|
|
227
|
+
outputOptions: rolldown.OutputOptions;
|
|
228
|
+
extra: Bundle.BundleConfig | undefined;
|
|
229
|
+
}, import("effect/PlatformError").PlatformError, FileSystem.FileSystem | Path.Path>;
|
|
230
|
+
}, never, AlchemyContext | Docker | Path.Path>;
|
|
231
|
+
/** The resolver service returned by {@link makeContainerImageSource}. */
|
|
232
|
+
export interface ContainerImageSource extends Effect.Success<typeof makeContainerImageSource> {
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=ImageSource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageSource.d.ts","sourceRoot":"","sources":["../src/ImageSource.ts"],"names":[],"mappings":"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"}
|