Build ECR image
Overviewโ
This guide demonstrates how to build and push a Docker image to AWS ECR with meaningful tags using self-service action.
- Self-service: Enable developers to build and push Docker images to AWS ECR without needing to access AWS, while ensuring that images are following a consistent tagging convention.
- Automation: Automatically tag Docker images with meaningful information like commit ID, PR ID, and workflow ID.
- Traceability: Track the source of the image and the entity that triggered the build.
In the following guide, you are going to create a self-service action in Port that executes a GitHub workflow to:
- Generate a Docker image with tags.
- Push the image to an AWS Elastic Container Registry (ECR).
The image will include tags indicating information like the trigger source, commit ID, PR ID, and workflow ID.
Prerequisitesโ
- Install Port's GitHub app by clicking here.
- This guide assumes the presence of a blueprint representing your repositories. If you haven't done so yet, initiate the setup of your GitHub data model by referring to this guide first.
- A repository to contain your action resources i.e. the github workflow file.
- In your GitHub repository, go to Settings > Secrets and add the following secrets:
- AWS_ACCESS_KEY_ID: Your AWS access key.
- AWS_SECRET_ACCESS_KEY: Your AWS secret access key.
- ECR_REGISTRY: Your AWS ECR registry URI.
 
- Create an AWS ECR repository if you haven't already. Take note of your repository URI. This is where the docker image will be pushed.
GitHub Workflowโ
Create the file create-and-push-image.yml in the .github/workflows folder of your repository.
We recommend creating a dedicated repository for the workflows that are used by Port actions.
GitHub Workflow
name: Create and Push Image to ECR
on:
  workflow_dispatch:
    inputs:
      image_repo:
        description: 'Repository URL'
        required: true
      dockerfile:
        description: 'Path to Dockerfile'
        required: true
      port_context:
        required: true
        description: "Action and general context (blueprint, run id, etc...)"
        type: string
jobs:
  build:
    runs-on: ubuntu-latest
    env:
      REPO_URL: ${{ fromJson(inputs.port_context).entity.properties.url }}
      TRIGGERED_BY: ${{ fromJson(inputs.port_context).trigger.by.user.email || github.actor }}
      RUN_ID: ${{ fromJson(inputs.port_context).runId }}
    steps:
      - name: Inform execution of request to build ECR image
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: PATCH_RUN
          runId: ${{ env.RUN_ID }}
          logMessage: "Starting build of ECR image..."
      - name: Extract repository owner and name
        run: |
          repo_owner=$(echo "${REPO_URL}" | awk -F/ '{print $4}')
          repo_name=$(echo "${REPO_URL}" | awk -F/ '{print $5}')
          echo "REPO_OWNER=$repo_owner" >> $GITHUB_ENV
          echo "REPO_NAME=$repo_name" >> $GITHUB_ENV
        shell: bash
    
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          repository: ${{ env.REPO_OWNER }}/${{ env.REPO_NAME }}
      - name: Get short commit ID
        id: get-commit-id
        run: |
          echo "COMMIT_SHORT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
          echo "COMMIT_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV
        shell: bash
      - name: Inform execution of request to build ECR image
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: PATCH_RUN
          runId: ${{ env.RUN_ID }}
          logMessage: "Configuring AWS credentials..."
      
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-region: ${{ secrets.AWS_REGION }}
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      - name: Login to AWS ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1
      - name: Inform execution of request to build ECR image
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          baseUrl: https://api.getport.io
          operation: PATCH_RUN
          runId: ${{ env.RUN_ID }}
          logMessage: "Building docker image..."
      - name: Build and push Docker image
        env:
          ECR_REGISTRY: ${{ secrets.ECR_REGISTRY }}
          ECR_REPOSITORY: ${{ inputs.image_repo }}
        run: |
          # Build and push image with short commit ID and triggered by as tags
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$COMMIT_SHORT .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$COMMIT_SHORT
          # Tag image with commit ID and push
          docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$COMMIT_SHORT $ECR_REGISTRY/$ECR_REPOSITORY:$COMMIT_SHA
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$COMMIT_SHA
          # Tag image with triggered by and push
          docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$COMMIT_SHORT $ECR_REGISTRY/$ECR_REPOSITORY:actor-${TRIGGERED_BY//[^a-zA-Z0-9]/-}
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:actor-${TRIGGERED_BY//[^a-zA-Z0-9]/-}
          # Tag image with PR ID and push
          if [ "${{ github.event_name }}" == "pull_request" ]; then
            PR_ID=$(echo "${{ github.event.pull_request.number }}" | tr -d '/')
            docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$COMMIT_SHORT $ECR_REGISTRY/$ECR_REPOSITORY:pr-$PR_ID
            docker push $ECR_REGISTRY/$ECR_REPOSITORY:pr-$PR_ID
          fi
          # Tag image with workflow ID and push
          docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$COMMIT_SHORT $ECR_REGISTRY/$ECR_REPOSITORY:build-${{ github.run_id }}
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:build-${{ github.run_id }}
      - name: Notify Port of successful build
        uses: port-labs/port-github-action@v1
        with:
          clientId: ${{ secrets.PORT_CLIENT_ID }}
          clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
          operation: PATCH_RUN
          status: "SUCCESS"
          baseUrl: https://api.getport.io
          runId: ${{ fromJson(inputs.port_context).runId }}
          logMessage: |
            Built and pushed image to ECR repo ${{ inputs.image_repo }}
Port Configurationโ
- 
Head to the self-service page. 
- 
Click on the + New Actionbutton.
- 
Choose the Repositoryblueprint and clickNext.  
- 
Click on the {...} Edit JSONbutton.
- 
Copy and paste the following JSON configuration into the editor. 
Port Action
Make sure to replace <GITHUB_ORG> and <GITHUB_REPO> with your GitHub organization and repository names respectively.
{
  "identifier": "build_ecr_image",
  "title": "Build ECR Image",
  "icon": "AWS",
  "description": "Build Image and Push to ECR",
  "trigger": {
    "type": "self-service",
    "operation": "DAY-2",
    "userInputs": {
      "properties": {
        "dockerfile": {
          "icon": "Docker",
          "title": "Dockerfile",
          "description": "The path to the dockerfile e.g Dockerfile or ./deploy/prod.Dockerfile",
          "type": "string",
          "default": "Dockerfile"
        },
        "image_repo": {
          "title": "Image Repository",
          "description": "The Elastic Container Repository Name",
          "icon": "AWS",
          "type": "string"
        }
      },
      "required": [
        "dockerfile",
        "image_repo"
      ],
      "order": [
        "dockerfile"
      ]
    },
    "blueprintIdentifier": "repository"
  },
  "invocationMethod": {
    "type": "GITHUB",
    "org": "<GITHUB_ORG>",
    "repo": "<GITHUB_REPO>",
    "workflow": "create-and-push-image.yml",
    "workflowInputs": {
      "dockerfile": "{{ .inputs.\"dockerfile\" }}",
      "image_repo": "{{ .inputs.\"image_repo\" }}",
      "port_context": {
        "entity": "{{ .entity }}",
        "blueprint": "{{ .action.blueprint }}",
        "runId": "{{ .run.id }}",
        "trigger": "{{ .trigger }}"
      }
    },
    "reportWorkflowStatus": true
  },
  "requiredApproval": false
  
}
- Click Save.
Now you should see the Build ECR Image action in the self-service page. ๐
Let's test it!โ
- On the self-service page, go to the Build ECR Imageaction and fill in the properties.
 
- Click the execute button to trigger the GitHub workflow.
- The image is built and pushed to your ECR repository.
 
Let's assume your AWS ECR repository is named your-ecr-repository-name. Here's how the Docker image names will be tagged based on the provided workflow:
- 
Primary Tag: Short Commit ID - Tag: your-ecr-repository-name:abc123(assumingabc123is the short commit ID)
 
- Tag: 
- 
Secondary Tags: Full Commit ID, PR ID, Workflow ID, Triggered By - Tag: your-ecr-repository-name:abc1234567890123456789012345678901234567(full commit ID)
- Tag (PR): your-ecr-repository-name:pr-42(assuming the pull request ID is 42)
- Tag (Workflow): your-ecr-repository-name:build-123456789(workflow ID)
- Tag (Triggered By): your-ecr-repository-name:actor-username(replace "username" with the actual GitHub username or the name of the system triggering the workflow)
 
- Tag: 
You may also change the prefixes to context-appropriate ones i.e. you may prefer your-ecr-repository-name:username instead of having the actor prefix.
These tags provide meaningful information about the image, such as the commit ID, pull request ID (if applicable), workflow ID, and the entity triggering the workflow.
Done! ๐ You can now build and push images for your repositories from Port.