Deploy skeleton-app
Build and Deploy / build-and-push (push) Successful in 59s Details

This commit is contained in:
ImNotTheGuy 2026-04-21 14:57:53 +02:00
parent 083982814f
commit 6b31b6e68f
6 changed files with 55 additions and 32 deletions

View File

@ -18,7 +18,7 @@ jobs:
username: ${{ gitea.actor }} username: ${{ gitea.actor }}
password: ${{ secrets.CI_TOKEN }} password: ${{ secrets.CI_TOKEN }}
- name: Build and Pushz - name: Build and Push
uses: docker/build-push-action@v4 uses: docker/build-push-action@v4
with: with:
context: . context: .
@ -28,5 +28,6 @@ jobs:
- name: Deploy to Server - name: Deploy to Server
run: | run: |
# Here we tell the server to pull the new image and restart # Here we tell the server to pull the new image and restart
echo "${{ secrets.CI_TOKEN }}" | docker login git.ludops.com -u ${{ gitea.actor }} --password-stdin
docker compose -f docker-compose.prod.yml pull docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d docker compose -f docker-compose.prod.yml up -d

1
.npmrc Normal file
View File

@ -0,0 +1 @@
inject-workspace-packages=true

View File

@ -1,36 +1,37 @@
# --- STAGE 1: Base & Dependencies --- # --- STAGE 1: Base ---
FROM node:20-alpine AS base FROM node:24-alpine AS base
ENV PNPM_HOME="/pnpm" ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH" ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable RUN corepack enable
WORKDIR /app WORKDIR /app
# Copy lockfiles and workspace configs # --- STAGE 2: Build everything ---
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json turbo.json ./
# Copy all package.jsons to allow pnpm to link workspaces
COPY apps/api/package.json ./apps/api/
COPY apps/web/package.json ./apps/web/
COPY packages/shared/package.json ./packages/shared/
RUN pnpm install --frozen-lockfile
# --- STAGE 2: Build ---
FROM base AS build FROM base AS build
COPY . . COPY . .
# This runs 'turbo run build' which should create 'dist' in both apps RUN pnpm install --frozen-lockfile
RUN pnpm turbo run build RUN pnpm turbo run build
# --- STAGE 3: Runner (The tiny production image) --- # --- STAGE 3: Extract for Production ---
FROM node:20-alpine AS runner # This "flattens" the api and its node_modules into a standalone folder
RUN pnpm deploy --filter=api --prod /prod/api
# --- STAGE 4: Runner ---
FROM node:24-alpine AS runner
WORKDIR /app WORKDIR /app
# IMPORTANT: We copy from 'build' stage, not 'base' # Copy the standalone API (includes its own local node_modules)
# We check if the folders exist before copying to avoid the error you saw COPY --from=build /prod/api .
COPY --from=build /app/apps/api/dist ./api
# Copy the web dist into the location the API expects
# Based on your code, it looks for ../web-dist or ./web-dist
COPY --from=build /app/apps/web/dist ./web-dist COPY --from=build /app/apps/web/dist ./web-dist
COPY --from=build /app/node_modules ./node_modules
# We need the shared package if the API imports it directly as source
# But pnpm deploy usually handles the shared package if it's built
COPY --from=build /app/packages/shared ./packages/shared COPY --from=build /app/packages/shared ./packages/shared
EXPOSE 3000 EXPOSE 3000
# Update this path to wherever your compiled Fastify entry point is ENV NODE_ENV=production
CMD ["node", "api/src/index.ts"]
# Since we are now inside the "api" folder essentially:
CMD ["node", "dist/index.js"]

View File

@ -16,7 +16,7 @@ fastify.get('/api/status', async (): Promise<AppStatus> => {
// Serve Frontend (Vite Dist) // Serve Frontend (Vite Dist)
const webDistPath = process.env.NODE_ENV === 'production' const webDistPath = process.env.NODE_ENV === 'production'
? path.join(__dirname, '../web-dist') ? path.join(__dirname, 'web-dist') // Adjusted for the flattened Docker structure
: path.join(__dirname, '../../web/dist'); : path.join(__dirname, '../../web/dist');
fastify.register(fastifyStatic, { fastify.register(fastifyStatic, {

19
docker-compose.prod.yml Normal file
View File

@ -0,0 +1,19 @@
services:
skeleton-app:
image: git.ludops.com/ludops/ludops-skeleton:latest
container_name: ludops-skeleton-app
restart: always
environment:
- NODE_ENV=production
- PORT=3000
# We point to the shared DB we set up earlier
- DATABASE_URL=postgres://gitea:gitea@ludops-postgres:5432/skeleton_db
networks:
- proxy-tier # For NPM to find us
- infrastructure_infra-network # For us to find the Postgres DB
networks:
proxy-tier:
external: true
infrastructure_infra-network:
external: true

View File

@ -3,6 +3,7 @@ lockfileVersion: '9.0'
settings: settings:
autoInstallPeers: true autoInstallPeers: true
excludeLinksFromLockfile: false excludeLinksFromLockfile: false
injectWorkspacePackages: true
importers: importers: