Skip to content

Commit b4532cb

Browse files
author
Tarun Belani
committed
feat(imagebuilder-alpha): add support for Container Recipe Construct
1 parent 183ec35 commit b4532cb

File tree

48 files changed

+5099
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+5099
-0
lines changed

packages/@aws-cdk/aws-imagebuilder-alpha/README.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,181 @@ EC2 Image Builder supports AWS-managed components for common tasks, AWS Marketpl
3636
that you create. Components run during specific workflow phases: build and validate phases during the build stage, and
3737
test phase during the test stage.
3838

39+
### Container Recipe
40+
41+
A container recipe is similar to an image recipe but specifically for container images. It defines the base container
42+
image and components applied to produce the desired configuration for the output container image. Container recipes work
43+
with Docker images from DockerHub, Amazon ECR, or Amazon-managed container images as starting points.
44+
45+
#### Container Recipe Basic Usage
46+
47+
Create a container recipe with the required base image and target repository:
48+
49+
```ts
50+
const containerRecipe = new imagebuilder.ContainerRecipe(this, 'MyContainerRecipe', {
51+
baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'),
52+
targetRepository: imagebuilder.Repository.fromEcr(
53+
ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo')
54+
)
55+
});
56+
```
57+
58+
#### Container Recipe Base Images
59+
60+
##### DockerHub Images
61+
62+
Using public Docker Hub images:
63+
64+
```ts
65+
const containerRecipe = new imagebuilder.ContainerRecipe(this, 'DockerHubContainerRecipe', {
66+
baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'),
67+
targetRepository: imagebuilder.Repository.fromEcr(
68+
ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo')
69+
)
70+
});
71+
```
72+
73+
##### ECR Images
74+
75+
Using images from your own ECR repositories:
76+
77+
```ts
78+
const sourceRepo = ecr.Repository.fromRepositoryName(this, 'SourceRepo', 'my-base-image');
79+
const targetRepo = ecr.Repository.fromRepositoryName(this, 'TargetRepo', 'my-container-repo');
80+
81+
const containerRecipe = new imagebuilder.ContainerRecipe(this, 'EcrContainerRecipe', {
82+
baseImage: imagebuilder.BaseContainerImage.fromEcr(sourceRepo, '1.0.0'),
83+
targetRepository: imagebuilder.Repository.fromEcr(targetRepo)
84+
});
85+
```
86+
87+
##### ECR Public Images
88+
89+
Using images from Amazon ECR Public:
90+
91+
```ts
92+
const containerRecipe = new imagebuilder.ContainerRecipe(this, 'EcrPublicContainerRecipe', {
93+
baseImage: imagebuilder.BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', '2023'),
94+
targetRepository: imagebuilder.Repository.fromEcr(
95+
ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo')
96+
)
97+
});
98+
```
99+
100+
#### Container Recipe Components
101+
102+
##### Custom Components in Container Recipes
103+
104+
Add your own components to the container recipe:
105+
106+
```ts
107+
const customComponent = new imagebuilder.Component(this, 'MyComponent', {
108+
platform: imagebuilder.Platform.LINUX,
109+
data: imagebuilder.ComponentData.fromJsonObject({
110+
schemaVersion: imagebuilder.ComponentSchemaVersion.V1_0,
111+
phases: [
112+
{
113+
name: imagebuilder.ComponentPhaseName.BUILD,
114+
steps: [
115+
{
116+
name: 'install-app',
117+
action: imagebuilder.ComponentAction.EXECUTE_BASH,
118+
inputs: {
119+
commands: ['yum install -y my-container-application']
120+
}
121+
}
122+
]
123+
}
124+
]
125+
})
126+
});
127+
128+
const containerRecipe = new imagebuilder.ContainerRecipe(this, 'ComponentContainerRecipe', {
129+
baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'),
130+
targetRepository: imagebuilder.Repository.fromEcr(
131+
ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo')
132+
),
133+
components: [
134+
{
135+
component: customComponent
136+
}
137+
]
138+
});
139+
```
140+
141+
##### AWS-Managed Components in Container Recipes
142+
143+
Use pre-built AWS components:
144+
145+
```ts
146+
const containerRecipe = new imagebuilder.ContainerRecipe(this, 'AwsManagedContainerRecipe', {
147+
baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'),
148+
targetRepository: imagebuilder.Repository.fromEcr(
149+
ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo')
150+
),
151+
components: [
152+
{
153+
component: imagebuilder.AwsManagedComponent.updateOS(this, 'UpdateOS', {
154+
platform: imagebuilder.Platform.LINUX
155+
})
156+
},
157+
{
158+
component: imagebuilder.AwsManagedComponent.awsCliV2(this, 'AwsCli', {
159+
platform: imagebuilder.Platform.LINUX
160+
})
161+
}
162+
]
163+
});
164+
```
165+
166+
#### Container Recipe Configuration
167+
168+
##### Custom Dockerfile
169+
170+
Provide your own Dockerfile template:
171+
172+
```ts
173+
const containerRecipe = new imagebuilder.ContainerRecipe(this, 'CustomDockerfileContainerRecipe', {
174+
baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'),
175+
targetRepository: imagebuilder.Repository.fromEcr(
176+
ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo')
177+
),
178+
dockerfile: imagebuilder.DockerfileData.fromInline(`
179+
FROM {{{ imagebuilder:parentImage }}}
180+
CMD ["echo", "Hello, world!"]
181+
{{{ imagebuilder:environments }}}
182+
{{{ imagebuilder:components }}}
183+
`)
184+
});
185+
```
186+
187+
##### Instance Configuration
188+
189+
Configure the build instance:
190+
191+
```ts
192+
const containerRecipe = new imagebuilder.ContainerRecipe(this, 'InstanceConfigContainerRecipe', {
193+
baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'),
194+
targetRepository: imagebuilder.Repository.fromEcr(
195+
ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo')
196+
),
197+
// Custom ECS-optimized AMI for building
198+
instanceImage: imagebuilder.ContainerInstanceImage.fromSsmParameterName(
199+
'/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id'
200+
),
201+
// Additional storage for build process
202+
instanceBlockDevices: [
203+
{
204+
deviceName: '/dev/xvda',
205+
volume: ec2.BlockDeviceVolume.ebs(50, {
206+
encrypted: true,
207+
volumeType: ec2.EbsDeviceVolumeType.GENERAL_PURPOSE_SSD_GP3
208+
})
209+
}
210+
]
211+
});
212+
```
213+
39214
### Component
40215

41216
A component defines the sequence of steps required to customize an instance during image creation (build component) or
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import * as ecr from 'aws-cdk-lib/aws-ecr';
2+
import * as ssm from 'aws-cdk-lib/aws-ssm';
3+
4+
/**
5+
* Represents a base image that is used to start from in EC2 Image Builder image builds
6+
*/
7+
export class BaseContainerImage {
8+
/**
9+
* The DockerHub image to use as the base image in a container recipe
10+
*
11+
* @param repository The DockerHub repository where the base image resides in
12+
* @param tag The tag of the base image in the DockerHub repository
13+
*/
14+
public static fromDockerHub(repository: string, tag: string): BaseContainerImage {
15+
return new BaseContainerImage(`${repository}:${tag}`);
16+
}
17+
18+
/**
19+
* The ECR container image to use as the base image in a container recipe
20+
*
21+
* @param repository The ECR repository where the base image resides in
22+
* @param tag The tag of the base image in the ECR repository
23+
*/
24+
public static fromEcr(repository: ecr.IRepository, tag: string): BaseContainerImage {
25+
return new BaseContainerImage(repository.repositoryUriForTag(tag));
26+
}
27+
28+
/**
29+
* The ECR public container image to use as the base image in a container recipe
30+
*
31+
* @param registryAlias The alias of the ECR public registry where the base image resides in
32+
* @param repositoryName The name of the ECR public repository, where the base image resides in
33+
* @param tag The tag of the base image in the ECR public repository
34+
*/
35+
public static fromEcrPublic(registryAlias: string, repositoryName: string, tag: string): BaseContainerImage {
36+
return new BaseContainerImage(`public.ecr.aws/${registryAlias}/${repositoryName}:${tag}`);
37+
}
38+
39+
/**
40+
* The string value of the base image to use in a container recipe. This can be an EC2 Image Builder image ARN,
41+
* an ECR or ECR public image, or a container URI sourced from a third-party container registry such as DockerHub.
42+
*
43+
* @param baseContainerImageString The base image as a direct string value
44+
*/
45+
public static fromString(baseContainerImageString: string): BaseContainerImage {
46+
return new BaseContainerImage(baseContainerImageString);
47+
}
48+
49+
/**
50+
* The rendered base image to use
51+
**/
52+
public readonly image: string;
53+
54+
protected constructor(image: string) {
55+
this.image = image;
56+
}
57+
}
58+
59+
/**
60+
* Represents a container instance image that is used to launch the instance used for building the container for an
61+
* EC2 Image Builder container build.
62+
*/
63+
export class ContainerInstanceImage {
64+
/**
65+
* The AMI ID to use to launch the instance for building the container image
66+
*
67+
* @param amiId The AMI ID to use as the container instance image
68+
*/
69+
public static fromAmiId(amiId: string): ContainerInstanceImage {
70+
return new ContainerInstanceImage(amiId);
71+
}
72+
73+
/**
74+
* The SSM parameter to use to launch the instance for building the container image
75+
*
76+
* @param parameter The SSM parameter to use as the container instance image
77+
*/
78+
public static fromSsmParameter(parameter: ssm.IStringParameter): ContainerInstanceImage {
79+
return this.fromSsmParameterName(parameter.parameterArn);
80+
}
81+
82+
/**
83+
* The name of the SSM parameter used to launch the instance for building the container image
84+
*
85+
* @param parameterName The name of the SSM parameter used as the container instance image
86+
*/
87+
public static fromSsmParameterName(parameterName: string): ContainerInstanceImage {
88+
return new ContainerInstanceImage(`ssm:${parameterName}`);
89+
}
90+
91+
/**
92+
* The string value of the container instance image to use in a container recipe. This can either be an SSM parameter,
93+
* or an AMI ID.
94+
*
95+
* @param containerInstanceImageString The container instance image as a direct string value
96+
*/
97+
public static fromString(containerInstanceImageString: string): ContainerInstanceImage {
98+
return new ContainerInstanceImage(containerInstanceImageString);
99+
}
100+
101+
/**
102+
* The rendered container instance image to use
103+
**/
104+
public readonly image: string;
105+
106+
protected constructor(image: string) {
107+
this.image = image;
108+
}
109+
}

0 commit comments

Comments
 (0)