Introduction
This tutorial teaches how to configure automatic deployment on Zenifra using GitHub Actions. The flow allows the OCI image to be built and sent to Zenifra automatically whenever there is a new change in the repository.
Important: This flow is for projects with OCI Image source. It does not replace the flow for projects created with
GitHub Repositorysource.
Prerequisites
- Git repository with the application source code
- HTTP project already created on Zenifra
- GitHub account
What you will learn
- Configure GitHub Actions for automatic image build
- Configure automatic deployment to the Zenifra platform
- Trigger deployments through version tags
Step 1: Configure GitHub Secrets
Before creating the workflow, configure the required secrets in your GitHub repository:
- Open Settings > Secrets and variables > Actions in your repository
- Add the following secrets:
| Secret | Description |
|---|---|
OCI_USERNAME | Docker registry username (for example: Docker Hub) |
OCI_PASSWORD | Registry access token |
ZENIFRA_PROJECT_ID | Project ID on Zenifra |
ZENIFRA_API_KEY | Project API Key on Zenifra |
Important: Project ID and API Key are shown only when the project is created. Store them safely.
Step 2: Create the Workflow
Create the file .github/workflows/deploy.yml in your repository:
name: Deploy PRD
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
jobs:
build:
name: Build and Publish Image
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Registry
uses: docker/login-action@v3
with:
username: ${{ secrets.OCI_USERNAME }}
password: ${{ secrets.OCI_PASSWORD }}
- name: Build and Publish OCI Image
run: |
docker buildx build \
--tag ${{ secrets.OCI_USERNAME }}/my-app:${{ github.ref_name }} \
--platform=linux/amd64 \
--push .
deploy:
name: Deploy to Zenifra
needs: build
runs-on: ubuntu-latest
steps:
- name: Deploy Image to Zenifra
uses: zenifra/action-zenifra-deploy@main
with:
PROJECT_ID: ${{ secrets.ZENIFRA_PROJECT_ID }}
API_KEY: ${{ secrets.ZENIFRA_API_KEY }}
IMAGE: ${{ secrets.OCI_USERNAME }}/my-app:${{ github.ref_name }}Workflow Settings
| Field | Description |
|---|---|
on.push.tags | Triggers the workflow when a tag in the format v1.0.0 is created |
OCI_USERNAME | Your Docker registry username |
PROJECT_ID | Zenifra project ID |
API_KEY | Project API key |
IMAGE | Full image URI with tag |
Step 3: Trigger the Deployment
To trigger the deployment:
-
Create a version tag in your repository:
git tag v1.0.0 git push origin v1.0.0 -
GitHub Actions will execute:
- Docker image build
- Registry publication
- Automatic deployment to Zenifra
Deployment with AWS ECR
Besides Docker Hub, you can use AWS ECR (Elastic Container Registry) as the container registry. The example below demonstrates a full workflow using AWS ECR.
Required Secrets
Add the following secrets to your GitHub repository:
| Secret | Description |
|---|---|
AWS_ACCESS_KEY_ID | AWS Access Key ID with permissions for ECR |
AWS_SECRET_ACCESS_KEY | AWS Secret Access Key |
AWS_REGION | AWS region (for example: us-east-1) |
AWS_ECR_URL | Your ECR registry URL (for example: 123456789.dkr.ecr.us-east-1.amazonaws.com) |
ZENIFRA_PROJECT_ID | Project ID on Zenifra |
ZENIFRA_API_KEY | Project API Key on Zenifra |
Full Workflow (Tag-based Deployment)
This workflow is triggered when a tag in the format v1.0.0 is created:
name: Deploy PRD
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
jobs:
build:
name: Build and Publish Image
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: linux/amd64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build and Publish Image to ECR
run: |
docker buildx build \
--tag ${{ secrets.AWS_ECR_URL }}/my-app:${{ github.ref_name }} \
--platform=linux/amd64 \
--push .
deploy:
name: Deploy to Zenifra
needs: build
runs-on: ubuntu-latest
steps:
- name: Deploy Image to Zenifra
uses: ramonpaolo/action-zenifra@main
with:
PROJECT_ID: ${{ secrets.ZENIFRA_PROJECT_ID }}
API_KEY: ${{ secrets.ZENIFRA_API_KEY }}
IMAGE: ${{ secrets.AWS_ECR_URL }}/my-app:${{ github.ref_name }}Pull Request Workflow (Staging Deployment)
This workflow is triggered whenever a pull request is opened or updated:
name: Deploy STG
on:
pull_request:
types:
- opened
- synchronize
jobs:
build:
name: Build and Publish Image
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: linux/amd64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build and Publish Image to ECR
run: |
docker buildx build \
--tag ${{ secrets.AWS_ECR_URL }}/my-app-stg:${{ github.sha }} \
--platform=linux/amd64 \
--push .
deploy:
name: Deploy to Zenifra
needs: build
runs-on: ubuntu-latest
steps:
- name: Deploy Image to Zenifra
uses: ramonpaolo/action-zenifra@main
with:
PROJECT_ID: ${{ secrets.ZENIFRA_PROJECT_ID_STG }}
API_KEY: ${{ secrets.ZENIFRA_API_KEY_STG }}
IMAGE: ${{ secrets.AWS_ECR_URL }}/my-app-stg:${{ github.sha }}Advantages of AWS ECR
| Advantage | Description |
|---|---|
| AWS Integration | Natively integrated with other AWS services |
| Performance | Low latency when used with EC2/ECS/Fargate |
| Security | Encryption at rest with KMS |
| Cost | Pay only for used storage |
| IAM | Granular access control through IAM policies |
Creating an ECR Repository
Before using the workflow, create a repository in AWS ECR:
aws ecr create-repository \
--repository-name my-app \
--region us-east-1The command returns the repository URL:
123456789.dkr.ecr.us-east-1.amazonaws.com/my-appValidation
To verify that the deployment completed successfully:
- Open the Zenifra console
- Select your project
- In the Deployments tab, confirm there is a new deploy with status
success - Open the project URL to confirm that the new version is active
Next Steps
FAQ
Can I use another registry besides Docker Hub?
Yes. You can use AWS ECR, Google Container Registry (GCR), GitHub Container Registry (GHCR), Azure Container Registry (ACR), among others. Each one has its own login action:
- AWS ECR:
aws-actions/amazon-ecr-login@v2 - GCR/Artifact Registry:
docker/login-action@v3 - GHCR:
docker/login-action@v3(username:${{ github.actor }}, password:ghp_xxx)
How does versioning work?
The workflow uses the Git tag as the image version. For example, when creating the tag v1.2.3, the image becomes your-app:v1.2.3.
What is the difference between tag deployment and pull request deployment?
| Aspect | By Tag | By Pull Request |
|---|---|---|
| Typical use | Production | Staging/QA |
| Versioning | Semantic (v1.0.0) | Commit hash |
| Trigger | git push tag v1.0.0 | git push on the branch |
| Environment | PRD | STG |
What happens if the build fails?
Deployment to Zenifra is not executed. You will receive a failure notification from GitHub Actions with the error logs.
How do I configure IAM permissions for AWS ECR?
Create an IAM policy with the following permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:PutImage"
],
"Resource": "arn:aws:ecr:us-east-1:123456789:repository/minha-app"
}
]
}Can I do multi-platform deployment (AMD64 + ARM64)?
Yes. Add both platforms in the configuration:
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: linux/amd64,linux/arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64,linux/arm64