Files
astro-docs/README.docker.md
2026-08-22 12:19:49 -07:00

3.7 KiB

astro-docs — Docker deployment

Single container. Astro + Starlight, served by the Astro Node adapter on port 7701. TLS, hostname routing, and auth stay with your existing nginx + Authelia.

1. Create the app source

Add folder to NAS under /docker

Make sure the folder has general read/write permissions.

ssh into NAS and navigate to the folder created above.

Most of the files have already been added to this repo, but to make sure everything is up to date, re-install the Astro project alongside them.

npm create astro@latest astro-docs -- --template starlight

Copy Dockerfile, .dockerignore, and compose.yaml into the generated project, then add the Node adapter:

npx astro add node

2. Required config

astro.config.mjs must produce a standalone server — the container runs dist/server/entry.mjs:

import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
import starlight from '@astrojs/starlight';

export default defineConfig({
  site: 'https://docs.example.org', // public URL served by nginx
  output: 'server',
  adapter: node({ mode: 'standalone' }),
  integrations: [starlight({ title: 'astro-docs' })],
});

Starlight prerenders its routes, so pages are static output; the Node server just delivers them. package.json needs "build": "astro build" (the Starlight template includes it).

Commit package-lock.json. Without it the image build falls back to npm install, which gives up reproducible dependency versions.

3. Deploy via Dockhand

Dockhand expects the stack at {DATA_DIR}/stacks/{environment}/astro-docs/compose.yaml. Because this stack builds from source, the whole project has to live in that directory — Dockhand's Git auto-sync is the intended way to get it there.

  1. Push the project (app source + these Docker files) to Gitea.
  2. Create the astro-docs stack in Dockhand and point its Git sync at that repo, so the stack directory is populated from the repo rather than by hand.
  3. Set TZ in Dockhand's encrypted environment editor. Do not commit a .env — auto-sync will overwrite it. TZ is the only variable; everything else is fixed in compose.yaml.
  4. Deploy. The first run builds the image on the NAS, which takes several minutes.
  5. Verify over SSH on the NAS:
curl -I http://localhost:7701/
  1. Point an nginx vhost at http://<nas-ip>:7701, and decide whether it sits behind Authelia or is publicly readable.

Faster alternative: build off-NAS

Building on NAS hardware is slow and memory-hungry. To build on your workstation and push to Gitea's registry instead, drop the build: block from compose.yaml and set image: <gitea-host>/<user>/astro-docs:latest. Dockhand then only pulls, and the stack directory needs nothing but compose.yaml.

4. Publishing content changes

The image holds a build artifact, so edits under src/content/docs/ go live only after a rebuild — push to Gitea, then trigger Dockhand's rebuild/redeploy on the stack.

Notes

  • No name: or container_name: — they collide across Dockhand environments.
  • No bind mounts: this stack is stateless, so nothing survives or needs to survive a redeploy.
  • platform: linux/amd64 is pinned for Synology x86 hardware. Remove that line on ARM models.
  • Runs as the non-root node user, read-only root filesystem, /tmp on tmpfs.
  • The health check uses Node's built-in fetch; the image ships no curl or wget.
  • Base image is node:24-bookworm-slim rather than Alpine, because Starlight's image optimization pulls in sharp, which is less trouble on glibc.

Not verified

Neither Node nor Docker is available in the environment where these files were written, so nothing here has been built or run. The first Dockhand deploy is the first real test.