Add container deployment: Dockerfile, compose, systemd unit, redeploy script
Multi-stage build (node -> go -> alpine) producing the static tefterd binary with the frontend embedded. Compose follows the house style for the podman/SELinux server (:Z volume label + label:disable). deploy/ holds the user systemd unit and redeploy-tefter.sh, mirroring the apelacija setup. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
10
.dockerignore
Normal file
10
.dockerignore
Normal file
@@ -0,0 +1,10 @@
|
||||
.git
|
||||
.gitea
|
||||
build
|
||||
desktop
|
||||
frontend/node_modules
|
||||
frontend/dist
|
||||
server/webdist/dist
|
||||
notes.zip
|
||||
*.md
|
||||
.env.docker
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,4 +9,5 @@ desktop/build/bin/
|
||||
*.db-wal
|
||||
*.db-shm
|
||||
notes.zip
|
||||
.env.docker
|
||||
!server/webdist/dist/.gitkeep
|
||||
|
||||
33
Dockerfile
Normal file
33
Dockerfile
Normal file
@@ -0,0 +1,33 @@
|
||||
# Build the frontend bundle (vite), then the static tefterd binary that
|
||||
# embeds it, then ship binary-only. VERSION flows in from compose
|
||||
# (${TEFTER_VERSION}) so `tefterd version` matches the git describe.
|
||||
|
||||
# Fully-qualified images (podman enforces short-name resolution non-interactively).
|
||||
FROM docker.io/library/node:22-alpine AS frontend
|
||||
WORKDIR /src/frontend
|
||||
COPY frontend/package.json frontend/package-lock.json ./
|
||||
RUN npm ci --no-audit --no-fund
|
||||
COPY frontend/ ./
|
||||
ARG VERSION=dev
|
||||
RUN TEFTER_VERSION=$VERSION npx vite build
|
||||
|
||||
FROM docker.io/library/golang:1.25-alpine AS build
|
||||
WORKDIR /src/server
|
||||
COPY server/go.mod server/go.sum ./
|
||||
RUN go mod download
|
||||
COPY server/ ./
|
||||
# go:embed cannot reach outside the module dir, so the bundle is copied in
|
||||
# (same as the Makefile does).
|
||||
COPY --from=frontend /src/frontend/dist ./webdist/dist
|
||||
ARG VERSION=dev
|
||||
RUN CGO_ENABLED=0 go build -trimpath -ldflags "-s -w -X main.Version=$VERSION" -o /tefterd .
|
||||
|
||||
FROM docker.io/library/alpine:3.22
|
||||
RUN adduser -D -H tefter && mkdir -p /data && chown tefter /data
|
||||
COPY --from=build /tefterd /usr/local/bin/tefterd
|
||||
USER tefter
|
||||
ENV TEFTER_DB=/data/tefter.db
|
||||
# The auth token is generated and printed to the logs on first start.
|
||||
EXPOSE 8420
|
||||
VOLUME /data
|
||||
CMD ["tefterd"]
|
||||
30
deploy/redeploy-tefter.sh
Executable file
30
deploy/redeploy-tefter.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
APP_DIR=$HOME/tefter
|
||||
SERVICE=tefter.service
|
||||
|
||||
cd "$APP_DIR"
|
||||
|
||||
# Port the app is published on (kept in .env.docker next to the compose file).
|
||||
WEB_PORT=$(grep -oP '^WEB_PORT=\K.*' .env.docker 2>/dev/null || echo 8420)
|
||||
|
||||
echo "==> Pulling latest code..."
|
||||
git pull
|
||||
|
||||
echo "==> Rebuilding container..."
|
||||
TEFTER_VERSION=$(git describe --tags --always --dirty) podman-compose build
|
||||
|
||||
echo "==> Restarting service..."
|
||||
systemctl --user restart $SERVICE
|
||||
|
||||
echo "==> Waiting for boot..."
|
||||
sleep 5
|
||||
|
||||
if curl -s -o /dev/null -w "" http://localhost:$WEB_PORT/; then
|
||||
echo "==> Deploy successful! App is running on port $WEB_PORT."
|
||||
podman-compose logs --tail 5 tefter 2>&1
|
||||
else
|
||||
echo "==> WARNING: App may not be ready yet. Check logs:"
|
||||
podman-compose logs --tail 20 tefter 2>&1
|
||||
fi
|
||||
20
deploy/tefter.service
Normal file
20
deploy/tefter.service
Normal file
@@ -0,0 +1,20 @@
|
||||
# User unit — install to ~/.config/systemd/user/tefter.service, then:
|
||||
# systemctl --user daemon-reload && systemctl --user enable --now tefter.service
|
||||
# Requires lingering (loginctl enable-linger) so it survives logout.
|
||||
|
||||
[Unit]
|
||||
Description=Tefter notes server (podman-compose)
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=%h/tefter
|
||||
EnvironmentFile=%h/tefter/.env.docker
|
||||
ExecStart=/home/hamo/.local/bin/podman-compose up
|
||||
ExecStop=/home/hamo/.local/bin/podman-compose down
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
20
docker-compose.yml
Normal file
20
docker-compose.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
services:
|
||||
tefter:
|
||||
build:
|
||||
context: .
|
||||
args:
|
||||
VERSION: ${TEFTER_VERSION:-dev}
|
||||
environment:
|
||||
TEFTER_DB: /data/tefter.db
|
||||
volumes:
|
||||
# ":Z" relabels for SELinux (required on the podman/SELinux server; a
|
||||
# harmless no-op on non-SELinux Docker hosts).
|
||||
- data:/data:Z
|
||||
security_opt:
|
||||
- label:disable
|
||||
ports:
|
||||
- "${WEB_PORT:-8420}:8420"
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
data:
|
||||
Reference in New Issue
Block a user