Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
**/*
!package.json
!package-lock.json
!guide
!nginx.conf
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DOCKER_REGISTRY=registry.mydomain.com
29 changes: 0 additions & 29 deletions .github/workflows/main.yml

This file was deleted.

67 changes: 67 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Build and Release Docker Image

on:
push:
branches:
- main
tags:
- 'v*'
pull_request:
branches:
- main

env:
REGISTRY: ${{ secrets.DOCKER_REGISTRY || 'docker.io' }}
IMAGE_NAME: raspdevpy/${{ github.event.repository.name }}

jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Private Registry
if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr,prefix=pr-
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push Docker image
uses: docker/build-push-action@v5
timeout-minutes: 20
with:
context: .
platforms: linux/amd64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
BUILD_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}
GIT_COMMIT=${{ github.sha }}
VERSION=${{ steps.meta.outputs.version }}
cache-from: ${{ github.event_name == 'pull_request' && 'type=local,src=/tmp/.buildx-cache' || format('type=registry,ref={0}/{1}:cache', env.REGISTRY, env.IMAGE_NAME) }}
cache-to: ${{ github.event_name == 'pull_request' && 'type=local,dest=/tmp/.buildx-cache-new,mode=max' || format('type=registry,ref={0}/{1}:cache,mode=max', env.REGISTRY, env.IMAGE_NAME) }}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ ignore/*
.DS_Store
guide/.vuepress/public/images/*
.vscode
OnTemplate.md
OnTemplate.md
.env
23 changes: 23 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Stage 1 — build the static assets
FROM node:20-alpine3.21 AS builder
WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .
# adjust the build command if your project uses a different script
RUN npm run build

# Stage 2 — serve with nginx
FROM nginx:1.25-alpine
ARG BUILD_DIR=guide/.vuepress/dist

# Remove default config and add a simple SPA-friendly config
COPY nginx.conf /etc/nginx/conf.d/default.conf

# Copy built static files from the builder stage
COPY --from=builder /app/${BUILD_DIR} /usr/share/nginx/html

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
65 changes: 65 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
include .env

# Variables
# DOCKER_REGISTRY ?=
DOCKER_REPO ?= raspdevpy/$(shell basename `git remote get-url origin`)
VERSION ?= $(shell git describe --tags --always --dirty)
LATEST_TAG := latest
BUILD_DATE := $(shell date -u +"%Y-%m-%dT%H:%M:%SZ")
GIT_COMMIT := $(shell git rev-parse HEAD)

# Docker image tags
IMAGE_TAG := $(DOCKER_REGISTRY)/$(DOCKER_REPO):$(VERSION)
LATEST_IMAGE := $(DOCKER_REGISTRY)/$(DOCKER_REPO):$(LATEST_TAG)

.PHONY: help build push release clean login test

help: ## Show this help message
@echo "Available targets:"
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " %-15s %s\n", $$1, $$2}' $(MAKEFILE_LIST)

build: ## Build Docker image
@echo "Building Docker image: $(IMAGE_TAG)"
docker build \
--build-arg BUILD_DATE=$(BUILD_DATE) \
--build-arg GIT_COMMIT=$(GIT_COMMIT) \
--build-arg VERSION=$(VERSION) \
-t $(IMAGE_TAG) \
-t $(LATEST_IMAGE) \
.
@echo "Built: $(IMAGE_TAG)"
@echo "Built: $(LATEST_IMAGE)"

test: ## Test the Docker image
@echo "Testing Docker image: $(IMAGE_TAG)"
# docker run --rm $(IMAGE_TAG) curl http://localhost:80/index.html

test-interactive: ## Run an interactive shell in the Docker image for testing
@echo "Starting interactive shell in Docker image: $(IMAGE_TAG)"
docker run --rm -it $(IMAGE_TAG) sh

login: ## Login to Docker registry
@echo "Logging into Docker registry: $(DOCKER_REGISTRY)"
docker login $(DOCKER_REGISTRY)

push: ## Push Docker image to registry
@echo "Pushing Docker image: $(IMAGE_TAG)"
docker push $(IMAGE_TAG)
docker push $(LATEST_IMAGE)
@echo "Pushed: $(IMAGE_TAG)"
@echo "Pushed: $(LATEST_IMAGE)"

release: build test push ## Build, test and push Docker image
@echo "Release completed for version: $(VERSION)"

clean: ## Remove local Docker images
@echo "Cleaning up local Docker images"
-docker rmi $(IMAGE_TAG) 2>/dev/null || true
-docker rmi $(LATEST_IMAGE) 2>/dev/null || true

# CI/CD helpers
ci-info: ## Show build information for CI
@echo "VERSION=$(VERSION)"
@echo "IMAGE_TAG=$(IMAGE_TAG)"
@echo "BUILD_DATE=$(BUILD_DATE)"
@echo "GIT_COMMIT=$(GIT_COMMIT)"
11 changes: 11 additions & 0 deletions nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
server {
listen 80;
server_name _;

root /usr/share/nginx/html;
index index.html;

location / {
try_files $uri $uri/ /index.html;
}
}
Loading