Skip to content

Commit a379cff

Browse files
committed
Add site Docker build (nginx) and .htaccess for Apache hosting
- site/Dockerfile: multi-stage build (node:24-slim → nginx:alpine) - site/nginx.conf: trailing slash removal, .html fallback, SPA fallback - site/static/.htaccess: same logic for Apache hosting - .github/workflows/site-docker.yml: build+push to ghcr.io on tags
1 parent a7fde56 commit a379cff

5 files changed

Lines changed: 119 additions & 0 deletions

File tree

.github/workflows/site-docker.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Build and Push Site Docker Image
2+
3+
on:
4+
push:
5+
tags: ['v*']
6+
paths:
7+
- 'site/**'
8+
workflow_dispatch:
9+
10+
env:
11+
REGISTRY: ghcr.io
12+
IMAGE_NAME: graph-memory/graphmemory-site
13+
14+
jobs:
15+
build-and-push:
16+
runs-on: ubuntu-latest
17+
permissions:
18+
contents: read
19+
packages: write
20+
21+
steps:
22+
- uses: actions/checkout@v6
23+
24+
- name: Log in to Container Registry
25+
uses: docker/login-action@v4
26+
with:
27+
registry: ${{ env.REGISTRY }}
28+
username: ${{ github.actor }}
29+
password: ${{ secrets.GITHUB_TOKEN }}
30+
31+
- name: Set up QEMU
32+
uses: docker/setup-qemu-action@v4
33+
34+
- name: Set up Docker Buildx
35+
uses: docker/setup-buildx-action@v4
36+
37+
- name: Extract metadata
38+
id: meta
39+
uses: docker/metadata-action@v6
40+
with:
41+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
42+
tags: |
43+
type=raw,value=latest
44+
type=sha,prefix=
45+
type=semver,pattern={{version}}
46+
type=semver,pattern={{major}}.{{minor}}
47+
type=semver,pattern={{major}}
48+
49+
- name: Build and push
50+
uses: docker/build-push-action@v7
51+
with:
52+
context: ./site
53+
platforms: linux/amd64,linux/arm64
54+
push: true
55+
tags: ${{ steps.meta.outputs.tags }}
56+
labels: ${{ steps.meta.outputs.labels }}

site/.dockerignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
build
3+
.docusaurus

site/Dockerfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM node:24-slim AS build
2+
3+
WORKDIR /app
4+
COPY package.json package-lock.json ./
5+
RUN npm ci
6+
COPY . .
7+
RUN npm run build
8+
9+
FROM nginx:alpine
10+
COPY --from=build /app/build /usr/share/nginx/html
11+
COPY nginx.conf /etc/nginx/conf.d/default.conf
12+
13+
EXPOSE 80

site/nginx.conf

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
server {
2+
listen 80;
3+
server_name _;
4+
root /usr/share/nginx/html;
5+
index index.html;
6+
7+
# Remove trailing slash (Docusaurus trailingSlash: false)
8+
rewrite ^(.+)/$ $1 permanent;
9+
10+
location / {
11+
try_files $uri $uri.html $uri/index.html /index.html;
12+
}
13+
14+
location /assets/ {
15+
expires 1y;
16+
add_header Cache-Control "public, immutable";
17+
}
18+
19+
location /img/ {
20+
expires 1y;
21+
add_header Cache-Control "public, immutable";
22+
}
23+
}

site/static/.htaccess

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
DirectoryIndex index.html
2+
3+
RewriteEngine On
4+
5+
# Remove trailing slash
6+
RewriteCond %{REQUEST_FILENAME} !-d
7+
RewriteRule ^(.+)/$ /$1 [R=301,L]
8+
9+
# If directory with trailing slash — try serving dir/index.html or redirect to without slash
10+
RewriteCond %{REQUEST_FILENAME} -d
11+
RewriteCond %{REQUEST_URI} ^(.+)/$
12+
RewriteCond %{DOCUMENT_ROOT}/$1.html -f
13+
RewriteRule ^(.+)/$ /$1 [R=301,L]
14+
15+
# Serve .html extension for clean URLs
16+
RewriteCond %{REQUEST_FILENAME} !-f
17+
RewriteCond %{REQUEST_FILENAME} !-d
18+
RewriteCond %{REQUEST_FILENAME}.html -f
19+
RewriteRule ^ %{REQUEST_URI}.html [L]
20+
21+
# SPA fallback
22+
RewriteCond %{REQUEST_FILENAME} !-f
23+
RewriteCond %{REQUEST_FILENAME} !-d
24+
RewriteRule ^ /index.html [L]

0 commit comments

Comments
 (0)