Skip to content

Commit 85a0dd2

Browse files
Add github action to create and push image on release (#4)
* Add Dockerfile for building and serving web UI with NGINX * Add github action to create and push image on release
1 parent caf72b2 commit 85a0dd2

File tree

4 files changed

+143
-0
lines changed

4 files changed

+143
-0
lines changed

.dockerignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.dockerignore
2+
coverage
3+
node_modules
4+
dist
5+
README.md
6+
.git
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Publish Docker Image
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
env:
8+
REGISTRY: ghcr.io
9+
IMAGE_REPOSITORY: ghcr.io/DiamondLightSource/visr-ui
10+
11+
jobs:
12+
docker-build:
13+
runs-on: ubuntu-latest
14+
15+
permissions:
16+
contents: read
17+
packages: write
18+
attestations: write
19+
id-token: write
20+
21+
steps:
22+
- name: Checkout repository
23+
uses: actions/checkout@v4
24+
25+
- name: Log in to GitHub Container Registry
26+
uses: docker/login-action@v3
27+
with:
28+
registry: ${{ env.REGISTRY }}
29+
username: ${{ github.actor }}
30+
password: ${{ secrets.GITHUB_TOKEN }}
31+
32+
- name: Extract metadata (tags, labels) for Docker
33+
id: meta
34+
uses: docker/metadata-action@v5
35+
with:
36+
images: ${{ env.IMAGE_REPOSITORY }}
37+
tags: |
38+
type=semver,pattern={{version}}
39+
40+
- name: Build and push Docker image
41+
id: push
42+
uses: docker/build-push-action@v5
43+
with:
44+
context: .
45+
push: true
46+
tags: ${{ steps.meta.outputs.tags }}
47+
labels: ${{ steps.meta.outputs.labels }}
48+
49+
- name: Generate artifact attestation
50+
uses: actions/attest-build-provenance@v1
51+
with:
52+
subject-name: ${{ env.IMAGE_REPOSITORY }}
53+
subject-digest: ${{ steps.push.outputs.digest }}
54+
push-to-registry: true

Dockerfile

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
FROM node:22-alpine AS base
2+
3+
# Use a consistent working directory across all stages
4+
WORKDIR /app
5+
6+
# 1) Install dependencies
7+
FROM base AS deps
8+
9+
# If your application uses environment variables for compile-time configuration, you can use arguments
10+
# to configure them when building the image.
11+
# ARG FOO=BAR
12+
# ENV REACT_APP_FOO=${FOO}
13+
14+
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./
15+
16+
# Uncomment the next line if you're not using Classic Yarn
17+
#COPY ./.yarn ./.yarn
18+
19+
20+
# Install dependencies using the detected lockfile
21+
RUN \
22+
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
23+
elif [ -f package-lock.json ]; then npm ci; \
24+
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
25+
else echo "Lockfile not found." && exit 1; \
26+
fi
27+
28+
# 2) Run the build
29+
FROM base AS builder
30+
31+
# Copy installed dependencies
32+
COPY --from=deps /app/node_modules ./node_modules
33+
34+
# Copy all source files
35+
COPY . .
36+
37+
# Build the app using the detected package manager
38+
RUN \
39+
if [ -f yarn.lock ]; then yarn run build; \
40+
elif [ -f package-lock.json ]; then npm run build; \
41+
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \
42+
else echo "Lockfile not found." && exit 1; \
43+
fi
44+
45+
# 3) Create minimal image to serve the app
46+
FROM nginxinc/nginx-unprivileged:1.25-alpine as runner
47+
48+
# Copy built files to nginx web root
49+
COPY --from=builder /app/dist /usr/share/nginx/html
50+
51+
# Copy your custom nginx config
52+
COPY nginx.conf /etc/nginx/nginx.conf
53+
54+
EXPOSE 8080
55+
CMD ["nginx", "-g", "daemon off;"]

nginx.conf

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
worker_processes 3;
2+
pid /tmp/nginx.pid; # Changed from /var/run/nginx.pid
3+
error_log /var/log/nginx/error.log;
4+
events {
5+
worker_connections 10240;
6+
}
7+
8+
http {
9+
include mime.types;
10+
client_body_temp_path /tmp/client_temp;
11+
proxy_temp_path /tmp/proxy_temp_path;
12+
fastcgi_temp_path /tmp/fastcgi_temp;
13+
uwsgi_temp_path /tmp/uwsgi_temp;
14+
scgi_temp_path /tmp/scgi_temp;
15+
server {
16+
listen 8080;
17+
# Redirects traffic to /index.html, our main entrypoint. If you have a multi-page application, add more locations
18+
location / {
19+
root /usr/share/nginx/html;
20+
index index.html index.htm;
21+
try_files $uri $uri/ /index.html;
22+
}
23+
error_page 500 502 503 504 /50x.html;
24+
location = /50x.html {
25+
root /usr/share/nginx/html;
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)