Dynamic Docker Image Generation by GitHub Actions with User Inputs
A Real World Scenario with Building NextJS Applications by Defining Dynamic ENV Variables
Hi folks! Have you ever needed to use the same codebase for different clients? Did you manage that by forking the same repo or by managing a branch? To be honest, I have managed the problem by forking the repo for each client until the method that I am going to tell you in this article.
We are not going to develop something from zero. Instead of developing from zero, I am going to tell you about the scenario and the method.
The Project
The project is developed by using NextJS. The idea behind it is to make api calls to a Django app. Users can log in and donate. There are some other payment related features.
*Unfortunately, the frontend project is not public at the moment.
The Case
BaysanSoft should maintain the same repo for each client and the clients should use the same codebases with their own configurations by defining their own env variables below. By using these variables, the same project can be used in different forms.
- NEXT_PUBLIC_BASE_API_URL
- NEXT_PUBLIC_ORGANIZATION_NAME
- NEXT_PUBLIC_ORGANIZATION_LINK
- NEXT_PUBLIC_ORGANIZATION_LOGO
- NEXT_PUBLIC_PRIMARY_COLOR
- NEXT_PUBLIC_SECONDARY_COLOR
If you know NextJS then you probably know it requires the environment variables while building the project. Therefore we define the environment variables in build time. Our GitHub Actions workflow is going to define these variables by using our inputs.
*The project below is our backend project which is publicly available on GitHub and free to use. As I know, some organizations are using their own setups with their own IT teams.
The Solution — GitHub Actions
There is a concept called workflow_dispatch
In GitHub Actions. It is an event that triggers the workflows. It helps us to manually run the workflows and pass the input variables if they exist.
on:
workflow_dispatch:
inputs:
public-base-api-url:
description: 'Public base API URL to use in the app'
required: true
type: string
Final workflow file is below. We can pass input variables by extracting them from inputs
context.
name: CI
on:
workflow_dispatch:
inputs:
docker-hub-username:
description: 'Docker Hub username'
required: true
type: string
docker-hub-token:
description: 'Docker Hub token'
required: true
type: string
docker-image-tag:
description: 'Docker image tag'
required: true
type: string
public-base-api-url:
description: 'Public base API URL to use in the app'
required: true
type: string
organization-name:
description: 'Organization name to use in header'
required: true
type: string
organization-link:
description: 'Organization link to use in header'
required: true
type: string
organization-logo-url:
description: 'Organization logo URL to use in header'
required: true
type: string
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Print Image Tag
run: echo ${{inputs.docker-hub-username}}/${{inputs.docker-image-tag}}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ inputs.docker-hub-username }}
password: ${{ inputs.docker-hub-token }}
- name: Build and push
uses: docker/build-push-action@v3
with:
push: true
tags: ${{ inputs.docker-hub-username }}/${{ inputs.docker-image-tag }}
build-args: |
NEXT_PUBLIC_BASE_API_URL=${{ inputs.public-base-api-url }}
NEXT_PUBLIC_ORGANIZATION_NAME=${{ inputs.organization-name }}
NEXT_PUBLIC_ORGANIZATION_LINK=${{ inputs.organization-link }}
NEXT_PUBLIC_ORGANIZATION_LOGO=${{ inputs.organization-logo-url }}
Well done! We can pass the input variables to use them in build time. We are able to build/create the same app in different forms with this setup.
You see 3 different forms of the same repo below.
Finally
After getting experience in the sector, I understood that to code something mostly is the easiest part. My intention was to tell you a real world scenario about how we get benefit from GitHub Actions. Therefore, I didn’t code something from zero and didn’t write every step. Hopefully, this article helps you to configure your own CI pipelines.
You can find my links below to follow me on other platforms.
Kind regards