Module classic/ecr
Pulumi Elastic Contain Registry (ECR) Components
Pulumi’s API’s for simplifying working with ECR. The API currently provides ways to define and configure Repositories
and LifecyclePolicies
. It also makes it simple to build and push Docker Images to a Repository providing stored cloud images that can then be used by other AWS services like ECS.
Repositories
To start with, here’s a simple example of how one can create a simple ECR Repository:
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";
const repository = new awsx.ecr.Repository("app");
With a repository available, it’s easy to build an push a Docker Image that will be stored in the cloud:
const repository = new awsx.ecr.Repository("app");
// "./app" is a relative folder to this application containing a Dockerfile. For more
// examples of what can be built and pushed, see the @pulumi/docker package.
const image = repository.buildAndPushImage("./app");
Now that we have an image, it can be easily referenced from an ECS Service like so:
const repository = new awsx.ecr.Repository("app");
const image = repository.buildAndPushImage("./app");
const listener = new awsx.lb.NetworkListener("app", { port: 80 });
const nginx = new awsx.ecs.FargateService("app", {
taskDefinitionArgs: {
containers: {
nginx: {
image: image,
memory: 128,
portMappings: [listener],
},
},
},
desiredCount: 2,
});
In the case where you don’t really need to use the repository (except as a place to store the built image), the above can be simplified as:
const nginx = new awsx.ecs.FargateService("app", {
taskDefinitionArgs: {
containers: {
nginx: {
image: awsx.ecr.buildAndPushImage("app", "./app"),
// ...
},
},
},
// ...
});
Lifecycle Policies
Amazon ECR lifecycle policies enable you to specify the lifecycle management of images in a repository. A lifecycle policy is a set of one or more rules, where each rule defines an action for Amazon ECR. The actions apply to images that contain tags prefixed with the given strings. This allows the automation of cleaning up unused images, for example expiring images based on age or count. You should expect that after creating a lifecycle policy the affected images are expired within 24 hours. See https://docs.aws.amazon.com/AmazonECR/latest/userguide/LifecyclePolicies.html for more details.
The ECR module makes it easy to configure the Lifecycle Policy for a given Repository. There are two main ways that control how an image is purged from the repository:
- Once a maximum number of images has been reached (
maximumNumberOfImages
). - Once an image reaches a maximum allowed age (
maximumAgeLimit
).
Policies can apply to all images, ‘untagged’ images, or tagged images that match a specific tag-prefix.
By default an awsx.ecr.Repository is created with a policy that will only keep at most one untagged image around. In other words, the following are equivalent:
const repository1 = new awsx.ecr.Repository("app1");
const repository2 = new awsx.ecr.Repository("app2", {
lifeCyclePolicyArgs: {
rules: [{
selection: "untagged",
maximumNumberOfImages: 1,
}],
},
});
Policy Rules
A Lifecycle Policy is built from a collection of rules
. These rules are ordered from lower priority to higher priority. How the collection of rules
is interpreted is as follows:
- An image is expired by exactly one or zero rules.
- An image that matches the tagging requirements of a higher priority rule cannot be expired by a rule with a lower priority.
- Rules can never mark images that are marked by higher priority rules, but can still identify them as if they haven’t been expired.
- The set of rules must contain a unique set of tag prefixes.
- Only one rule is allowed to select
untagged
images. - Expiration is always ordered by the “pushed at time” for an image, and always expires older images before newer ones.
- When using the
tagPrefixList
, an image is successfully matched if all of the tags in thetagPrefixList
value are matched against any of the image’s tags. - With
maximumNumberOfImages
, images are sorted from youngest to oldest based on their “pushed at time” and then all images greater than the specified count are expired. maximumAgeLimit
, all images whose “pushed at time” is older than the specified number of days based oncountNumber
are expired.
Examples
Example A:
The following example shows the lifecycle policy syntax for a policy that expires untagged images older than 14 days:
const repository = new awsx.ecr.Repository("app", {
lifeCyclePolicyArgs: {
rules: [{
selection: "untagged",
maximumAgeLimit: 14,
}],
},
});
Example B: Filtering on Multiple Rules
The following examples use multiple rules in a lifecycle policy. An example repository and lifecycle policy are given along with an explanation of the outcome.
const repository = new awsx.ecr.Repository("app", {
lifeCyclePolicyArgs: {
rules: [{
selection: { tagPrefixList: ["prod"] },
maximumNumberOfImages: 1,
}, {
selection: { tagPrefixList: ["beta"] },
maximumNumberOfImages: 1,
}],
},
});
Repository contents:
- Image A, Taglist: [“beta-1”, “prod-1”], Pushed: 10 days ago
- Image B, Taglist: [“beta-2”, “prod-2”], Pushed: 9 days ago
- Image C, Taglist: [“beta-3”], Pushed: 8 days ago
The logic of this lifecycle policy would be:
Rule 1 identifies images tagged with prefix
prod
. It should mark images, starting with the oldest, until there is one or fewer images remaining that match. It marks Image A for expiration.Rule 2 identifies images tagged with prefix beta. It should mark images, starting with the oldest, until there is one or fewer images remaining that match. It marks both Image A and Image B for expiration. However, Image A has already been seen by Rule 1 and if Image B were expired it would violate Rule 1 and thus is skipped.
Result: Image A is expired.
Example C: Filtering on Multiple Rules
This is the same repository as the previous example but the rule priority order is changed to illustrate the outcome.
const repository = new awsx.ecr.Repository("app", {
lifeCyclePolicyArgs: {
rules: [{
selection: { tagPrefixList: ["beta"] },
maximumNumberOfImages: 1,
}, {
selection: { tagPrefixList: ["prod"] },
maximumNumberOfImages: 1,
}],
},
});
Repository contents:
- Image A, Taglist: [“beta-1”, “prod-1”], Pushed: 10 days ago
- Image B, Taglist: [“beta-2”, “prod-2”], Pushed: 9 days ago
- Image C, Taglist: [“beta-3”], Pushed: 8 days ago
The logic of this lifecycle policy would be:
Rule 1 identifies images tagged with beta. It should mark images, starting with the oldest, until there is one or fewer images remaining that match. It sees all three images and would mark Image A and Image B for expiration.
Rule 2 identifies images tagged with prod. It should mark images, starting with the oldest, until there is one or fewer images remaining that match. It would see no images because all available images were already seen by Rule 1 and thus would mark no additional images.
Result: Images A and B are expired.
Example D: Filtering on Multiple Tags in a Single Rule
The following examples specify the lifecycle policy syntax for multiple tag prefixes in a single rule. An example repository and lifecycle policy are given along with an explanation of the outcome.
When multiple tag prefixes are specified on a single rule, images must match all listed tag prefixes.
const repository = new awsx.ecr.Repository("app", {
lifeCyclePolicyArgs: {
rules: [{
selection: { tagPrefixList: ["alpha", "beta"] },
maximumAgeLimit: 5,
},
},
});
Repository contents:
- Image A, Taglist: [“alpha-1”], Pushed: 12 days ago
- Image B, Taglist: [“beta-1”], Pushed: 11 days ago
- Image C, Taglist: [“alpha-2”, “beta-2”], Pushed: 10 days ago
- Image D, Taglist: [“alpha-3”], Pushed: 4 days ago
- Image E, Taglist: [“beta-3”], Pushed: 3 days ago
- Image F, Taglist: [“alpha-4”, “beta-4”], Pushed: 2 days ago
The logic of this lifecycle policy would be:
Rule 1 identifies images tagged with alpha and beta. It sees images C and F. It should mark images that are older than five days, which would be Image C.
Result: Image C is expired.
Example E: Filtering on All Images
The following lifecycle policy examples specify all images with different filters. An example repository and lifecycle policy are given along with an explanation of the outcome.
const repository = new awsx.ecr.Repository("app", {
lifeCyclePolicyArgs: {
rules: [{
selection: "any",
maximumNumberOfImages: 5,
},
},
});
Repository contents:
- Image A, Taglist: [“alpha-1”], Pushed: 4 days ago
- Image B, Taglist: [“beta-1”], Pushed: 3 days ago
- Image C, Taglist: [], Pushed: 2 days ago
- Image D, Taglist: [“alpha-2”], Pushed: 1 day ago
The logic of this lifecycle policy would be:
Rule 1 identifies all images. It sees images A, B, C, and D. It should expire all images other than the newest one. It marks images A, B, and C for expiration.
Result: Images A, B, and C are expired.
Resources
Others
Resources
Resource Repository
class Repository extends ComponentResource
A [Repository] represents an [aws.ecr.Repository] along with an associated [LifecyclePolicy] controlling how images are retained in the repo.
Docker images can be built and pushed to the repo using the [buildAndPushImage] method. This
will call into the @pulumi/docker/buildAndPushImage
function using this repo as the appropriate
destination registry.
constructor
new Repository(name: string, args: RepositoryArgs, opts: ComponentResourceOptions)
method buildAndPushImage
public buildAndPushImage(pathOrBuild: pulumi.Input<string | DockerBuild>): Output<string>
Builds the docker container specified by [pathOrBuild] and pushes it to this repository.
The result is the unique ID pointing to that pushed image in this repo. This unique ID
can be passed as the value to image: repo.buildAndPushImage(...)
in an ecs.Container
.
method getData
protected getData(): Promise<TData>
Retrieves the data produces by [initialize]. The data is immediately available in a
derived class’s constructor after the super(...)
call to ComponentResource
.
method getProvider
getProvider(moduleMember: string): ProviderResource | undefined
method initialize
protected initialize(args: Inputs): Promise<TData>
Can be overridden by a subclass to asynchronously initialize data for this Component
automatically when constructed. The data will be available immediately for subclass
constructors to use. To access the data use .getData
.
method isInstance
static isInstance(obj: any): obj is ComponentResource
Returns true if the given object is an instance of CustomResource. This is designed to work even when multiple copies of the Pulumi SDK have been loaded into the same process.
method registerOutputs
protected registerOutputs(outputs?: Inputs | Promise<Inputs> | Output<Inputs>): void
registerOutputs registers synthetic outputs that a component has initialized, usually by allocating other child sub-resources and propagating their resulting property values.
ComponentResources can call this at the end of their constructor to indicate that they are
done creating child resources. This is not strictly necessary as this will automatically be
called after the initialize
method completes.
property lifecyclePolicy
public lifecyclePolicy: LifecyclePolicy | undefined;
property repository
public repository: Repository;
property urn
urn: Output<URN>;
urn is the stable logical URN used to distinctly address a resource, both before and after deployments.
Others
function buildAndPushImage
buildAndPushImage(name: string, pathOrBuild: pulumi.Input<string | DockerBuild>, args?: RepositoryArgs, opts?: pulumi.ComponentResourceOptions): RepositoryImage
Creates a new [Repository], optionally configured using [args], builds the docker container
specified by [pathOrBuild] and then pushes the built image to the repository. The result
contains both the Repository created as well as the unique ID referencing the built image in that
repo. This result type can be passed in as image: ecr.buildAndPushImage(...)
for an
ecs.Container
class LifecyclePolicy
class LifecyclePolicy extends LifecyclePolicy
constructor
new LifecyclePolicy(name: string, repository: Repository, args?: LifecyclePolicyArgs, opts: ComponentResourceOptions)
Creates a new [LifecyclePolicy] for the given [repository]. If [args] is not provided, then [getDefaultLifecyclePolicyArgs] will be used to set the default policy for this repo.
method defaultLifecyclePolicyArgs
public static defaultLifecyclePolicyArgs(): LifecyclePolicyArgs
Creates a default lifecycle policy such that at most a single untagged image is retained. All tagged layers and images will never expire.
method get
static get(name: string, id: pulumi.Input<pulumi.ID>, state?: LifecyclePolicyState, opts?: pulumi.CustomResourceOptions): LifecyclePolicy
Get an existing LifecyclePolicy resource’s state with the given name, ID, and optional extra properties used to qualify the lookup.
method getProvider
getProvider(moduleMember: string): ProviderResource | undefined
method isInstance
static isInstance(obj: any): obj is LifecyclePolicy
Returns true if the given object is an instance of LifecyclePolicy. This is designed to work even when multiple copies of the Pulumi SDK have been loaded into the same process.
property id
id: Output<ID>;
id is the provider-assigned unique ID for this managed resource. It is set during deployments and may be missing (undefined) during planning phases.
property policy
policy: pulumi.Output<string>;
The policy document. This is a JSON formatted string. See more details about Policy Parameters in the official AWS docs.
property registryId
registryId: pulumi.Output<string>;
The registry ID where the repository was created.
property repository
repository: pulumi.Output<string>;
Name of the repository to apply the policy.
property urn
urn: Output<URN>;
urn is the stable logical URN used to distinctly address a resource, both before and after deployments.
interface LifecyclePolicyArgs
interface LifecyclePolicyArgs
See https://docs.aws.amazon.com/AmazonECR/latest/userguide/lifecycle_policy_examples.html for more details.
property rules
rules: pulumi.Input<pulumi.Input<LifecyclePolicyRule>[]>;
Specifies the rules to determine how images should be retired from this repository. Rules are
ordered from lowest priority to highest. If there is a rule with a selection
value of
any
, then it will have the highest priority.
interface LifecyclePolicyRule
interface LifecyclePolicyRule
The following behaviors hold for these rules:
An image is expired by exactly one or zero rules.
An image that matches the tagging requirements of a higher priority rule cannot be expired by a rule with a lower priority.
Rules can never mark images that are marked by higher priority rules, but can still identify them as if they haven’t been expired.
The set of rules must contain a unique set of tag prefixes.
Only one rule is allowed to select
untagged
images.Expiration is always ordered by pushed_at_time, and always expires older images before newer ones.
When using the
tagPrefixList
, an image is successfully matched if all of the tags in thetagPrefixList
value are matched against any of the image’s tags.With
maximumNumberOfImages
, images are sorted from youngest to oldest based on pushed_at_time and then all images greater than the specified count are expired.With
maximumAgeLimit
, all images whose pushed_at_time is older than the specified number of days based on countNumber are expired.
property description
description?: pulumi.Input<string>;
Describes the purpose of a rule within a lifecycle policy.
property maximumAgeLimit
maximumAgeLimit?: pulumi.Input<number>;
The maximum age limit (in days) for your images. Either [maximumNumberOfImages] or [maximumAgeLimit] must be provided.
property maximumNumberOfImages
maximumNumberOfImages?: pulumi.Input<number>;
The maximum number of images that you want to retain in your repository. Either [maximumNumberOfImages] or [maximumAgeLimit] must be provided.
property selection
selection: pulumi.Input<"untagged" | "any" | {
tagPrefixList: pulumi.Input<pulumi.Input<string>[]>;
}>;
Determines whether the lifecycle policy rule that you are adding specifies a tag for an
image. If you specify any
, then all images have the rule applied to them. If you specify
untagged
then the rule will only apply to untagged images. Otherwise, you can specify a
tagPrefixList
value.
interface RepositoryArgs
interface RepositoryArgs
property lifeCyclePolicyArgs
lifeCyclePolicyArgs?: LifecyclePolicyArgs;
The arguments controlling the [LifecyclePolicy] for this [Repository]. If undefined
, a default one will be
created using LifecyclePolicy.getDefaultLifecyclePolicyArgs
.
property repository
repository?: aws.ecr.Repository;
Underlying repository. If not provided, a new one will be created on your behalf.
property tags
tags?: pulumi.Input<Record<string, pulumi.Input<string>>>;
A mapping of tags to assign to the resource.
class RepositoryImage
implements ContainerImageProvider
A simple pair of a [Repository] and a built docker image that was pushed to it. This can
be passed in as the image: repoImage
value to an ecs.Container
.
constructor
new RepositoryImage(repository: Repository, image: pulumi.Input<string>)
method environment
public environment(): never[]
method image
public image(): Input<string>
property imageValue
public imageValue: pulumi.Input<string>;
property repository
public repository: Repository;
Thank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.