@codedazur/cdk-docker-cluster 0.4.0 → 0.5.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @codedazur/cdk-docker-cluster
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`d1f3d51`](https://github.com/codedazur/toolkit/commit/d1f3d512d31d659ffdc115147d9631057fe8d073) Thanks [@thijsdaniels](https://github.com/thijsdaniels)! - Support for a custom domain name was added.
8
+
9
+ ### Patch Changes
10
+
11
+ - [`17034ee`](https://github.com/codedazur/toolkit/commit/17034ee5fcbc026fc779a12130572d515d2b8298) Thanks [@thijsdaniels](https://github.com/thijsdaniels)! - Dependency versions were made explicit.
12
+
13
+ - [`737fe0d`](https://github.com/codedazur/toolkit/commit/737fe0ddd4d353db1e005d2dab886a4a60bc02d8) Thanks [@thijsdaniels](https://github.com/thijsdaniels)! - The build environment prop was renamed to arguments.
14
+
15
+ - Updated dependencies [[`17034ee`](https://github.com/codedazur/toolkit/commit/17034ee5fcbc026fc779a12130572d515d2b8298), [`d1f3d51`](https://github.com/codedazur/toolkit/commit/d1f3d512d31d659ffdc115147d9631057fe8d073)]:
16
+ - @codedazur/cdk-site-distribution@0.1.0
17
+
3
18
  ## 0.4.0
4
19
 
5
20
  ### Minor Changes
package/README.md CHANGED
@@ -2,16 +2,112 @@
2
2
 
3
3
  This construct creates a load balanced Fargate service, for which it builds a Docker image from a local directory. A CloudFront distribution is connected to the load balancer.
4
4
 
5
+ ## Examples
6
+
7
+ The minimum needed to get a DockerCluster up and running is a path to the source directory that contains a Dockerfile, relative to the CDK app, and the port on which your container needs to be accessible.
8
+
5
9
  ```ts
6
- new DockerCluster({
7
- path: "../../", // path to Docker build context
8
- file: "apps/myApp/DockerFile", // path to Dockerfile
10
+ new DockerCluster(this, "DockerCluster", {
11
+ source: "../path/to/source",
9
12
  port: 3000,
13
+ });
14
+ ```
15
+
16
+ ### With Monorepo Build
17
+
18
+ If your Dockerfile is not located directly in the build context directory, which is common for monorepositories, you can provide the path to the Dockerfile relative to the source directory.
19
+
20
+ ```ts
21
+ new DockerCluster({
22
+ source: {
23
+ directory: "../path/to/source",
24
+ file: "./apps/myApp/DockerFile",
25
+ },
26
+ // ...
27
+ });
28
+ ```
29
+
30
+ ### With Arguments and Secrets
31
+
32
+ Additionally, if your Dockerfile requires arguments and/or secrets, you can provide those as well.
33
+
34
+ ```ts
35
+ new DockerCluster({
36
+ source: {
37
+ // ...
38
+ arguments: {
39
+ MY_BUILD_ARGUMENT: "foo",
40
+ },
41
+ secrets: {
42
+ myBuildSecret: DockerBuildSecret.fromSrc("./foo"),
43
+ },
44
+ },
45
+ // ...
46
+ });
47
+ ```
48
+
49
+ ### With ContainerImage
50
+
51
+ Alternatively, you can provide your own `ContainerImage` instance. There are many ways to construct a `ContainerImage`. For example, you can create one from an asset and take full control over how CDK builds your Docker image.
52
+
53
+ ```ts
54
+ new DockerCluster({
55
+ source: ContainerImage.fromAsset("../path/to/source", {
56
+ // ...
57
+ }),
58
+ // ...
59
+ });
60
+ ```
61
+
62
+ Or, if you want to build your Docker image outside of CDK, you can create a `ContainerImage` from a path to your image's tarball.
63
+
64
+ ```ts
65
+ new DockerCluster({
66
+ source: ContainerImage.fromTarball("./path/to/image.tar"),
67
+ // ...
68
+ });
69
+ ```
70
+
71
+ Or if the image you need is published to a registry, you can create your
72
+ `ContainerImage` from a registry path. You can provide credentials in case the registry is private.
73
+
74
+ ```ts
75
+ new DockerCluster({
76
+ source: ContainerImage.fromRegistry("node:20"),
77
+ // ...
78
+ });
79
+ ```
80
+
81
+ Finally, you can create a `ContainerImage` from an image that you have published to an ECR repository.
82
+
83
+ ```ts
84
+ new DockerCluster({
85
+ source: ContainerImage.fromEcrRepository(myRespository, "my-tag"),
86
+ // ...
87
+ });
88
+ ```
89
+
90
+ ### With Scaling
91
+
92
+ The `DockerCluster` construct supports both vertical and horizontal scaling.
93
+
94
+ ```ts
95
+ new DockerCluster(this, "DockerCluster", {
96
+ // ...
10
97
  cpu: 1024, // 1vCPU
11
98
  memory: 4096, // 4GB
12
- tasks: { minimum: 1, maximum: 10 },
13
- secrets: {
14
- foo: DockerBuildSecret.fromSrc("./foo"),
99
+ tasks: 3,
100
+ });
101
+ ```
102
+
103
+ Horizontal auto-scaling is also supported.
104
+
105
+ ```ts
106
+ new DockerCluster(this, "DockerCluster", {
107
+ // ...
108
+ tasks: {
109
+ minimum: 1,
110
+ maximum: 5,
15
111
  },
16
112
  });
17
113
  ```
package/dist/index.d.mts CHANGED
@@ -1,10 +1,11 @@
1
- import { ApplicationLoadBalancedFargateServiceProps } from 'aws-cdk-lib/aws-ecs-patterns';
1
+ import * as aws_cdk_lib_aws_ecs from 'aws-cdk-lib/aws-ecs';
2
+ import { ContainerImage } from 'aws-cdk-lib/aws-ecs';
3
+ import { SiteDistributionProps, SiteDistribution } from '@codedazur/cdk-site-distribution';
4
+ import { ApplicationLoadBalancedFargateServiceProps, ApplicationLoadBalancedFargateService } from 'aws-cdk-lib/aws-ecs-patterns';
2
5
  import { Construct } from 'constructs';
3
6
 
4
7
  interface DockerClusterProps {
5
- path: string;
6
- file?: string;
7
- secrets?: Record<string, string>;
8
+ source: string | SourceProps | ContainerImage;
8
9
  port?: number;
9
10
  tasks?: number | {
10
11
  minimum: number;
@@ -12,17 +13,30 @@ interface DockerClusterProps {
12
13
  };
13
14
  cpu?: ApplicationLoadBalancedFargateServiceProps["cpu"];
14
15
  memory?: ApplicationLoadBalancedFargateServiceProps["memoryLimitMiB"];
15
- environment?: {
16
- buildtime?: Record<string, string>;
17
- runtime?: Record<string, string>;
18
- };
16
+ distribution?: Omit<SiteDistributionProps, "origin">;
17
+ }
18
+ interface SourceProps {
19
+ directory: string;
20
+ exclude?: string[];
21
+ file?: string;
22
+ arguments?: Record<string, string>;
23
+ secrets?: Record<string, string>;
19
24
  }
20
25
  /**
21
26
  * An Docker cluster on a load balanced Fargate service on EC2, using an image
22
27
  * built from a Dockerfile in a directory and pushed to ECR.
23
28
  */
24
29
  declare class DockerCluster extends Construct {
30
+ protected readonly props: DockerClusterProps;
31
+ readonly domain?: string;
32
+ readonly image: ContainerImage;
33
+ readonly service: ApplicationLoadBalancedFargateService;
34
+ readonly distribution: SiteDistribution;
25
35
  constructor(scope: Construct, id: string, props: DockerClusterProps);
36
+ protected createImage(source: string | SourceProps): aws_cdk_lib_aws_ecs.AssetImage;
37
+ protected createService(): ApplicationLoadBalancedFargateService;
38
+ protected createDistribution(): SiteDistribution;
39
+ protected getOutputDirectory(): string;
26
40
  }
27
41
 
28
- export { DockerCluster, DockerClusterProps };
42
+ export { DockerCluster, type DockerClusterProps };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import { ApplicationLoadBalancedFargateServiceProps } from 'aws-cdk-lib/aws-ecs-patterns';
1
+ import * as aws_cdk_lib_aws_ecs from 'aws-cdk-lib/aws-ecs';
2
+ import { ContainerImage } from 'aws-cdk-lib/aws-ecs';
3
+ import { SiteDistributionProps, SiteDistribution } from '@codedazur/cdk-site-distribution';
4
+ import { ApplicationLoadBalancedFargateServiceProps, ApplicationLoadBalancedFargateService } from 'aws-cdk-lib/aws-ecs-patterns';
2
5
  import { Construct } from 'constructs';
3
6
 
4
7
  interface DockerClusterProps {
5
- path: string;
6
- file?: string;
7
- secrets?: Record<string, string>;
8
+ source: string | SourceProps | ContainerImage;
8
9
  port?: number;
9
10
  tasks?: number | {
10
11
  minimum: number;
@@ -12,17 +13,30 @@ interface DockerClusterProps {
12
13
  };
13
14
  cpu?: ApplicationLoadBalancedFargateServiceProps["cpu"];
14
15
  memory?: ApplicationLoadBalancedFargateServiceProps["memoryLimitMiB"];
15
- environment?: {
16
- buildtime?: Record<string, string>;
17
- runtime?: Record<string, string>;
18
- };
16
+ distribution?: Omit<SiteDistributionProps, "origin">;
17
+ }
18
+ interface SourceProps {
19
+ directory: string;
20
+ exclude?: string[];
21
+ file?: string;
22
+ arguments?: Record<string, string>;
23
+ secrets?: Record<string, string>;
19
24
  }
20
25
  /**
21
26
  * An Docker cluster on a load balanced Fargate service on EC2, using an image
22
27
  * built from a Dockerfile in a directory and pushed to ECR.
23
28
  */
24
29
  declare class DockerCluster extends Construct {
30
+ protected readonly props: DockerClusterProps;
31
+ readonly domain?: string;
32
+ readonly image: ContainerImage;
33
+ readonly service: ApplicationLoadBalancedFargateService;
34
+ readonly distribution: SiteDistribution;
25
35
  constructor(scope: Construct, id: string, props: DockerClusterProps);
36
+ protected createImage(source: string | SourceProps): aws_cdk_lib_aws_ecs.AssetImage;
37
+ protected createService(): ApplicationLoadBalancedFargateService;
38
+ protected createDistribution(): SiteDistribution;
39
+ protected getOutputDirectory(): string;
26
40
  }
27
41
 
28
- export { DockerCluster, DockerClusterProps };
42
+ export { DockerCluster, type DockerClusterProps };
package/dist/index.js CHANGED
@@ -25,7 +25,9 @@ __export(src_exports, {
25
25
  module.exports = __toCommonJS(src_exports);
26
26
 
27
27
  // src/constructs/DockerCluster.ts
28
- var import_cdk_cache_invalidator = require("@codedazur/cdk-cache-invalidator");
28
+ var import_cdk_site_distribution = require("@codedazur/cdk-site-distribution");
29
+ var import_aws_cdk_lib = require("aws-cdk-lib");
30
+ var import_aws_certificatemanager = require("aws-cdk-lib/aws-certificatemanager");
29
31
  var import_aws_cloudfront = require("aws-cdk-lib/aws-cloudfront");
30
32
  var import_aws_cloudfront_origins = require("aws-cdk-lib/aws-cloudfront-origins");
31
33
  var import_aws_ecr_assets = require("aws-cdk-lib/aws-ecr-assets");
@@ -34,53 +36,68 @@ var import_aws_ecs_patterns = require("aws-cdk-lib/aws-ecs-patterns");
34
36
  var import_constructs = require("constructs");
35
37
  var DockerCluster = class extends import_constructs.Construct {
36
38
  constructor(scope, id, props) {
37
- var _a, _b, _c;
38
39
  super(scope, id);
39
- const image = new import_aws_ecr_assets.DockerImageAsset(this, "Image", {
40
- directory: props.path,
41
- file: props.file,
42
- exclude: ["**/cdk.out"],
43
- buildSecrets: props.secrets,
44
- platform: import_aws_ecr_assets.Platform.LINUX_AMD64,
45
- buildArgs: (_a = props.environment) == null ? void 0 : _a.buildtime
40
+ this.props = props;
41
+ this.image = this.props.source instanceof import_aws_ecs.ContainerImage ? this.props.source : this.createImage(this.props.source);
42
+ this.service = this.createService();
43
+ this.distribution = this.createDistribution();
44
+ }
45
+ createImage(source) {
46
+ const props = {
47
+ exclude: [`**/${this.getOutputDirectory()}`],
48
+ platform: import_aws_ecr_assets.Platform.LINUX_AMD64
49
+ };
50
+ if (typeof source === "string") {
51
+ return import_aws_ecs.ContainerImage.fromAsset(source, props);
52
+ }
53
+ return import_aws_ecs.ContainerImage.fromAsset(source.directory, {
54
+ ...props,
55
+ file: source.file,
56
+ buildArgs: source.arguments,
57
+ buildSecrets: source.secrets
46
58
  });
47
- const desiredTasks = typeof props.tasks === "number" ? props.tasks : (_b = props.tasks) == null ? void 0 : _b.minimum;
48
- const fargate = new import_aws_ecs_patterns.ApplicationLoadBalancedFargateService(this, "Service", {
59
+ }
60
+ createService() {
61
+ var _a;
62
+ const desiredTasks = typeof this.props.tasks === "number" ? this.props.tasks : (_a = this.props.tasks) == null ? void 0 : _a.minimum;
63
+ const service = new import_aws_ecs_patterns.ApplicationLoadBalancedFargateService(this, "Service", {
49
64
  cluster: new import_aws_ecs.Cluster(this, "Cluster"),
50
- cpu: props.cpu,
51
- memoryLimitMiB: props.memory,
65
+ cpu: this.props.cpu,
66
+ memoryLimitMiB: this.props.memory,
52
67
  desiredCount: desiredTasks,
53
68
  taskImageOptions: {
54
- // image: ContainerImage.fromEcrRepository(image.repository, image.imageTag),
55
- image: import_aws_ecs.ContainerImage.fromDockerImageAsset(image),
56
- containerPort: props.port,
57
- environment: (_c = props.environment) == null ? void 0 : _c.runtime
69
+ image: this.image,
70
+ containerPort: this.props.port
58
71
  },
59
72
  circuitBreaker: {
60
73
  enable: true,
61
74
  rollback: true
62
- }
63
- // @todo certificate: ...
64
- // @todo publicLoadBalancer: false,
75
+ },
76
+ publicLoadBalancer: false,
77
+ certificate: new import_aws_certificatemanager.Certificate(this, "Certificate", {
78
+ domainName: "example.com"
79
+ })
65
80
  });
66
- if (typeof props.tasks === "object") {
67
- fargate.service.autoScaleTaskCount({
68
- minCapacity: props.tasks.minimum,
69
- maxCapacity: props.tasks.maximum
81
+ if (typeof this.props.tasks === "object") {
82
+ this.service.service.autoScaleTaskCount({
83
+ minCapacity: this.props.tasks.minimum,
84
+ maxCapacity: this.props.tasks.maximum
70
85
  });
71
86
  }
72
- const distribution = new import_aws_cloudfront.Distribution(this, "Distribution", {
73
- defaultBehavior: {
74
- origin: new import_aws_cloudfront_origins.LoadBalancerV2Origin(fargate.loadBalancer, {
75
- protocolPolicy: import_aws_cloudfront.OriginProtocolPolicy.HTTP_ONLY
76
- // @todo OriginProtocolPolicy.HTTPS_ONLY
77
- })
78
- }
79
- });
80
- new import_cdk_cache_invalidator.CacheInvalidator(this, "CacheInvalidator", {
81
- distribution
87
+ return service;
88
+ }
89
+ createDistribution() {
90
+ return new import_cdk_site_distribution.SiteDistribution(this, "Distribution", {
91
+ ...this.props.distribution,
92
+ origin: new import_aws_cloudfront_origins.LoadBalancerV2Origin(this.service.loadBalancer, {
93
+ protocolPolicy: import_aws_cloudfront.OriginProtocolPolicy.HTTP_ONLY
94
+ })
82
95
  });
83
96
  }
97
+ getOutputDirectory() {
98
+ var _a, _b;
99
+ return (_b = (_a = import_aws_cdk_lib.App.of(this)) == null ? void 0 : _a.outdir) != null ? _b : "cdk.out";
100
+ }
84
101
  };
85
102
  // Annotate the CommonJS export names for ESM import in node:
86
103
  0 && (module.exports = {
package/dist/index.mjs CHANGED
@@ -1,8 +1,12 @@
1
1
  // src/constructs/DockerCluster.ts
2
- import { CacheInvalidator } from "@codedazur/cdk-cache-invalidator";
3
- import { Distribution, OriginProtocolPolicy } from "aws-cdk-lib/aws-cloudfront";
2
+ import {
3
+ SiteDistribution
4
+ } from "@codedazur/cdk-site-distribution";
5
+ import { App } from "aws-cdk-lib";
6
+ import { Certificate } from "aws-cdk-lib/aws-certificatemanager";
7
+ import { OriginProtocolPolicy } from "aws-cdk-lib/aws-cloudfront";
4
8
  import { LoadBalancerV2Origin } from "aws-cdk-lib/aws-cloudfront-origins";
5
- import { DockerImageAsset, Platform } from "aws-cdk-lib/aws-ecr-assets";
9
+ import { Platform } from "aws-cdk-lib/aws-ecr-assets";
6
10
  import { Cluster, ContainerImage } from "aws-cdk-lib/aws-ecs";
7
11
  import {
8
12
  ApplicationLoadBalancedFargateService
@@ -10,53 +14,68 @@ import {
10
14
  import { Construct } from "constructs";
11
15
  var DockerCluster = class extends Construct {
12
16
  constructor(scope, id, props) {
13
- var _a, _b, _c;
14
17
  super(scope, id);
15
- const image = new DockerImageAsset(this, "Image", {
16
- directory: props.path,
17
- file: props.file,
18
- exclude: ["**/cdk.out"],
19
- buildSecrets: props.secrets,
20
- platform: Platform.LINUX_AMD64,
21
- buildArgs: (_a = props.environment) == null ? void 0 : _a.buildtime
18
+ this.props = props;
19
+ this.image = this.props.source instanceof ContainerImage ? this.props.source : this.createImage(this.props.source);
20
+ this.service = this.createService();
21
+ this.distribution = this.createDistribution();
22
+ }
23
+ createImage(source) {
24
+ const props = {
25
+ exclude: [`**/${this.getOutputDirectory()}`],
26
+ platform: Platform.LINUX_AMD64
27
+ };
28
+ if (typeof source === "string") {
29
+ return ContainerImage.fromAsset(source, props);
30
+ }
31
+ return ContainerImage.fromAsset(source.directory, {
32
+ ...props,
33
+ file: source.file,
34
+ buildArgs: source.arguments,
35
+ buildSecrets: source.secrets
22
36
  });
23
- const desiredTasks = typeof props.tasks === "number" ? props.tasks : (_b = props.tasks) == null ? void 0 : _b.minimum;
24
- const fargate = new ApplicationLoadBalancedFargateService(this, "Service", {
37
+ }
38
+ createService() {
39
+ var _a;
40
+ const desiredTasks = typeof this.props.tasks === "number" ? this.props.tasks : (_a = this.props.tasks) == null ? void 0 : _a.minimum;
41
+ const service = new ApplicationLoadBalancedFargateService(this, "Service", {
25
42
  cluster: new Cluster(this, "Cluster"),
26
- cpu: props.cpu,
27
- memoryLimitMiB: props.memory,
43
+ cpu: this.props.cpu,
44
+ memoryLimitMiB: this.props.memory,
28
45
  desiredCount: desiredTasks,
29
46
  taskImageOptions: {
30
- // image: ContainerImage.fromEcrRepository(image.repository, image.imageTag),
31
- image: ContainerImage.fromDockerImageAsset(image),
32
- containerPort: props.port,
33
- environment: (_c = props.environment) == null ? void 0 : _c.runtime
47
+ image: this.image,
48
+ containerPort: this.props.port
34
49
  },
35
50
  circuitBreaker: {
36
51
  enable: true,
37
52
  rollback: true
38
- }
39
- // @todo certificate: ...
40
- // @todo publicLoadBalancer: false,
53
+ },
54
+ publicLoadBalancer: false,
55
+ certificate: new Certificate(this, "Certificate", {
56
+ domainName: "example.com"
57
+ })
41
58
  });
42
- if (typeof props.tasks === "object") {
43
- fargate.service.autoScaleTaskCount({
44
- minCapacity: props.tasks.minimum,
45
- maxCapacity: props.tasks.maximum
59
+ if (typeof this.props.tasks === "object") {
60
+ this.service.service.autoScaleTaskCount({
61
+ minCapacity: this.props.tasks.minimum,
62
+ maxCapacity: this.props.tasks.maximum
46
63
  });
47
64
  }
48
- const distribution = new Distribution(this, "Distribution", {
49
- defaultBehavior: {
50
- origin: new LoadBalancerV2Origin(fargate.loadBalancer, {
51
- protocolPolicy: OriginProtocolPolicy.HTTP_ONLY
52
- // @todo OriginProtocolPolicy.HTTPS_ONLY
53
- })
54
- }
55
- });
56
- new CacheInvalidator(this, "CacheInvalidator", {
57
- distribution
65
+ return service;
66
+ }
67
+ createDistribution() {
68
+ return new SiteDistribution(this, "Distribution", {
69
+ ...this.props.distribution,
70
+ origin: new LoadBalancerV2Origin(this.service.loadBalancer, {
71
+ protocolPolicy: OriginProtocolPolicy.HTTP_ONLY
72
+ })
58
73
  });
59
74
  }
75
+ getOutputDirectory() {
76
+ var _a, _b;
77
+ return (_b = (_a = App.of(this)) == null ? void 0 : _a.outdir) != null ? _b : "cdk.out";
78
+ }
60
79
  };
61
80
  export {
62
81
  DockerCluster
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codedazur/cdk-docker-cluster",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "main": ".dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
@@ -22,22 +22,17 @@
22
22
  "types": "tsc --noEmit",
23
23
  "test": "vitest run --passWithNoTests"
24
24
  },
25
- "dependencies": {
26
- "@codedazur/cdk-cache-invalidator": "*"
27
- },
28
25
  "peerDependencies": {
29
26
  "aws-cdk-lib": ">=2",
30
27
  "constructs": ">=10"
31
28
  },
29
+ "dependencies": {
30
+ "@codedazur/cdk-site-distribution": "^0.1.0"
31
+ },
32
32
  "devDependencies": {
33
- "@codedazur/eslint-config": "*",
34
- "@codedazur/tsconfig": "*",
35
- "@types/node": "^20.14.2",
36
- "aws-cdk-lib": "^2.145.0",
33
+ "@types/node": "^20.14.9",
34
+ "aws-cdk-lib": "^2.147.2",
37
35
  "constructs": "^10.3.0",
38
- "esbuild": "^0.20.2",
39
- "eslint": "^8.30.0",
40
- "tsconfig": "*",
41
- "typescript": "^5.4.5"
36
+ "esbuild": "^0.21.5"
42
37
  }
43
38
  }
package/tsconfig.json CHANGED
@@ -1,5 +1,3 @@
1
1
  {
2
- "extends": "@codedazur/tsconfig/cdk.json",
3
- "include": ["."],
4
- "exclude": ["dist", "build", "node_modules"]
2
+ "extends": "@codedazur/tsconfig/cdk.json"
5
3
  }