ECRのイメージレプリケーションはイメージのコピーであって状態の完全同期ではない
レプリケーション元でイメージを削除すると、レプリケーション先でも削除されないか気になる
こんにちは、のんピ(@non____97)です。
皆さんはECRのクロスリージョン、クロスアカウントレプリケーションにおいて、レプリケーション元でイメージを削除すると、レプリケーション先でも削除されないか気にったことはありますか? 私はあります。
2026/1/31現在、ECR上のコンテナイメージをバックアップすることはできません。
そのため、誤ってコンテナイメージやリポジトリを削除してしまった場合や、マルウェア等の悪意のある攻撃者からコンテナイメージを完全にされてしまうことを回避するために、クロスリージョン、クロスアカウントのレプリケーションが有効です。
この「レプリケーション」はどこまでレプリケーションしてくれるのでしょうか。リポジトリ内のイメージの完全同期なのであれば、レプリケーション元でイメージを削除してしまうと、レプリケーション先でも削除されてしまいそうです。
答えとしては以下のように削除はされないのですが、実際に確認してみました。
レジストリレプリケーションでは、削除アクションやアーカイブアクションは実行されません。レプリケートされたイメージとリポジトリは、使用されなくなったときに削除またはアーカイブできます。
やってみた
us-east-1でのコンテナイメージのPush
今回はus-east-1からap-northeast-1へのイメージのクロスリージョンレプリケーションを行います。
レプリケーション設定を行う前にPushされたイメージはレプリケーションされないことを確認するために、まず、us-east-1でのコンテナイメージのPushをします。具体的にはscratchのコンテナイメージをビルドしてPushします。
> echo test > test.txt
> vi Dockerfile
> cat Dockerfile
FROM scratch
COPY test.txt /
> docker build -t test/scratch .
[+] Building 0.1s (5/5) FINISHED docker:rancher-desktop
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 66B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 40B 0.0s
=> [1/1] COPY test.txt / 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:008f354f9560cec095d05da5b6ae0593af358119e43a61eb21c905ac288debe0 0.0s
=> => naming to docker.io/test/scratch 0.0s
> docker tag test/scratch:1 <AWSアカウントID>.dkr.ecr.us-east-1.amazonaws.com/test/scratch:1
> docker image ls | grep scratch
WARNING: This output is designed for human readability. For machine-readable output, please use --format.
test/scratch:latest 008f354f9560 5B 0B
> docker tag test/scratch:latest <AWSアカウントID>.dkr.ecr.us-east-1.amazonaws.com/test/scratch:1
> docker image ls | grep scratch
WARNING: This output is designed for human readability. For machine-readable output, please use --format.
<AWSアカウントID>.dkr.ecr.us-east-1.amazonaws.com/test/scratch:1 008f354f9560 5B 0B
test/scratch:latest 008f354f9560 5B 0B
> docker push <AWSアカウントID>.dkr.ecr.us-east-1.amazonaws.com/test/scratch:1
The push refers to repository [<AWSアカウントID>.dkr.ecr.us-east-1.amazonaws.com/test/scratch]
a9ff3eb9d504: Pushed
1: digest: sha256:7bbaba19926e61e647ef9bb553f63e6aff685effe5cf6ed291116dcd1334ba22 size: 523
us-east-1のプライベートリポジトリにイメージがPushされたことを確認します。

レプリケーションルールの設定
続いて、us-east-1にてレプリケーションルールの設定を行います。
設定は以下のとおりです。
{
"destinations": [
{
"registryId": "<AWSアカウントID>",
"region": "ap-northeast-1"
}
],
"repositoryFilters": [
{
"filter": "test/scratch",
"filterType": "PREFIX_MATCH"
}
]
}
設定後、しばらく待ちましたが、ap-northeast-1側にはレプリケーションされていません。

us-east-1にてPush済みのイメージにタグを追加してPush
us-east-1にてPush済みのイメージにタグを追加してPushしてみましょう。
> docker tag test/scratch:latest <AWSアカウントID>.dkr.ecr.us-east-1.amazonaws.com/test/scratch:2
> docker push <AWSアカウントID>.dkr.ecr.us-east-1.amazonaws.com/test/scratch:2
The push refers to repository [<AWSアカウントID>.dkr.ecr.us-east-1.amazonaws.com/test/scratch]
a9ff3eb9d504: Layer already exists
2: digest: sha256:7bbaba19926e61e647ef9bb553f63e6aff685effe5cf6ed291116dcd1334ba22 size: 523
us-east-1を確認すると、イメージタグが2, 1となっていますね。

ap-northeast-1を確認すると、test/scratchとus-east-1と同様名のプライベートリポジトリが作成されていました。

リポジトリ内のコンテナイメージを確認すると、2のタグが付与されたコンテナイメージを確認できました。

どうやら、レプリケーション設定前にPush済みのイメージタグについてはレプリケーションされないようです。
us-east-1にて追加のコンテナイメージのPush
us-east-1にて追加のコンテナイメージのPushをします。
> echo test2 > test2.txt
> vi Dockerfile
> cat Dockerfile
FROM scratch
COPY test.txt /
COPY test2.txt /
> docker build -t test/scratch:3 .
[+] Building 0.1s (6/6) FINISHED docker:rancher-desktop
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 83B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 73B 0.0s
=> CACHED [1/2] COPY test.txt / 0.0s
=> [2/2] COPY test2.txt / 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:9964d986b5f3bb1938ad0205957960602d78055322c3848febbd889b797974f0 0.0s
=> => naming to docker.io/test/scratch:3 0.0s
> docker tag test/scratch:3 <AWSアカウントID>.dkr.ecr.us-east-1.amazonaws.com/test/scratch:3
> docker push <AWSアカウントID>.dkr.ecr.us-east-1.amazonaws.com/test/scratch:3
The push refers to repository [<AWSアカウントID>.dkr.ecr.us-east-1.amazonaws.com/test/scratch]
61b559a89d46: Pushed
a9ff3eb9d504: Layer already exists
3: digest: sha256:4d095f5442680dfc22fffa6fa87e7aa9b30f3308201c4dc8a3038fe67f31e34a size: 730
Push後のus-east-1のリポジトリを確認すると、イメージタグ3のコンテナイメージが確認できました。

ap-northeast-1のリポジトリを確認すると、こちらもイメージタグ3のコンテナイメージが確認できました。

us-east-1にてコンテナイメージの削除
us-east-1にて先ほどPushしたイメージタグ3のコンテナイメージの削除をします。

イメージが削除されました。

ap-northeast-1aのリポジトリを確認しましたが、イメージは削除されていません。

3日待っても削除されていませんでした。また、us-east-1でリポジトリごと削除しましたが、ap-northeast-1側では変化はありませんでした。
ということで、ECRのイメージレプリケーションはイメージのコピーであって状態の完全同期ではないことが分かりました。
誤ってレプリケーション元でイメージを削除してしまっても安心
ECRのイメージレプリケーションはイメージのコピーであって状態の完全同期ではないことを確認しました。
逆にいうと、レプリケーション元は定期的にイメージを整理していっても、レプリケーション先で整理がされていないのであれば、イメージが溜まり続けてしまいます。レプリケーション先でもライフサイクルポリシーを設定しましょう。
レプリケーションのタイミングでタグのミュータビリティ、暗号化設定、リポジトリの権限、ライフサイクルポリシーを設定したい場合はリポジトリ作成テンプレートを事前に設定しておきましょう。リポジトリ作成テンプレートは以下が参考になります。
この記事が誰かの助けになれば幸いです。
以上、クラウド事業本部 コンサルティング部の のんピ(@non____97)でした!






