Skip to content
Joey Wang
Menu

Search

DevOps and Reliability

Build and Push Docker Images to Quay.io with GitHub Actions

A working GitHub Actions workflow that builds a Docker image and pushes it to Quay.io using a scoped robot account and repository secrets.

· 2 min read

devops #docker#github-actions#ci#devops

Audio summary

Pushing images to Quay.io from GitHub Actions comes down to four steps: create the repository, create a robot account scoped to it, store its credentials as GitHub secrets, and write the workflow that logs in and pushes.

Step 1: Create a repository on Quay.io

  1. Go to https://quay.io and sign in.

  2. Click “+ New Repository”.

  3. Choose:

    • Name (e.g., my-app)
    • Visibility (Public or Private)
    • Namespace: your username or an organization
  4. Click “Create Repository”.


  1. Go to your namespace page: https://quay.io/organization/<your-namespace>/robots (For personal accounts: https://quay.io/user/<your-username>?tab=robots)

  2. Click “Create Robot Account”.

    • Example: ci-bot
    • This will generate a username like yournamespace+ci-bot
  3. After creation:

    • Copy the generated token/password

    • Assign the robot write permissions on your repository:

      • Go to the repository settings → Permissions tab
      • Add the robot account and give it Write or Admin access

Step 3: Add secrets to GitHub

In your GitHub repository:

  1. Go to SettingsSecrets and variablesActions
  2. Click “New repository secret” and add:
NameValue
QUAY_USERNAMEyournamespace+ci-bot
QUAY_PASSWORDThe robot account token

Step 4: Write a GitHub Actions workflow

Create .github/workflows/docker-build.yml:

name: Build and Push Docker Image

on:
  push:
    branches: [main] # Or your deployment branch

jobs:
  build-and-push:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Log in to Quay.io
        run: echo "${{ secrets.QUAY_PASSWORD }}" | docker login quay.io -u "${{ secrets.QUAY_USERNAME }}" --password-stdin

      - name: Build Docker image
        run: |
          docker build -t quay.io/${{ secrets.QUAY_USERNAME }}/my-app:latest .

      - name: Push Docker image
        run: |
          docker push quay.io/${{ secrets.QUAY_USERNAME }}/my-app:latest

Optional enhancements

  • Tag with Git SHA or date:

    IMAGE_TAG=$(git rev-parse --short HEAD)
    docker build -t quay.io/${{ secrets.QUAY_USERNAME }}/my-app:$IMAGE_TAG .
    docker push quay.io/${{ secrets.QUAY_USERNAME }}/my-app:$IMAGE_TAG
  • Support multiple tags (e.g., latest + commit):

    - name: Tag and push
      run: |
        SHA=${{ github.sha }}
        docker tag quay.io/...:latest quay.io/...:$SHA
        docker push quay.io/...:$SHA

Conclusion

A scoped robot account plus GitHub secrets is enough to build and push images to Quay.io securely from CI. Quay.io’s image scanning and access controls are the main reason to pick it over Docker Hub in the first place; this workflow is what makes that choice usable in practice.