Skip to content
name: Build and Publish Docker Image
on:
push:
branches: [ "main" ] # Trigger the workflow when code is pushed to the main branch
pull_request:
branches: [ "main" ] # Trigger the workflow for pull requests targeting the main branch
env:
REGISTRY: ghcr.io # Set the Docker registry to GitHub Container Registry (ghcr.io)
IMAGE_NAME: ${{ github.repository }} # Use the GitHub repository name as the Docker image name
jobs:
build-and-publish:
runs-on: ubuntu-latest # Use the latest stable Ubuntu version as the runner environment
permissions:
contents: read # Allows reading of repository contents
packages: write # Allows publishing packages (e.g., Docker images) to GitHub Packages
id-token: write # Required for future features like signing images with cosign
steps:
# Step 1: Check out the repository code
- name: Checkout repository
uses: actions/checkout@v4 # This action checks out the repository code for use in the workflow
# Step 2: Extract version information from package.json
- name: Extract version from package.json
id: version # Assign an ID to reference this step's outputs later if needed
run: |
# Extract the semantic version (e.g., 1.2.3) from the package.json file
SEMVER=$(grep '"version":' package.json | cut -d '"' -f 4)
# Store the extracted version as an environment variable for use in later steps
echo "SEMVER=$SEMVER" >> $GITHUB_ENV
# Step 3: Set up Docker Buildx
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 # Set up Docker Buildx to enable advanced Docker features
# Docker Buildx allows for multi-platform builds, build caching, and more
# Step 4: Log in to the Docker registry
- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@v3 # Log into the Docker registry to enable pushing images
with:
registry: ${{ env.REGISTRY }} # Specify the Docker registry (ghcr.io)
username: ${{ github.actor }} # Use the GitHub actor (the user triggering the workflow) as the username
password: ${{ secrets.GITHUB_TOKEN }} # Use the GitHub token to authenticate (securely passed as a secret)
# Step 5: Extract Docker image metadata (tags, labels)
- name: Extract Docker metadata
id: meta # Assign an ID to reference this step's outputs (tags and labels) in the build step
uses: docker/metadata-action@v5 # This action generates Docker image metadata like tags and labels
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} # Define the full image name (registry/repository)
tags: |
# Create various tags for the Docker image based on version information
type=raw,value=latest # Tag the image as "latest"
type=semver,pattern={{major}}.{{minor}}.{{patch}},value=${{ env.SEMVER }} # Full version tag (e.g., 1.2.3)
type=semver,pattern={{major}}.{{minor}},value=${{ env.SEMVER }} # Major.minor tag (e.g., 1.2)
type=semver,pattern={{major}},value=${{ env.SEMVER }} # Major tag (e.g., 1)
# Step 6: Build and push the Docker image
- name: Build and push Docker image
id: build-and-push # Assign an ID to reference this step's outputs (digest) if needed later
uses: docker/build-push-action@v5 # This action builds and pushes the Docker image
with:
context: . # Use the root of the repository as the build context (includes Dockerfile and source code)
push: ${{ github.event_name != 'pull_request' }} # Push the image only if the event is not a pull request
tags: ${{ steps.meta.outputs.tags }} # Apply the tags generated in the metadata step
labels: ${{ steps.meta.outputs.labels }} # Apply the labels generated in the metadata step
cache-from: type=gha # Use GitHub Actions cache to speed up the build process
cache-to: type=gha,mode=max # Store the build cache in GitHub Actions for future use