fix(deploy): close container final review
This commit is contained in:
@@ -36,3 +36,17 @@ The small input file pins the harness's PEP 517 build backend as well; it is not
|
||||
host environment. The image installs the resulting lock with pip's `--require-hashes`, then
|
||||
installs the local `tht` project with `--no-deps --no-build-isolation`. This prevents both project
|
||||
metadata and an isolated build environment from resolving unpinned packages.
|
||||
|
||||
## Base images
|
||||
|
||||
Every `FROM` uses an exact tag plus a multi-platform manifest-list digest. To update one:
|
||||
|
||||
1. Choose an exact patch tag that publishes both `linux/amd64` and `linux/arm64`.
|
||||
2. Inspect it with `docker buildx imagetools inspect <tag>`.
|
||||
3. Replace both the human-readable tag and `@sha256:...` digest.
|
||||
4. Run `./scripts/verify-container-images.sh` and the Compose smoke.
|
||||
5. Review the generated inventory under `.artifacts/container-images/`.
|
||||
|
||||
The digest freezes image layers, but `apt-get update` and `apk add` still consume mutable package
|
||||
repositories during a no-cache rebuild. Full OS-package immutability would require Debian/Alpine
|
||||
snapshot repositories and is not claimed by this deployment.
|
||||
|
||||
@@ -1,6 +1,24 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
load_secret() {
|
||||
value_name=$1
|
||||
file_name=$2
|
||||
secret_file=$(printenv "$file_name" 2>/dev/null || true)
|
||||
if [ -n "$secret_file" ]; then
|
||||
if [ ! -r "$secret_file" ]; then
|
||||
echo "$file_name is not readable: $secret_file" >&2
|
||||
exit 2
|
||||
fi
|
||||
secret_value=$(cat "$secret_file")
|
||||
export "$value_name=$secret_value"
|
||||
fi
|
||||
}
|
||||
|
||||
load_secret THT_DWH_API_KEY THT_DWH_API_KEY_FILE
|
||||
load_secret THT_VEC_API_KEY THT_VEC_API_KEY_FILE
|
||||
load_secret THT_VEC_WRITE_API_KEY THT_VEC_WRITE_API_KEY_FILE
|
||||
|
||||
case "${1:-server}" in
|
||||
server)
|
||||
shift || true
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM node:22.19.0-bookworm-slim AS node-runtime
|
||||
FROM node:22.19.0-bookworm-slim@sha256:4a4884e8a44826194dff92ba316264f392056cbe243dcc9fd3551e71cea02b90 AS node-runtime
|
||||
WORKDIR /opt/pi-runtime
|
||||
COPY docker/pi-runtime/package.json docker/pi-runtime/package-lock.json ./
|
||||
RUN npm ci --omit=dev --ignore-scripts --no-audit --no-fund \
|
||||
&& ./node_modules/.bin/pi --version
|
||||
|
||||
FROM node:22.19.0-bookworm-slim AS backend-build
|
||||
FROM node:22.19.0-bookworm-slim@sha256:4a4884e8a44826194dff92ba316264f392056cbe243dcc9fd3551e71cea02b90 AS backend-build
|
||||
WORKDIR /src/backend
|
||||
COPY backend/package.json backend/package-lock.json ./
|
||||
RUN npm ci --no-audit --no-fund
|
||||
@@ -13,12 +13,12 @@ COPY backend/ ./
|
||||
RUN npm run build \
|
||||
&& npm prune --omit=dev
|
||||
|
||||
FROM node:22.19.0-bookworm-slim AS gate-deps
|
||||
FROM node:22.19.0-bookworm-slim@sha256:4a4884e8a44826194dff92ba316264f392056cbe243dcc9fd3551e71cea02b90 AS gate-deps
|
||||
WORKDIR /src/harness
|
||||
COPY harness/package.json harness/package-lock.json ./
|
||||
RUN npm ci --no-audit --no-fund
|
||||
|
||||
FROM python:3.12-slim-bookworm AS runtime
|
||||
FROM python:3.12.11-slim-bookworm@sha256:519591d6871b7bc437060736b9f7456b8731f1499a57e22e6c285135ae657bf7 AS runtime
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install --yes --no-install-recommends ca-certificates curl \
|
||||
|
||||
@@ -1,7 +1,20 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
backend_base_url=${BACKEND_BASE_URL:-/api}
|
||||
backend_base_url=${BACKEND_BASE_URL-/api}
|
||||
case "$backend_base_url" in
|
||||
""|/|/api|/api/) ;;
|
||||
http://*|https://*)
|
||||
if printf '%s' "$backend_base_url" | grep -Eq '[[:space:]]|^https?://[^/]*@'; then
|
||||
echo "Invalid BACKEND_BASE_URL: credentials and whitespace are not allowed" >&2
|
||||
exit 2
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Invalid BACKEND_BASE_URL: use empty/root, /api, or an absolute http(s) URL" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
runtime_config=$(jq -cn --arg backend_base_url "$backend_base_url" \
|
||||
'{backendBaseUrl: $backend_base_url}')
|
||||
printf 'window.__THOTHII_CONFIG__ = %s;\n' "$runtime_config" \
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM node:22.19.0-bookworm-slim AS build
|
||||
FROM node:22.19.0-bookworm-slim@sha256:4a4884e8a44826194dff92ba316264f392056cbe243dcc9fd3551e71cea02b90 AS build
|
||||
WORKDIR /src/frontend
|
||||
COPY frontend/package.json frontend/package-lock.json ./
|
||||
RUN npm ci --no-audit --no-fund
|
||||
COPY frontend/ ./
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:1.27-alpine
|
||||
FROM nginxinc/nginx-unprivileged:1.27.5-alpine@sha256:65e3e85dbaed8ba248841d9d58a899b6197106c23cb0ff1a132b7bfe0547e4c0
|
||||
USER root
|
||||
RUN apk add --no-cache jq
|
||||
COPY --from=build /src/frontend/dist /usr/share/nginx/html
|
||||
|
||||
@@ -8,6 +8,13 @@ server {
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location = /health {
|
||||
proxy_pass http://core:8787/health;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache off;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://core:8787/;
|
||||
proxy_http_version 1.1;
|
||||
@@ -15,6 +22,9 @@ server {
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
# Trusted only when AUTH_MODE=upstream and this frontend port is reachable solely
|
||||
# from the authenticated host proxy documented in deploy/.
|
||||
proxy_set_header X-Authenticated-User $http_x_authenticated_user;
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
proxy_read_timeout 1h;
|
||||
|
||||
@@ -7,7 +7,7 @@ assignment=$(sed \
|
||||
/usr/share/nginx/html/config.js)
|
||||
|
||||
printf '%s\n' "$assignment" \
|
||||
| jq -e --arg expected "${BACKEND_BASE_URL:-/api}" \
|
||||
| jq -e --arg expected "${BACKEND_BASE_URL-/api}" \
|
||||
'type == "object" and keys == ["backendBaseUrl"] and .backendBaseUrl == $expected' \
|
||||
>/dev/null
|
||||
|
||||
|
||||
Reference in New Issue
Block a user