feat: implement automated Docker deployment and update README
- Replaced manual rsync/npm_deploy workflow with multi-stage Docker builds. - Added Dockerfile and .dockerignore for staging and production environments. - Added 'deploy:staging' and 'deploy:prod' scripts to package.json. - Updated README.md with new deployment instructions.
This commit is contained in:
12
.dockerignore
Normal file
12
.dockerignore
Normal file
@@ -0,0 +1,12 @@
|
||||
node_modules
|
||||
build
|
||||
.svelte-kit
|
||||
.git
|
||||
.env
|
||||
.env.*
|
||||
!.env.staging
|
||||
!.env.prod
|
||||
npm_deploy
|
||||
test-results
|
||||
test_results
|
||||
documentation
|
||||
46
Dockerfile
Normal file
46
Dockerfile
Normal file
@@ -0,0 +1,46 @@
|
||||
# Stage 1: Build the application
|
||||
# Using node:21-alpine for a lightweight, secure build environment.
|
||||
FROM node:21-alpine AS builder
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies first for better Docker layer caching.
|
||||
# This step only reruns if package.json or package-lock.json changes.
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
|
||||
# Copy the rest of the source code.
|
||||
COPY . .
|
||||
|
||||
# Build Argument to determine build environment (staging, prod, or production).
|
||||
# Defaults to "staging".
|
||||
ARG BUILD_MODE=staging
|
||||
ENV NODE_ENV=production
|
||||
|
||||
# Perform the build based on the BUILD_MODE argument.
|
||||
# This runs the existing scripts in package.json, which already
|
||||
# handle copying the correct .env file to .env.production for Vite.
|
||||
RUN if [ "$BUILD_MODE" = "prod" ] || [ "$BUILD_MODE" = "production" ]; then \
|
||||
npm run build:prod; \
|
||||
else \
|
||||
npm run build:staging; \
|
||||
fi
|
||||
|
||||
# Stage 2: Final runtime image
|
||||
FROM node:21-alpine AS deploy-node
|
||||
WORKDIR /app
|
||||
|
||||
# Copy only the built files and necessary scripts from the builder stage.
|
||||
COPY --from=builder /app/build .
|
||||
COPY --from=builder /app/package.json .
|
||||
|
||||
# Install only production dependencies for a smaller, cleaner image.
|
||||
RUN npm install --omit=dev
|
||||
|
||||
# Copy the resulting .env.production file to .env.
|
||||
# adapter-node reads from .env at runtime for non-PUBLIC_ variables.
|
||||
COPY --from=builder /app/.env.production .env
|
||||
|
||||
# SvelteKit (via adapter-node) defaults to port 3000.
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["node", "index.js"]
|
||||
40
README.md
40
README.md
@@ -123,36 +123,34 @@ Developer sandbox pages — not for production use.
|
||||
|
||||
# How to build and deploy SvelteKit:
|
||||
|
||||
Copy the contents of the "build" directory to ./npm_deploy/build/
|
||||
The deployment is now fully automated using Docker Compose. The application is built directly from source inside a clean Docker environment, eliminating the need for manual `rsync` or `npm_deploy` management.
|
||||
|
||||
### Commands
|
||||
|
||||
Run these commands from the root of the `aether_app_sveltekit` project:
|
||||
|
||||
#### 1. Deploy to Staging (Dev)
|
||||
This builds and restarts the staging containers (`ae_app_node_dev`, etc.) on your local workstation.
|
||||
```bash
|
||||
npm run build
|
||||
npm run deploy:staging
|
||||
```
|
||||
|
||||
If this is just a quick build update then only the build directory needs to be copied (rsync).
|
||||
|
||||
#### 2. Deploy to Production
|
||||
This builds the image using production flags and restarts the production containers.
|
||||
```bash
|
||||
rsync -vhrz --exclude 'node_modules' ~/OSIT_dev/aether_app_sveltekit/build/ ~/OSIT_dev/ae_env_node_app/npm_deploy/build/ --delete
|
||||
|
||||
rsync -vhrz ~/OSIT_dev/ae_env_node_app/npm_deploy/build/ scott@linode.oneskyit.com:/srv/env/prod_aether_sveltekit/npm_deploy/build/ --delete
|
||||
npm run deploy:prod
|
||||
```
|
||||
|
||||
If this includes package updates (not development) we need to copy the new package.json. Manually copy the new package.json file to ./npm_deploy/. This also needs to be copied to the server. Copy the package.json even though not really used.
|
||||
### Technical Details
|
||||
|
||||
Run the --omit dev to clear out the node_modules directory. Copy the root node_modules directory to ./npm_deploy/build/node_modules/ after running te omit dev command.
|
||||
- **Dockerfile**: Uses a multi-stage build. Stage 1 (builder) installs dependencies and builds the app using the `BUILD_MODE` argument. Stage 2 (runtime) creates the final lightweight image.
|
||||
- **Environment Handling**:
|
||||
- `PUBLIC_` variables are baked into the image during the build step based on `.env.staging` or `.env.prod`.
|
||||
- Private runtime variables are passed via the `env_file` in `docker-compose.yml`.
|
||||
- **Networking**: Containers are automatically joined to the `ae_dev_net` network to allow local Nginx proxying.
|
||||
- **Legacy Migration**: The `upstream` in the local Nginx configuration has been updated to point to these new SvelteKit containers on port 3000.
|
||||
|
||||
```bash
|
||||
npm ci --omit dev
|
||||
|
||||
# copy/paste, rsync, or cp
|
||||
rsync -vhrz ~/OSIT_dev/aether_app_sveltekit/node_modules ~/OSIT_dev/ae_env_node_app/npm_deploy/build/ --delete
|
||||
|
||||
# copy package.json as well
|
||||
|
||||
npm install
|
||||
```
|
||||
|
||||
Everything should be ready to run on the development server and production server.
|
||||
---
|
||||
|
||||
# Rebuild the node_modules directory and manually install extra Svelte packages
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
"lint": "prettier --check . && eslint .",
|
||||
"format": "prettier --write .",
|
||||
"test:integration": "playwright test",
|
||||
"test:unit": "vitest"
|
||||
"test:unit": "vitest",
|
||||
"deploy:staging": "docker compose -f ../ae_env_node_app/docker-compose.yml up -d --build --remove-orphans",
|
||||
"deploy:prod": "docker compose -f ../ae_env_node_app/docker-compose.yml build --build-arg BUILD_MODE=prod && docker compose -f ../ae_env_node_app/docker-compose.yml up -d --remove-orphans"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.1",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
// *** Libraries & Stores
|
||||
import { liveQuery } from 'dexie';
|
||||
import { Modal } from 'flowbite-svelte';
|
||||
import { db_core } from '$lib/ae_core/db_core';
|
||||
import { db_journals } from '$lib/ae_journals/db_journals';
|
||||
import { journals_func } from '$lib/ae_journals/ae_journals_functions';
|
||||
import { ae_loc, ae_api, slct } from '$lib/stores/ae_stores';
|
||||
@@ -47,6 +48,13 @@
|
||||
let log_lvl = 0;
|
||||
|
||||
// *** LiveQueries
|
||||
let lq__account = $derived(
|
||||
liveQuery(async () => {
|
||||
if (!$slct.account_id) return null;
|
||||
return await db_core.account.get($slct.account_id);
|
||||
})
|
||||
);
|
||||
|
||||
let lq__journal_obj_li = $derived(
|
||||
liveQuery(async () => {
|
||||
return await db_journals.journal
|
||||
@@ -105,7 +113,7 @@
|
||||
</h1>
|
||||
<p class="text-surface-600 dark:text-surface-400 font-medium">
|
||||
Managed by <span class="text-primary-500"
|
||||
>{$ae_loc.account_name ?? 'Æ loading...'}</span
|
||||
>{$lq__account?.name ?? $ae_loc.account_name ?? 'Æ loading...'}</span
|
||||
>
|
||||
{#if $ae_loc.person.given_name}
|
||||
• <span class="opacity-75"
|
||||
|
||||
Reference in New Issue
Block a user