Commit 20e50e8
Muhamad Sazwan Bin Ismail
Create Docker image GitHub
# 🐳 Docker Image GitHub Actions Workflow – Complete Guide
You want to create a GitHub Actions workflow to build and push a Docker image automatically whenever you push code or create a release. This is a crucial part of modern CI/CD pipelines, especially for projects involving microservices, AI models, or deployable applications.
Below I'll provide you with a **production‑ready template** for `.github/workflows/docker-image.yml`, explain each part, and show you how to customize it for your needs (e.g., pushing to Docker Hub, GitHub Container Registry, or both).
---
## 📁 File Location
Place this file in your repository at:
```
.github/workflows/docker-image.yml
```
---
## 🚀 Full Workflow Example
```yaml
name: Build and Push Docker Image
on:
push:
branches: [ "main", "develop" ]
tags: [ "v*.*.*" ]
pull_request:
branches: [ "main" ]
release:
types: [ published ]
env:
REGISTRY: docker.io # change to ghcr.io for GitHub Container Registry
IMAGE_NAME: ${{ github.repository }} # e.g., username/repo
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write # needed for GHCR
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
# If you want to push to GitHub Container Registry instead (or in addition)
# - name: Log in to GHCR
# uses: docker/login-action@v3
# with:
# registry: ghcr.io
# username: ${{ github.actor }}
# password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,format=long
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64 # optional: multi‑arch
```
---
## 🔍 Step‑by‑Step Explanation
### 1. **Triggers (`on`)**
The workflow runs on:
- `push` to `main` or `develop` branches.
- `push` of tags matching `v*.*.*` (e.g., `v1.2.3`).
- `pull_request` to `main` (builds only, does **not** push).
- `release` published (ideal for final tagging).
Adjust the branches and patterns to match your workflow.
### 2. **Environment Variables**
- `REGISTRY`: set to `docker.io` for Docker Hub, or `ghcr.io` for GitHub Container Registry.
- `IMAGE_NAME`: uses `github.repository` (e.g., `yourusername/yourrepo`). You can hardcode a custom name if needed.
### 3. **Permissions**
- `packages: write` is required if you push to GHCR. For Docker Hub you don’t need it, but it’s harmless to keep.
### 4. **Checkout**
Fetches your code so the Docker build can use it.
### 5. **Set up Docker Buildx**
Enables advanced features like multi‑platform builds and better caching.
### 6. **Login to Registry**
- **Docker Hub**: uses secrets `DOCKER_USERNAME` and `DOCKER_PASSWORD`.
(Create these in your repository **Settings → Secrets and variables → Actions**.)
- **GHCR**: uses the built‑in `GITHUB_TOKEN` – no extra secrets needed. Uncomment the second login block if you want to push there as well.
### 7. **Metadata Extraction**
The `docker/metadata-action` generates Docker tags and labels based on the git reference.
Common tag types:
- `type=ref,event=branch` → e.g., `main`, `develop`
- `type=ref,event=pr` → `pr-123`
- `type=semver,pattern={{version}}` → for tags: `v1.2.3`, `v1.2`, `v1`
- `type=sha,format=long` → full commit hash
- `type=raw,value=latest,enable={{is_default_branch}}` → adds `latest` only on the default branch
You can customise the tag list as you like.
### 8. **Build and Push**
- `push: true` only when the event is **not** a pull request (to avoid pushing PR images).
- `tags` and `labels` come from the metadata step.
- **Caching** (`cache-from` / `cache-to` with `type=gha`) uses GitHub Actions cache to speed up subsequent builds.
- `platforms`: optional, enables multi‑architecture images (e.g., both Intel and ARM). Requires QEMU setup (see below).
---
## 🧪 Adding Multi‑Platform Builds
If you need images for different CPU architectures (e.g., `linux/arm64` for Raspberry Pi), include these steps before `buildx`:
```yaml
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
```
Then in the build step, add:
```yaml
platforms: linux/amd64,linux/arm64,linux/arm/v7
```
---
## 🔒 Security Scanning
Integrate vulnerability scanning to ensure your images are safe:
```yaml
- name: Scan image with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: 'trivy-results.sarif'
```
Add this **after** the build step.
---
## 🧪 Running Tests Before Building
You can add a separate job for testing, or include test steps in the same job:
```yaml
- name: Run unit tests
run: |
docker build --target test -t test-image .
docker run --rm test-image npm test
```
(Assumes your Dockerfile has a `test` stage.)
---
## 📦 Using the GitHub Container Registry (GHCR)
If you prefer GHCR over Docker Hub:
- Set `REGISTRY: ghcr.io`
- Use the GHCR login step (already shown, commented out).
- Your image will be available at `ghcr.io/yourusername/yourrepo:tag`.
---
## 🔐 Required Secrets
| Secret Name | Description |
|-------------|-------------|
| `DOCKER_USERNAME` | Your Docker Hub username |
| `DOCKER_PASSWORD` | Docker Hub password or access token (recommended) |
If you use two‑factor authentication on Docker Hub, create an **access token** (Account Settings → Security → New Access Token) and use that as the password.
For GHCR, no secrets are needed – `GITHUB_TOKEN` is automatically provided.
---
## 🧠 Customizing for Your Project
### **Context Path**
If your Dockerfile is not in the repository root, change `context` to the correct folder, e.g.:
```yaml
context: ./my-service
```
### **Dockerfile Name**
If your Dockerfile has a different name, add:
```yaml
file: ./my-service/Dockerfile.custom
```
### **Tagging Overrides**
Add custom tags using `type=raw`:
```yaml
tags: |
type=raw,value=production,enable=${{ github.ref == 'refs/heads/production' }}
```
---
## ✅ Example Workflow in Action
1. You push a commit to `main`.
2. GitHub Actions triggers the workflow.
3. It builds the Docker image with tags: `main`, `latest`, and the commit SHA.
4. The image is pushed to Docker Hub.
5. (Optional) Trivy scans it and uploads results.
When you create a release (or push a tag `v1.2.3`), it also builds and pushes `v1.2.3`, `v1.2`, `v1`.
---
## 📚 Next Steps
1. **Copy the template** into your repository.
2. **Add secrets** if using Docker Hub.
3. **Commit and push** to see the first run.
4. **Check the Actions tab** in your GitHub repo to monitor progress.
You now have a fully automated Docker build pipeline. Combine it with your Firebase AI, ESP32, and WebRTC projects to deploy microservices effortlessly. Let me know if you need help adapting it to a specific part of your system! 🚀1 parent aa17a0e commit 20e50e8
1 file changed
+893
-0
lines changed
0 commit comments