{"id":480,"date":"2025-09-13T04:30:43","date_gmt":"2025-09-13T04:30:43","guid":{"rendered":"https:\/\/blog.ngocha.biz\/?p=480"},"modified":"2025-09-13T04:30:43","modified_gmt":"2025-09-13T04:30:43","slug":"setup-argocd-image-updater","status":"publish","type":"post","link":"https:\/\/blog.ngocha.biz\/?p=480","title":{"rendered":"How to Use Argo CD Image Updater with AWS ECR (Step-by-Step Guide)"},"content":{"rendered":"<p>In this step by step guide, we will look in to Argo CD Image Updater and how to use it with AWS ECR.<\/p>\n<p>At the end of this guide, you will learn:<\/p>\n<ul>\n<li>About Argo CD Image Updater<\/li>\n<li>How it works<\/li>\n<li>How to install and configure it for EKS + ECR<\/li>\n<li>Testing Image Updater with a simple Flask application<\/li>\n<li>Available update strategies and annotations<\/li>\n<\/ul>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-text\"><b><strong style=\"white-space: pre-wrap;\">Important Note:<\/strong><\/b> Image Updater supports Helm and Kustomize applications. It does not work with plain YAML deployments.<\/div>\n<\/div>\n<h2 id=\"what-is-argo-cd-image-updater\">What is Argo CD Image Updater?<\/h2>\n<p>Argo CD Image Updater is an additional tool in Argo CD that helps to automate the process of updating new container images on applications managed by Argo CD.<\/p>\n<p>Image Updater supports popular container registries like AWS ECR, Docker Hub, GCR, etc, and can even access their private repositories with proper authentication.<\/p>\n<p>Using Argo CD Image Updater is simple, you just have to install Image Updater and specify the annotation on the application manifest file, which we will see about later in this blog.<\/p>\n<p>Image Updater only works with applications that are in Helm or Kustomize, not any other deployment format like plain <a href=\"https:\/\/devopscube.com\/create-kubernetes-yaml\/\" rel=\"noreferrer\">YAML<\/a>.<\/p>\n<h2 id=\"how-does-argo-cd-image-updater-work\">How does Argo CD Image Updater work?<\/h2>\n<p>The Image Updater continuously monitors the configured container registry for new images. When it detects a new tag that matches the allowed version rules, it updates the application using one of two <strong>write-back methods<\/strong>.<\/p>\n<ul>\n<li><strong>Argo CD mode: <\/strong> This mode directly patches the application resource inside Argo CD.<\/li>\n<li><strong>Git mode: <\/strong>This mode commits the change to the Git repository, and Argo CD syncs it from there.<\/li>\n<\/ul>\n<p>Once updated, Argo CD rolls out a new pod with the latest image. If auto-sync is enabled, this happens automatically. Or else, you need to trigger a manual sync.<\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\">The image updation and rollout process will be completed in less than 1 minute.<\/div>\n<\/div>\n<p>The workflow of the Argo CD Image Updater with ECR registry is shown in the below image.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/09\/image-updater.png\" class=\"kg-image\" alt=\"Argo CD ECR Image Updater Workflow\" loading=\"lazy\" width=\"2000\" height=\"1684\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/09\/image-updater.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/09\/image-updater.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/09\/image-updater.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/09\/image-updater.png 2002w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Here is how it works.<\/p>\n<ol>\n<li>The Argo CD Image Updater will be always monitoring the configured image registry for new images.<\/li>\n<li>When a user pushes a new image to the registry with the configured version, Image Updater detects it and updates it to the application deployment files in Argo CD.<\/li>\n<li>Once the new image tag has been updated, Argo CD will automatically rollout the application pod with the new version of the image.<\/li>\n<\/ol>\n<h2 id=\"setup-prerequisites\">Setup Prerequisites<\/h2>\n<p>Below are the prerequisites for this setup<\/p>\n<ul>\n<li><a href=\"https:\/\/devopscube.com\/create-aws-eks-cluster-eksctl\/\" rel=\"noreferrer\">EKS cluster<\/a><\/li>\n<li>Pod Identity Association enabled on the cluster<\/li>\n<li>AWS ECR Registry<\/li>\n<li><a href=\"https:\/\/devopscube.com\/use-aws-cli-create-ec2-instance\/\" rel=\"noreferrer\">AWS CLI<\/a><\/li>\n<li><a href=\"https:\/\/devopscube.com\/kubectl-set-context\/\" rel=\"noreferrer\">kubectl<\/a><\/li>\n<li><a href=\"https:\/\/devopscube.com\/setup-argo-cd-using-helm\/\">Argo CD<\/a> installed on the cluster<\/li>\n<li><a href=\"https:\/\/devopscube.com\/create-helm-chart\/\" rel=\"noreferrer\">Helm<\/a><\/li>\n<\/ul>\n<h2 id=\"install-argo-cd-image-updater-on-kubernetes\">Install Argo CD Image Updater on Kubernetes<\/h2>\n<p>For the Image Updater to access the ECR registry, the default installation is not enough. We have to create a custom script and mount it in the Image Updater deployment.<\/p>\n<p>The custom script contains the command to login to ECR registry.<\/p>\n<p>We have already created every file and kept it in our <a href=\"https:\/\/github.com\/devopscube\/argocd-image-updater.git?ref=devopscube.com\">GitHub repo<\/a>, fork it and clone it to your local.<\/p>\n<p>Run the following command to clone it.<\/p>\n<pre><code class=\"language-bash\">git clone https:\/\/github.com\/devopscube\/argocd-image-updater.git<\/code><\/pre>\n<p><code>CD<\/code> into the <code>argocd-image-updater<\/code> folder.<\/p>\n<pre><code class=\"language-bash\">cd argocd-image-updater<\/code><\/pre>\n<p>You can see the following folder structure.<\/p>\n<pre><code class=\"language-bash\">argocd-image-updater\n    \u251c\u2500\u2500 README.md\n    \u251c\u2500\u2500 app\n    \u2502   \u251c\u2500\u2500 Dockerfile\n    \u2502   \u2514\u2500\u2500 app.py\n    \u251c\u2500\u2500 flask-app\n    \u2502   \u251c\u2500\u2500 Chart.yaml\n    \u2502   \u251c\u2500\u2500 templates\n    \u2502   \u2502   \u251c\u2500\u2500 deployment.yaml\n    \u2502   \u2502   \u2514\u2500\u2500 service.yaml\n    \u2502   \u2514\u2500\u2500 values.yaml\n    \u2514\u2500\u2500 manifest\n        \u251c\u2500\u2500 application.yaml\n        \u2514\u2500\u2500 values.yaml\n<\/code><\/pre>\n<p>Lets get started with the setup.<\/p>\n<h2 id=\"step1-create-pod-identity-association\">Step1: Create Pod Identity Association<\/h2>\n<p>First, let&#8217;s create a pod identity association for the Argo CD Image Updater service account, which is required for it to monitor and update new images from ECR.<\/p>\n<p>Run the following command to create a trust policy JSON file.<\/p>\n<pre><code class=\"language-bash\">cat &lt;&lt;EOF &gt; trust-policy.json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Principal\": {\n        \"Service\": \"pods.eks.amazonaws.com\"\n      },\n      \"Action\": [\n        \"sts:AssumeRole\",\n        \"sts:TagSession\"\n      ]\n    }\n  ]\n}\nEOF<\/code><\/pre>\n<p>Then, create a role with the trust policy from the <code>trust-policy.json<\/code> file<\/p>\n<pre><code class=\"language-bash\">aws iam create-role \\\n    --role-name ecr-auth-role \\\n    --assume-role-policy-document file:\/\/trust-policy.json<\/code><\/pre>\n<p>We are going to use the <code>AmazonEC2ContainerRegistryReadOnly<\/code> policy, which has every permission Image Updater needs.<\/p>\n<p>Run the following command to attach the container registry read-only policy to the role.<\/p>\n<pre><code class=\"language-bash\">aws iam attach-role-policy \\\n    --role-name ecr-auth-role \\\n    --policy-arn arn:aws:iam::aws:policy\/AmazonEC2ContainerRegistryReadOnly<\/code><\/pre>\n<p>Then, save the ARN of the role as an environment variable, which will be useful in the next step.<\/p>\n<pre><code class=\"language-bash\">ROLE_ARN=$(aws iam get-role --role-name ecr-auth-role --query 'Role.Arn' --output text)\n<\/code><\/pre>\n<p>Now, update your cluster name in the command below and run it.<\/p>\n<pre><code class=\"language-bash\">eksctl create podidentityassociation \\\n    --cluster &lt;cluster-name&gt; \\\n    --namespace argocd \\\n    --service-account-name argocd-image-updater \\\n    --role-arn $ROLE_ARN<\/code><\/pre>\n<h2 id=\"step-2-deploy-argo-cd-image-updater\">Step 2: Deploy Argo CD Image Updater<\/h2>\n<p>We will be using the offical <strong><code>argocd-image-updater<\/code><\/strong> helm chart for the installation.<\/p>\n<p>You can download and modify the official Helm values file using the following command.<\/p>\n<pre><code class=\"language-bash\">helm show values argo\/argocd-image-updater &gt; values.yaml<\/code><\/pre>\n<p>Or you can use the custom values file inside the <code>manifest<\/code> folder as <code>values.yaml<\/code>.<\/p>\n<p>I am using the custom values file.<\/p>\n<p>Open the values file and update your <code>AWS account ID<\/code> in it. If your ECR is in a different region, change that as well.<\/p>\n<pre><code class=\"language-yaml\">config:\n  registries:\n    - name: ECR\n      api_url: https:\/\/&lt;account-id&gt;.dkr.ecr.us-west-2.amazonaws.com\n      prefix: &lt;account-id&gt;.dkr.ecr.us-west-2.amazonaws.com\n      ping: yes\n      insecure: no\n      credentials: ext:\/scripts\/login.sh\n      credsexpire: 6h\n\nauthScripts:\n  enabled: true\n  scripts:\n      login.sh: |\n        #!\/bin\/sh\n        aws ecr --region \"us-west-2\" get-authorization-token --output text --query 'authorizationData[].authorizationToken' | base64 -d<\/code><\/pre>\n<p>In this, <code>registries<\/code> and <code>authScripts<\/code> are default configuration is available in the Image Updater, which we can use to specify the image registry it has to monitor and the authentication script.<\/p>\n<p>Also, it refreshes the authentication token every 6 hours.<\/p>\n<p>The best method for installing Image Updater is to install it on the same namespace as Argo CD, so the Image Updater can make use of the Argo CD ServiceAccount for permissions.<\/p>\n<p>By installing it in the same namespace, you can simply use the Image Updater by using annotations on the manifest file.<\/p>\n<p>To deploy the Argo CD Image Updater, run the following Helm install command with the custom values file from the root directory.<\/p>\n<pre><code class=\"language-bash\">helm install argocd-image-updater argo\/argocd-image-updater -n argocd -f manifest\/values.yaml<\/code><\/pre>\n<p>Then, run the following command to check if the Image Updater is installed.<\/p>\n<pre><code class=\"language-bash\">kubectl get po -n argocd<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/07\/image-234.png\" class=\"kg-image\" alt=\"checking the status of argo cd image updater pods\" loading=\"lazy\" width=\"1315\" height=\"675\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/07\/image-234.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/07\/image-234.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/07\/image-234.png 1315w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>You can also install Image Updater on another namespace, but for that, you need to create a new account with the API key and ServiceAccount, which will be used to connect Image Updater with Argo CD.<\/p>\n<p>You can check the official document for <a href=\"https:\/\/argocd-image-updater.readthedocs.io\/en\/stable\/install\/installation\/?ref=devopscube.com#method-2-connect-using-argo-cd-api-server\" rel=\"noreferrer\">Image updater installation<\/a> on other namespaces.<\/p>\n<h2 id=\"step-3-test-argo-cd-image-updater\">Step 3: Test Argo CD Image Updater<\/h2>\n<p>To test the Image Updater, we are going to do the following.<\/p>\n<ul>\n<li>First, create an image with a simple Python Flask application and push it to ECR<\/li>\n<li>Create an application on Argo CD with the Image Updater annotations<\/li>\n<li>Push a new image to ECR to check if the Image Updater to rolling out the new image<\/li>\n<\/ul>\n<h3 id=\"create-a-python-flask-docker-image\">Create a Python Flask Docker Image<\/h3>\n<p>You can find a Python file for a Flask application and a <a href=\"https:\/\/devopscube.com\/create-dockerfile-using-docker-init\/\" rel=\"noreferrer\">Dockerfile<\/a> to <a href=\"https:\/\/devopscube.com\/dockerize-python-flask-application\/\" rel=\"noreferrer\">dockerize<\/a> it inside the <code>app<\/code> folder.<\/p>\n<p>The Flask application is a simple one that says &#8220;This is image version 1.0.0&#8221;.<\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\">Before going further, create a ECR registry for your images. I have already created registry as <code spellcheck=\"false\" style=\"white-space: pre-wrap;\">flask-app<\/code> in ECR<\/div>\n<\/div>\n<p>Go inside the <code>app<\/code> folder and run the following command to dockerize the application.<\/p>\n<p>Update the registry URL before running the command.<\/p>\n<pre><code class=\"language-bash\">docker build -t &lt;registry-url&gt;:1.0.0 .<\/code><\/pre>\n<p>Once the build is completed, run the following command to push it to ECR.<\/p>\n<pre><code class=\"language-bash\">docker push &lt;registry-url&gt;:1.0.0<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/07\/image-286.png\" class=\"kg-image\" alt=\"image updated to ecr\" loading=\"lazy\" width=\"766\" height=\"444\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/07\/image-286.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/07\/image-286.png 766w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h3 id=\"modify-helm-values-file\">Modify Helm Values File<\/h3>\n<p>We are going to use Helm to deploy the application, since only Helm and <a href=\"https:\/\/devopscube.com\/kustomize-tutorial\/\" rel=\"noreferrer\">Kustomize<\/a> work with the Image Updater.<\/p>\n<p>You can find the Helm charts inside <code>flask-app<\/code> folder.<\/p>\n<p>Open the <code>values.yaml<\/code> file ,update your image registry URL, and then push it to your repository.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/08\/image.png\" class=\"kg-image\" alt=\"helm values file\" loading=\"lazy\" width=\"698\" height=\"486\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/08\/image.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/08\/image.png 698w\"><\/figure>\n<h3 id=\"create-an-application-on-argo-cd\">Create an Application on Argo CD<\/h3>\n<p>To create an application, you can find the manifest file inside the <code>manifest<\/code> folder as <code>application.yaml<\/code>.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: argoproj.io\/v1alpha1\nkind: Application\nmetadata:\n  name: flask-app\n  namespace: argocd\n  annotations:\n    argocd-image-updater.argoproj.io\/image-list: &lt;account-id&gt;.dkr.ecr.us-west-2.amazonaws.com\/flask-app:~1.0\n    argocd-image-updater.argoproj.io\/write-back-method: argocd\n    argocd-image-updater.argoproj.io\/update-strategy: newest-build\n  finalizers:\n    - resources-finalizer.argocd.argoproj.io\nspec:\n  project: default\n  source:\n    repoURL: https:\/\/github.com\/devopscube\/argocd-image-updater.git\n    targetRevision: main\n    path: flask-app\n  destination:\n    server: https:\/\/kubernetes.default.svc\n    namespace: default\n  syncPolicy:\n    automated:\n      prune: true\n      selfHeal: true\n<\/code><\/pre>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\u26a0\ufe0f<\/div>\n<div class=\"kg-callout-text\">Update the above file with your registry URL, GitHub repository URL, and path of the Helm chart.<\/div>\n<\/div>\n<p>The application resource will be created on the Argo CD namespace, and the Flask application will be deployed on the default namespace.<\/p>\n<pre><code class=\"language-bash\">  annotations:\n    argocd-image-updater.argoproj.io\/image-list: &lt;account-id&gt;.dkr.ecr.us-west-2.amazonaws.com\/flask-app:~1.0\n    argocd-image-updater.argoproj.io\/write-back-method: argocd\n    argocd-image-updater.argoproj.io\/update-strategy: newest-build<\/code><\/pre>\n<p>The annotations enable the Argo CD Image Updater to monitor the specified registry and update new images.<\/p>\n<p>What the annotations for:<\/p>\n<p><code>argocd-image-updater.argoproj.io\/image-list<\/code> &#8211; for specifying the registry URL Image Updater needs to monitor.<\/p>\n<p>At the end, the tag is given as <code>~1.0<\/code> , which means it will update the images that are tagged as 1.0.1, 1.0.2, 1.0.3,&#8230;.<\/p>\n<p>For example, if we specify the allowed version as <code>~1.0<\/code> in the annotation, the Image Updater will automatically update the image that is pushed with tags like 1.0.1, 1.0.2,&#8230;<\/p>\n<p>Image Updater will not update the images with tags other than the version specified in the configuration, in our case it is ~1.0, so it will not update the images with tags 2.0.0, 1.2.0, etc.<\/p>\n<p><code>argocd-image-updater.argoproj.io\/write-back-method<\/code> &#8211; specify the write-back method need to use.<\/p>\n<p>We are going to use the <code>argocd<\/code> write-back method, and there is also a git method.<\/p>\n<p>We will look into write-back methods in detail later in this blog.<\/p>\n<p><code>argocd-image-updater.argoproj.io\/update-strategy<\/code> &#8211; specify how new images need to be updated.<\/p>\n<p>We are going to use the <code>newest-build<\/code> update strategy. Apart from this, there are three more strategies that we will see about later in this blog.<\/p>\n<p>Now, run the following command from the root directory to deploy the application.<\/p>\n<pre><code class=\"language-bash\">kubectl apply -f manifest\/application.yaml<\/code><\/pre>\n<p>Then run the following commands to check if your application resource and Flask application are created.<\/p>\n<pre><code class=\"language-bash\">kubectl get applications -n argocd\n\nkubectl get po  <\/code><\/pre>\n<p>You will get the following output.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/07\/image-295.png\" class=\"kg-image\" alt=\"checking if the application is created\" loading=\"lazy\" width=\"1560\" height=\"810\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/07\/image-295.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/07\/image-295.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/07\/image-295.png 1560w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Also, in the Argo CD UI, you can see the following.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/07\/image-297.png\" class=\"kg-image\" alt=\"verifying the application on argocd ui\" loading=\"lazy\" width=\"822\" height=\"518\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/07\/image-297.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/07\/image-297.png 822w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Since the Flask application will be exposed using <code>NodePort 30050<\/code>, you can check the application on a browser using the URL <code>&lt;your-node-ip&gt;:30050<\/code> as shown below.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/07\/image-296.png\" class=\"kg-image\" alt=\"accessing the application webpage on the browser\" loading=\"lazy\" width=\"406\" height=\"173\"><\/figure>\n<h3 id=\"upload-new-image-to-ecr\">Upload New Image to ECR<\/h3>\n<p>Now, we are going to check what the Argo CD Image updater does when a new image is pushed to ECR.<\/p>\n<p>To update the new image, just do the <code>Create a Python Flask Docker Image<\/code> step again.<\/p>\n<p>The only thing you need to change is the tag in the Docker build and push command, as below.<\/p>\n<pre><code class=\"language-bash\">docker build -t &lt;registry-url&gt;:1.0.2 .\n\ndocker push &lt;registry-url&gt;:1.0.2 .<\/code><\/pre>\n<p>Also, change the message inside the Flask application file <code>\/app\/app.py<\/code> as shown below.<\/p>\n<pre><code class=\"language-python\">from flask import Flask\n\napp = Flask(__name__)\n\n@app.route('\/')\ndef version():\n    return \"This is image version 1.0.2\"\n\nif __name__ == '__main__':\n    app.run(host='0.0.0.0', port=5000)\n<\/code><\/pre>\n<p>You can see I have changed the message from <code>This is image version 1.0.0<\/code> to <code>This is image version 1.0.2<\/code><\/p>\n<p>Then, build the new image from the same directory where the Dockerfile is and push it to ECR.<\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-blue\">\n<div class=\"kg-callout-emoji\">\ud83d\udca1<\/div>\n<div class=\"kg-callout-text\">New image will be updated within 1 minute<\/div>\n<\/div>\n<p>Once the new image tag is updated, you can see the Pod with the old version get terminated and a Pod with the new version comes up as shown below<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/07\/image-298.png\" class=\"kg-image\" alt=\"checking the new pod getting deleted and new pod getting created\" loading=\"lazy\" width=\"1102\" height=\"601\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/07\/image-298.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/07\/image-298.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/07\/image-298.png 1102w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>And refresh the flask application, you can see the message changed as shown below.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/07\/image-299.png\" class=\"kg-image\" alt=\"checking the webpage of the new version\" loading=\"lazy\" width=\"405\" height=\"149\"><\/figure>\n<p>This is how the Image Updater continually monitors and updates the image to the application.<\/p>\n<h2 id=\"clean-up\">Clean Up<\/h2>\n<p>If you no longer need the Argo CD Image Updater setup, run the following commands.<\/p>\n<p>Run the following command to delete the application.<\/p>\n<pre><code class=\"language-bash\">kubectl delete -f manifest\/application.yaml<\/code><\/pre>\n<p>Run the following command to uninstall the Image Updater.<\/p>\n<pre><code class=\"language-bash\">helm delete argocd-image-updater -n argocd<\/code><\/pre>\n<p>To delete the pod identity association, update your cluster name in the command below and run it.<\/p>\n<pre><code class=\"language-bash\">eksctl delete podidentityassociation \\\n  --cluster &lt;cluster-name&gt; \\\n  --namespace argocd \\\n  --service-account-name argocd-image-updater\n<\/code><\/pre>\n<p>And finally, delete the role created by running the following commands.<\/p>\n<pre><code class=\"language-bash\">aws iam list-attached-role-policies \\\n  --role-name ecr-auth-role \\\n  --query 'AttachedPolicies[*].PolicyArn' \\\n  --output text | \\\n  xargs -n 1 -I {} aws iam detach-role-policy \\\n    --role-name ecr-auth-role \\\n    --policy-arn {}\n\naws iam delete-role --role-name ecr-auth-role<\/code><\/pre>\n<h2 id=\"image-update-strategies\">Image Update Strategies<\/h2>\n<p>Image Updater has multiple <strong>update strategies,<\/strong> which are used to update the image. The available update strategies are listed below:<\/p>\n<h3 id=\"semver\">semver<\/h3>\n<p>This strategy updates the tag which has the highest allowed version according to the configuration. <\/p>\n<p>For example, let&#8217;s say you have configured to allow version 1.0, and your repository has image tags as 1.0.2, 1.0.3, and 1.0.4.<\/p>\n<p>While using this strategy, it updates the tag <strong>1.0.4<\/strong> because it is the highest allowed version available on the registry.<\/p>\n<h3 id=\"newest-build\">newest-build<\/h3>\n<p>This strategy updates the latest created image tag.<\/p>\n<p>For example, you have pushed the image in the order 1.0.1, 1.0.4, 1.0.3.<\/p>\n<p>While using this strategy, it updates the tag <strong>1.0.3<\/strong> because it is the latest pushed tag.<\/p>\n<h3 id=\"name\">name<\/h3>\n<p>This strategy is used when a tag is in alphabetical letters and it updates the tag with the highest letter.<\/p>\n<p>For example, you have tags as dev, stage, and prod.<\/p>\n<p>While using this strategy, it updates the tag <strong>stage<\/strong> because it has the highest alphabetical letter <strong>&#8216;S&#8217;<\/strong>.<\/p>\n<h3 id=\"digest\">digest<\/h3>\n<p>This strategy updates the latest mutable image tag.<\/p>\n<p>For example, you have already pushed an image with tag 1.0.4 and again you pushed the image with the same tag it becomes a mutable image.<\/p>\n<p>Your repo has tags such as 1.0.1, 1.0.4, and 1.0.6, in this 1.0.4 is a mutable image.<\/p>\n<p>While using this strategy, it updates the tag <strong>1.0.4<\/strong> because it is the latest pushed mutable image tag.<\/p>\n<h2 id=\"image-updater-annotations\">Image Updater Annotations<\/h2>\n<p>You need to use annotations of Image Updater on your application&#8217;s manifest file to monitor and update by Image Updater.<\/p>\n<p>Make sure to use the prefix <code>argocd-image-updater.argoproj.io\/<\/code> before every annotation.<br \/>Some of the commonly used annotations are given below:<\/p>\n<h3 id=\"image-list\">image-list<\/h3>\n<p>This is the mandatory annotation, here you have to specify your image repository with your preferred tag version.<\/p>\n<p>For example, if my image repository is <code>image\/dev<\/code> and the preferred tag version is <code>1.0<\/code>, then my annotation will be:<\/p>\n<pre><code class=\"language-bash\">argocd-image-updater.argoproj.io\/image-list: image\/dev:~1.0<\/code><\/pre>\n<p>You can also use an alias for this annotation as given below<strong>.<\/strong><\/p>\n<pre><code class=\"language-bash\">argocd-image-updater.argoproj.io\/image-list: nginx=image\/dev:~1.0<\/code><\/pre>\n<h3 id=\"update-strategy\">update-strategy<\/h3>\n<p>This annotation is used to specify the update strategy we see in the above feature.<\/p>\n<p>For example, if you are using the <code>newest-build<\/code> update-strategy your annotation will be:<\/p>\n<pre><code class=\"language-bash\">argocd-image-updater.argoproj.io\/update-strategy: newest-build<\/code><\/pre>\n<h3 id=\"allow-tags\">allow-tags<\/h3>\n<p>This annotation is used when you want to update images with two or more tag versions.<\/p>\n<p>For example, if you want to update images within the tag range <code>1.1<\/code> and <code>2.1<\/code>, then your annotation will be:<\/p>\n<pre><code class=\"language-bash\">argocd-image-updater.argoproj.io\/allow-tags: 1\\.1\\.[0-9]+|2\\.1\\.[0-9]+<\/code><\/pre>\n<h3 id=\"ignore-tags\">ignore-tags<\/h3>\n<p>This annotation is used when you don&#8217;t want to update a specific tag version.<\/p>\n<p>For example, if the ignored image tag is <code>1.0<\/code>, then Image Updater will not update the tag version that comes under the 1.0 version such as 1.0.1, 1.0.2, 1.0.3, &#8230; these tag versions will be ignored.<\/p>\n<h3 id=\"pull-secret\">pull-secret<\/h3>\n<p>With this annotation, you can specify the credentials of your private image repository stored as a secret in <a href=\"https:\/\/devopscube.com\/sealed-secrets-kubernetes\/\" rel=\"noreferrer\">Kubernetes.<\/a><\/p>\n<p>For example, I have stored the credentials of my private image repository as a secret in Kubernetes named <code>docker-cred<\/code> then my annotation will be:<\/p>\n<pre><code class=\"language-bash\">argocd-image-updater.argoproj.io\/pull-secret: docker-cred<\/code><\/pre>\n<h3 id=\"write-back-method\">write-back-method<\/h3>\n<p>Image Updater has two types of write-back methods argocd and git<\/p>\n<h4 id=\"argocd\">argocd<\/h4>\n<p>This method directly modifies the application resource on Argo CD. Once it&#8217;s updated, Argo CD rolls out the application pod with the new image tag.<\/p>\n<p>The annotation used to specify this method is:<\/p>\n<pre><code class=\"language-bash\">argocd-image-updater.argoproj.io\/write-back-method: argocd<\/code><\/pre>\n<h4 id=\"git\">git<\/h4>\n<p>This method creates a file named <code>.argocd-source-&lt;app-name&gt;.yaml<\/code> in GitHub and writes the parameters that have changed in the file.<\/p>\n<p>Then Argo CD notices the change in GitHub and updates the application pod.<\/p>\n<p>The annotation used to specify this method is:<\/p>\n<pre><code class=\"language-bash\">argocd-image-updater.argoproj.io\/write-back-method: git<\/code><\/pre>\n<p>For detailed information on the write-back method, refer to the <a href=\"https:\/\/argocd-image-updater.readthedocs.io\/en\/stable\/basics\/update-methods\/?ref=devopscube.com\">official documentation<\/a>.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>You have installed Argo CD Image Updater, connected it to <strong>ECR<\/strong>, deployed a sample <strong>Flask<\/strong> app, and verified automatic tag updates and rollouts. <\/p>\n<p>Also you learned common annotations and strategies to fine\u2011tune updates.<\/p>\n<p>I hope this blog gives you an understanding of Argo CD Image Updater. For more information and edge cases, refer to the <a href=\"https:\/\/argocd-image-updater.readthedocs.io\/en\/stable\/?ref=devopscube.com\">official documentation<\/a>.<\/p>\n<hr>\n<p><strong>Ngu\u1ed3n:<\/strong> <a href=\"https:\/\/devopscube.com\/setup-argocd-image-updater\/\" target=\"_blank\" rel=\"noopener noreferrer\">How to Use Argo CD Image Updater with AWS ECR (Step-by-Step Guide) \u2014 DevOpsCube<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Source: https:\/\/devopscube.com\/setup-argocd-image-updater\/<\/p>\n","protected":false},"author":1,"featured_media":481,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-480","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/480","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=480"}],"version-history":[{"count":0,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/480\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/media\/481"}],"wp:attachment":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=480"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=480"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=480"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}