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
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
-
Go to https://quay.io and sign in.
-
Click “+ New Repository”.
-
Choose:
- Name (e.g.,
my-app) - Visibility (Public or Private)
- Namespace: your username or an organization
- Name (e.g.,
-
Click “Create Repository”.
Step 2: Create a robot account (recommended for CI/CD)
-
Go to your namespace page:
https://quay.io/organization/<your-namespace>/robots(For personal accounts:https://quay.io/user/<your-username>?tab=robots) -
Click “Create Robot Account”.
- Example:
ci-bot - This will generate a username like
yournamespace+ci-bot
- Example:
-
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:
- Go to Settings → Secrets and variables → Actions
- Click “New repository secret” and add:
| Name | Value |
|---|---|
QUAY_USERNAME | yournamespace+ci-bot |
QUAY_PASSWORD | The 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.