diff --git a/.dockerignore b/.dockerignore index df2f64d..e147338 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,7 +1,18 @@ -node_modules -dist -build -.git -.env -docker-compose.yml -Dockerfile \ No newline at end of file +# Ignore all files + +* + +# Whitelist necessary build and config files from project root +!eslint.config.js +!index.html +!package-lock.json +!package.json +!tsconfig.app.json +!tsconfig.json +!tsconfig.node.json +!vite.config.ts +!nginx.conf + +# Whitelist source and public directories +!public/ +!src/ \ No newline at end of file diff --git a/.github/workflows/image-publish.yml b/.github/workflows/image-publish.yml new file mode 100644 index 0000000..3136378 --- /dev/null +++ b/.github/workflows/image-publish.yml @@ -0,0 +1,15 @@ +name: Build and Push Docker Image to GHCR + +# Run this workflow every time code is pushed or merged to the main branch +on: + push: + branches: + - main + +jobs: + call-build-and-push: + uses: project-carpi/.github/.github/workflows/image-publish.yml@main + permissions: + contents: read + packages: write + secrets: inherit diff --git a/Dockerfile b/Dockerfile index c993a69..a89bb0c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,33 @@ -FROM node:24.14.0-alpine - -WORKDIR /app -COPY package*.json ./ +# --- BASE STAGE --- +FROM node:24.14.0-alpine AS base +# Update npm to 11.12.x to comply with project's package-lock.json +RUN npm install -g npm@11.12.0 +# Store all application files in /site +WORKDIR /site +# Copy package.json and package-lock.json to the container +COPY package*.json . +# Install dependencies using npm ci for a clean install RUN npm ci +# Copy the rest of the application code to the container COPY . . -EXPOSE 5173 +# --- DEVELOPMENT STAGE --- +FROM base AS dev +EXPOSE 5173 +# Start the development server CMD ["npm", "run", "dev"] + +# --- BUILD STAGE --- +FROM base AS build +# Build the application for production +RUN npm run build + +# --- PRODUCTION STAGE --- +# Start from a clean NGINX image for production +FROM nginx:alpine AS prod +# Copy custom NGINX configuration to serve the built application +COPY nginx.conf /etc/nginx/conf.d/default.conf +# Copy the built application from the build stage +COPY --from=build /site/dist /usr/share/nginx/html +EXPOSE 80 +# NGINX starts automatically when the container runs diff --git a/docker-compose.yml b/docker-compose.yml index 5838df7..98d9b1b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,17 +1,40 @@ -services: - web: - build: . - image: carpi-dev:latest +# Docker Compose configuration for the CARPI website development environment. +# +# To start the development environment, run: +# docker compose run --rm --service-ports site +# +# This will build the Docker image for the site service if it doesn't already +# exist, and then start the container. An interactive terminal will be attached +# to the container so Vite commands can be entered. +# +# To stop the development environment, use Q+Enter in the terminal. The +# container will automatically be removed after it stops due to the --rm flag. +# +# Alternatively, you can run the container in detached (background) mode with: +# docker compose up -d +# +# To stop the detached container, run: +# docker compose down - # expose port 5173 - ports: - - "5173:5173" - - # mount the current directory to /app in the container - volumes: - - .:/app - - /app/node_modules +name: carpi-site-dev-environment - # interactive terminal +services: + site: + build: + context: . + target: dev + image: carpi-site:latest + container_name: carpi-site + # Ensure image is built locally and is not pulled from a registry + pull_policy: build + restart: on-failure + # Enable interactive mode to allow Vite command input and output stdin_open: true tty: true + ports: + - "5173:5173" + # Mount local code over the code built into the container for automatic + # reloading during development. + volumes: + - .:/site + - /site/node_modules diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..694aa12 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,11 @@ +server { + listen 80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + # Fallback to index.html if the path isn't a real file + try_files $uri $uri/ /index.html; + } +} \ No newline at end of file