Skip to content

Commit fdf4005

Browse files
authored
Merge pull request #1 from DFMoller/docker
Dockerise the application, add github actions
2 parents bfb4411 + c265826 commit fdf4005

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+855
-79
lines changed

.devcontainer/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ RUN apt-get update && apt-get -y upgrade && apt-get -qqy install \
2525
gnupg2 \
2626
tzdata
2727

28-
# Install claude code.
28+
# Install claude code globally.
2929
RUN sudo npm install -g @anthropic-ai/claude-code
3030

3131
########

.devcontainer/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ services:
66
context: .
77
dockerfile: Dockerfile
88
ports:
9-
- 80:80
9+
- 8080:80
1010
volumes:
1111
# Mounts the project folder to '/workspace'
1212
# in devcontainer.json we have specified workspaceFolder=/workspace.

.dockerignore

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Dependencies
2+
node_modules
3+
npm-debug.log*
4+
yarn-debug.log*
5+
yarn-error.log*
6+
pnpm-debug.log*
7+
8+
# Build output
9+
dist
10+
build
11+
.vite
12+
13+
# Development files
14+
.env.local
15+
.env.development.local
16+
.env.test.local
17+
.env.production.local
18+
19+
# Git
20+
.git
21+
.gitignore
22+
23+
# IDE
24+
.vscode
25+
.idea
26+
*.swp
27+
*.swo
28+
*~
29+
30+
# OS
31+
.DS_Store
32+
Thumbs.db
33+
34+
# Testing
35+
coverage
36+
.nyc_output
37+
playwright-report
38+
test-results
39+
40+
# Documentation
41+
*.md
42+
43+
# Docker
44+
Dockerfile
45+
.dockerignore
46+
docker-compose.yml
47+
48+
# Claude Code
49+
.claude
50+
51+
# Development containers
52+
.devcontainer
53+
54+
# GitHub
55+
.github
56+
57+
# Misc
58+
.prettierrc
59+
.eslintrc*

.github/workflows/default.yml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# This workflow will install Node.js dependencies, lint, and build the React application.
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
3+
4+
name: Node.js Lint + Build
5+
6+
# Run the default pipeline for any push event.
7+
on: [push]
8+
9+
env:
10+
NODE_VERSION: "20"
11+
12+
permissions:
13+
contents: read
14+
15+
jobs:
16+
version-check:
17+
if: github.ref_name != 'main'
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Checkout main branch
21+
uses: actions/checkout@v4
22+
with:
23+
ref: refs/heads/main
24+
25+
- name: Set up Node.js for main branch
26+
uses: actions/setup-node@v4
27+
with:
28+
node-version: ${{ env.NODE_VERSION }}
29+
30+
- name: Check main branch version
31+
id: check_main_branch_version
32+
run: |
33+
echo "MAIN_BRANCH_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
34+
35+
- name: Checkout current branch
36+
uses: actions/checkout@v4
37+
38+
- name: Set up Node.js for current branch
39+
uses: actions/setup-node@v4
40+
with:
41+
node-version: ${{ env.NODE_VERSION }}
42+
43+
- name: Check current branch version
44+
env:
45+
MAIN_BRANCH_VERSION: ${{ steps.check_main_branch_version.outputs.MAIN_BRANCH_VERSION }}
46+
run: |
47+
CURRENT_VERSION="$(node -p "require('./package.json').version")"
48+
CURRENT_CHANGELOG_VERSION="$(cat CHANGELOG.md | grep "^## \[" | tr -d "[]" | cut -d' ' -f2 | head -n1)"
49+
echo "Version in package.json: ($CURRENT_VERSION); Version in main branch: ($MAIN_BRANCH_VERSION)."
50+
echo "Version in CHANGELOG.md: ($CURRENT_CHANGELOG_VERSION)."
51+
if [ "$CURRENT_VERSION" == "$MAIN_BRANCH_VERSION" ]; then
52+
echo "Version in package.json matches the version in the main branch. It needs to be updated."
53+
exit 1
54+
fi
55+
if [ "$CURRENT_VERSION" != "$CURRENT_CHANGELOG_VERSION" ]; then
56+
echo "Version in package.json ($CURRENT_VERSION) does not match the version in CHANGELOG.md ($CURRENT_CHANGELOG_VERSION)."
57+
exit 1
58+
fi
59+
60+
lint-and-build:
61+
runs-on: ubuntu-latest
62+
steps:
63+
# Checkout the code.
64+
- name: Checkout repository
65+
uses: actions/checkout@v4
66+
67+
# Set up Node.js.
68+
- name: Set up Node.js
69+
uses: actions/setup-node@v4
70+
with:
71+
node-version: ${{ env.NODE_VERSION }}
72+
cache: 'npm'
73+
74+
# Install dependencies.
75+
- name: Install dependencies
76+
run: npm ci
77+
78+
# Run linter.
79+
- name: Lint with ESLint
80+
run: npm run lint
81+
82+
# Run TypeScript compilation check.
83+
- name: TypeScript compilation check
84+
run: npx tsc -b
85+
86+
# Build the application for production.
87+
- name: Build application
88+
run: npm run build
89+
90+
# Optional: Upload build artifacts for inspection.
91+
- name: Upload build artifacts
92+
uses: actions/upload-artifact@v4
93+
with:
94+
name: dist
95+
path: dist/
96+
retention-days: 7

.github/workflows/docker.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Docker Build + Push
2+
3+
# Build and push Docker images when version tags are pushed.
4+
on:
5+
push:
6+
tags:
7+
- 'v*'
8+
9+
# Environment variables for GitHub Container Registry.
10+
env:
11+
REGISTRY: ghcr.io
12+
IMAGE_NAME: ${{ github.repository }}
13+
14+
jobs:
15+
build-and-push-image:
16+
runs-on: ubuntu-latest
17+
# Permissions for pushing to GHCR and creating attestations.
18+
permissions:
19+
contents: read
20+
packages: write
21+
attestations: write
22+
id-token: write
23+
steps:
24+
- name: Checkout repository
25+
uses: actions/checkout@v4
26+
27+
# Set up Docker Buildx for multi-platform builds and layer caching.
28+
- name: Set up Docker Buildx
29+
uses: docker/setup-buildx-action@v3
30+
31+
# Log in to GitHub Container Registry.
32+
- name: Log in to the Container registry
33+
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
34+
with:
35+
registry: ${{ env.REGISTRY }}
36+
username: ${{ github.actor }}
37+
password: ${{ secrets.GITHUB_TOKEN }}
38+
39+
# Extract metadata (tags, labels) for the Docker image.
40+
- name: Extract metadata (tags, labels) for Docker
41+
id: meta
42+
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
43+
with:
44+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
45+
tags: |
46+
# Get the version from the tag (e.g., v0.1.0 -> 0.1.0).
47+
type=pep440,pattern={{version}}
48+
# Set latest tag for main branch.
49+
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
50+
type=ref,event=branch
51+
type=ref,event=pr
52+
type=sha
53+
labels: |
54+
org.opencontainers.image.title=SDC Web
55+
org.opencontainers.image.description=Supermarket Data Collector Web Application
56+
org.opencontainers.image.vendor=DFMoller
57+
org.opencontainers.image.source=https://github.com/${{ github.repository }}
58+
org.opencontainers.image.revision=${{ github.sha }}
59+
org.opencontainers.image.created=${{ github.event.head_commit.timestamp }}
60+
61+
# Build and push Docker image with multi-platform support and caching.
62+
- name: Build and push Docker image
63+
id: push
64+
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
65+
with:
66+
context: .
67+
platforms: linux/amd64,linux/arm64
68+
push: true
69+
tags: ${{ steps.meta.outputs.tags }}
70+
labels: ${{ steps.meta.outputs.labels }}
71+
# Enable layer caching to speed up builds.
72+
cache-from: type=gha
73+
cache-to: type=gha,mode=max
File renamed without changes.

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [0.1.0] - 2025-10-22
9+
10+
### Added
11+
12+
- Added `Dockerfile` to containerize the application production deployment.
13+
- Introduced `docker-compose.yml` for easy multi-container orchestration.
14+
- Implemented environment variable support for configuration settings.
15+
- Added health check endpoint for monitoring container status.
16+
- Created documentation for Docker setup and usage.
17+
- Addef GitHub Actions workflow for automated linting, Docker image building etc.
18+
- Better documentation.
19+
20+
### Changed
21+
22+
- Flatten the project structure. It was unnecessarily nested with sub-folders.
File renamed without changes.

Dockerfile

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Multi-stage Docker build for SDC Web React application.
2+
# Stage 1: Build Caddy with transform-encoder module.
3+
# Stage 2: Build the React application.
4+
# Stage 3: Serve with Caddy web server.
5+
6+
# Build arguments for version control.
7+
ARG NODE_VERSION=20
8+
ARG CADDY_VERSION=2-alpine
9+
10+
# --------------------------------------------------------------------------------
11+
# Stage 1: Caddy Builder - Build Caddy with transform-encoder module.
12+
# This module is required for transforming logs to a more readable format.
13+
# To optimise logs for machine parsing, just use the normal caddy image
14+
# with the json logger.
15+
FROM caddy:builder AS caddy-builder
16+
17+
RUN xcaddy build \
18+
--with github.com/caddyserver/transform-encoder
19+
20+
# --------------------------------------------------------------------------------
21+
# Stage 2: React Builder - Build the React app.
22+
FROM node:${NODE_VERSION}-alpine AS builder
23+
24+
WORKDIR /app
25+
26+
# Copy package files for dependency installation.
27+
COPY package*.json ./
28+
29+
# Install dependencies. Use clean install for reproducible builds.
30+
RUN npm ci
31+
32+
# Copy source code.
33+
COPY . .
34+
35+
# Build the application.
36+
RUN npm run build
37+
38+
# --------------------------------------------------------------------------------
39+
# Stage 3: Production - Serve with Caddy.
40+
FROM caddy:${CADDY_VERSION}
41+
42+
# Copy custom-built Caddy binary with transform-encoder module.
43+
COPY --from=caddy-builder /usr/bin/caddy /usr/bin/caddy
44+
45+
# Copy built static files from builder stage.
46+
COPY --from=builder /app/dist /usr/share/caddy
47+
48+
# Copy Caddyfile for server configuration.
49+
COPY configs/Caddyfile /etc/caddy/Caddyfile
50+
51+
# Extract version from package.json for labeling.
52+
COPY --from=builder /app/package.json /tmp/package.json
53+
54+
# Add labels for container metadata.
55+
LABEL org.opencontainers.image.title="SDC Web"
56+
LABEL org.opencontainers.image.description="Supermarket Data Collector Web Application"
57+
LABEL org.opencontainers.image.source="https://github.com/dfmoller/sdc-web"
58+
59+
# Expose HTTP and HTTPS ports.
60+
EXPOSE 80
61+
EXPOSE 443
62+
63+
# Health check endpoint.
64+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
65+
CMD wget --no-verbose --tries=1 --spider http://localhost:80/ || exit 1
66+
67+
# Caddy runs as non-root by default and serves from /usr/share/caddy.
68+
# No CMD needed, the base caddy image handles it.

0 commit comments

Comments
 (0)