feat: fullstack dockerization
This commit is contained in:
parent
094a16a768
commit
b19520eb6e
@ -17,5 +17,4 @@ FRONTEND_URL=""
|
|||||||
|
|
||||||
# Frontend
|
# Frontend
|
||||||
VITE_VIEW_COOKIE_PATH="/"
|
VITE_VIEW_COOKIE_PATH="/"
|
||||||
VITE_VIEW_COOKIE_DOMAIN=$DOMAIN
|
|
||||||
VITE_COKOIE_SAME_SITE="strict"
|
VITE_COKOIE_SAME_SITE="strict"
|
||||||
|
@ -40,7 +40,7 @@ services:
|
|||||||
LOG_LEVEL: debug
|
LOG_LEVEL: debug
|
||||||
APP_ENV: development
|
APP_ENV: development
|
||||||
DOMAIN: localhost
|
DOMAIN: localhost
|
||||||
FRONTEND_URL: http://localhost
|
FRONTEND_URL: http://localhost:5173
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
notatest:
|
notatest:
|
||||||
|
@ -38,18 +38,25 @@ services:
|
|||||||
LOG_LEVEL: ${LOG_LEVEL:-info}
|
LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||||
APP_ENV: ${APP_ENV:-production}
|
APP_ENV: ${APP_ENV:-production}
|
||||||
DOMAIN: ${DOMAIN:-localhost}
|
DOMAIN: ${DOMAIN:-localhost}
|
||||||
FRONTEND_URL: ${FRONTEND_URL:-http://localhost:5173}
|
FRONTEND_URL: ${FRONTEND_URL:-http://localhost:3000}
|
||||||
|
|
||||||
notatest-web:
|
notatest-web:
|
||||||
build: ${PWD}/web
|
|
||||||
image: notatest/web
|
|
||||||
container_name: notatest-web
|
container_name: notatest-web
|
||||||
|
build:
|
||||||
|
context: ${PWD}/web
|
||||||
|
dockerfile: ${PWD}/web/Dockerfile
|
||||||
|
image: notatest-web:latest
|
||||||
networks:
|
networks:
|
||||||
- notatest
|
- notatest
|
||||||
|
# Add potential reverse proxy's local network here
|
||||||
ports:
|
ports:
|
||||||
- 3000:80 # Defined in nginx.conf
|
- 3000:80 # Container port defined in nginx.conf (bound to 3000 for dev.)
|
||||||
depends_on:
|
depends_on:
|
||||||
- notatest-server
|
- notatest-server
|
||||||
|
environment:
|
||||||
|
VITE_VIEW_COOKIE_PATH: ${VITE_VIEW_COOKIE_PATH:-/}
|
||||||
|
VITE_VIEW_COOKIE_DOMAIN: ${DOMAIN:-localhost}
|
||||||
|
VITE_COOKIE_SAME_SITE: ${VITE_COOKIE_SAME_SITE:-strict}
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
notatest:
|
notatest:
|
||||||
|
10
scripts/run_full_dev.sh
Executable file
10
scripts/run_full_dev.sh
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
DEV_COMPOSE_FILE="docker-compose.yml"
|
||||||
|
|
||||||
|
[ "$( docker container inspect -f '{{.State.Status}}' notatest-psql )" = "running" ] || docker compose up notatest-psql -d
|
||||||
|
|
||||||
|
# Shutdown, rebuild, & restart
|
||||||
|
docker compose stop notatest-server notatest-web && docker compose rm -f notatest-server notatest-web
|
||||||
|
docker compose -f $DEV_COMPOSE_FILE build
|
||||||
|
docker compose -f $DEV_COMPOSE_FILE up notatest-server notatest-web
|
19
web/Dockerfile
Normal file
19
web/Dockerfile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Build stage
|
||||||
|
FROM node:23.11-alpine3.20 AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Final stage (optimized image size + NGINX)
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /app/build /usr/share/nginx/html
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
@ -1,15 +1,48 @@
|
|||||||
server {
|
server {
|
||||||
listen 80; # TLS termination is handled by Traefik
|
listen 80;
|
||||||
|
|
||||||
location / {
|
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
|
# TLS termination should be handled by a reverse proxy (e.g. Traefik)
|
||||||
|
|
||||||
|
# General security headers
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||||
|
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
|
||||||
|
|
||||||
|
# Block access to dotfiles
|
||||||
|
location ~ /\.(?!well-known) {
|
||||||
|
deny all;
|
||||||
|
access_log off;
|
||||||
|
log_not_found off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Enable gzip compression for all assets
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_proxied any;
|
||||||
|
gzip_comp_level 6;
|
||||||
|
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;
|
||||||
|
|
||||||
location /api {
|
location /api {
|
||||||
proxy_pass http://notatest-server:8080; # Internal Docker DNS
|
proxy_pass http://notatest-server:8080; # Internal Docker DNS
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
|
||||||
|
# Cache static assets
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
expires 7d;
|
||||||
|
add_header Cache-Control "public, no-transform";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Route 404 errors to front page
|
||||||
|
error_page 404 /;
|
||||||
|
}
|
11
web/package-lock.json
generated
11
web/package-lock.json
generated
@ -12,6 +12,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-auto": "^4.0.0",
|
"@sveltejs/adapter-auto": "^4.0.0",
|
||||||
|
"@sveltejs/adapter-static": "^3.0.8",
|
||||||
"@sveltejs/kit": "^2.16.0",
|
"@sveltejs/kit": "^2.16.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||||
"@tailwindcss/forms": "^0.5.9",
|
"@tailwindcss/forms": "^0.5.9",
|
||||||
@ -830,6 +831,16 @@
|
|||||||
"@sveltejs/kit": "^2.0.0"
|
"@sveltejs/kit": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@sveltejs/adapter-static": {
|
||||||
|
"version": "3.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.8.tgz",
|
||||||
|
"integrity": "sha512-YaDrquRpZwfcXbnlDsSrBQNCChVOT9MGuSg+dMAyfsAa1SmiAhrA5jUYUiIMC59G92kIbY/AaQOWcBdq+lh+zg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@sveltejs/kit": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@sveltejs/kit": {
|
"node_modules/@sveltejs/kit": {
|
||||||
"version": "2.20.7",
|
"version": "2.20.7",
|
||||||
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.20.7.tgz",
|
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.20.7.tgz",
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-auto": "^4.0.0",
|
"@sveltejs/adapter-auto": "^4.0.0",
|
||||||
|
"@sveltejs/adapter-static": "^3.0.8",
|
||||||
"@sveltejs/kit": "^2.16.0",
|
"@sveltejs/kit": "^2.16.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||||
"@tailwindcss/forms": "^0.5.9",
|
"@tailwindcss/forms": "^0.5.9",
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// TODO: this can be set to always be "/api" after Dockerization as the backend requests
|
// export const API_BASE_ADDR = import.meta.env.PROD ? "/api" : "http://localhost:8080/api"
|
||||||
// will automatically be proxied to the correct destination
|
export const API_BASE_ADDR = "/api"
|
||||||
export const API_BASE_ADDR = import.meta.env.PROD ? "/api" : "http://localhost:8080/api"
|
|
||||||
|
|
||||||
// Lifetimes of *in-memory* authentication tokens in milliseconds
|
// Lifetimes of *in-memory* authentication tokens in milliseconds
|
||||||
export const AT_EXP_MS = 15 * 60 * 1000 // 15 min.
|
export const AT_EXP_MS = 15 * 60 * 1000 // 15 min.
|
||||||
|
2
web/src/routes/+layout.server.ts
Normal file
2
web/src/routes/+layout.server.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export const ssr = false
|
||||||
|
export const prerender = false
|
@ -1,18 +1,21 @@
|
|||||||
import adapter from '@sveltejs/adapter-auto';
|
import adapter from "@sveltejs/adapter-static"
|
||||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"
|
||||||
|
|
||||||
/** @type {import('@sveltejs/kit').Config} */
|
/** @type {import('@sveltejs/kit').Config} */
|
||||||
const config = {
|
const config = {
|
||||||
// Consult https://svelte.dev/docs/kit/integrations
|
|
||||||
// for more information about preprocessors
|
|
||||||
preprocess: vitePreprocess(),
|
preprocess: vitePreprocess(),
|
||||||
|
|
||||||
kit: {
|
kit: {
|
||||||
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
|
adapter: adapter({
|
||||||
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
|
pages: "build",
|
||||||
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
|
assets: "build",
|
||||||
adapter: adapter()
|
fallback: "index.html",
|
||||||
|
precompress: false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ssr: false,
|
||||||
|
prerender: {
|
||||||
|
entries: []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export default config;
|
export default config
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import tailwindcss from "@tailwindcss/vite"
|
|
||||||
import { sveltekit } from "@sveltejs/kit/vite"
|
import { sveltekit } from "@sveltejs/kit/vite"
|
||||||
|
import tailwindcss from "@tailwindcss/vite"
|
||||||
import { defineConfig } from "vite"
|
import { defineConfig } from "vite"
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
Loading…
x
Reference in New Issue
Block a user