Deploy Astro Starlight on Docker
This guide documents the deployment of this documentation site at docs.smilepowered.org using Astro Starlight, Docker, and Traefik.
Prerequisites
Section titled “Prerequisites”- Debian server with Docker and Docker Compose installed
- Traefik reverse proxy running
- DNS A record pointing to your server IP
Architecture
Section titled “Architecture”┌─────────────────┐│ Traefik │ Port 80/443│ (reverse │ SSL via Let's Encrypt│ proxy) │└────────┬────────┘ │ ▼┌─────────────────┐│ nginx:alpine │ Serves static files│ (docs) │ from /dist└─────────────────┘Project Structure
Section titled “Project Structure”/opt/docker/docs/├── compose.yaml # nginx serving dist/├── build.sh # docker run node:22-alpine build├── package.json├── astro.config.mjs├── src/│ ├── content.config.ts│ └── content/docs/│ └── *.mdx├── public/│ └── downloads/└── dist/ # generated static siteStep 1 - Create DNS Record
Section titled “Step 1 - Create DNS Record”Add an A record pointing to your server:
Type: AName: docsValue: <your_server_ip>Verify DNS propagation:
dig +short docs.<your_domain>.com AStep 2 - Create Directory Structure
Section titled “Step 2 - Create Directory Structure”mkdir -p /opt/docker/docs/src/content/docsmkdir -p /opt/docker/docs/public/downloadsStep 3 - Create package.json
Section titled “Step 3 - Create package.json”Create /opt/docker/docs/package.json:
{ "name": "astro-docs-debian", "type": "module", "version": "0.0.1", "scripts": { "dev": "astro dev", "start": "astro dev", "build": "astro build", "preview": "astro preview", "astro": "astro" }, "dependencies": { "astro": "^6.0.0", "@astrojs/starlight": "^0.38.0" }}Step 4 - Create astro.config.mjs
Section titled “Step 4 - Create astro.config.mjs”Create /opt/docker/docs/astro.config.mjs:
import { defineConfig } from 'astro/config';import starlight from '@astrojs/starlight';
export default defineConfig({ site: 'https://docs.<your_domain>.com', integrations: [ starlight({ title: 'Astro docs on Debian', }), ],});Step 5 - Create Content Config
Section titled “Step 5 - Create Content Config”Create /opt/docker/docs/src/content.config.ts:
import { defineCollection } from 'astro:content';import { docsLoader } from '@astrojs/starlight/loaders';import { schema } from '@astrojs/starlight/schema';
export const collections = { docs: defineCollection({ loader: docsLoader(), schema }),};Step 6 - Create Build Script
Section titled “Step 6 - Create Build Script”Create /opt/docker/docs/build.sh:
#!/bin/shdocker run --rm \ -v "$(dirname "$0")":/app \ -w /app \ node:22-alpine \ sh -c "npm install && npm run build"Make it executable:
chmod +x /opt/docker/docs/build.shStep 7 - Create Index Page
Section titled “Step 7 - Create Index Page”Create /opt/docker/docs/src/content/docs/index.mdx:
---title: Your Site Titledescription: Site description---
Welcome to the documentation.Step 8 - Build the Site
Section titled “Step 8 - Build the Site”cd /opt/docker/docs./build.shThis pulls node:22-alpine and generates the dist/ folder.
Step 9 - Create Docker Compose
Section titled “Step 9 - Create Docker Compose”Create /opt/docker/docs/compose.yaml:
services: docs: image: nginx:alpine container_name: docs restart: unless-stopped volumes: - ./dist:/usr/share/nginx/html:ro labels: - "traefik.enable=true" - "traefik.http.routers.docs.rule=Host(`docs.<your_domain>.com`)" - "traefik.http.routers.docs.entrypoints=websecure" - "traefik.http.routers.docs.tls.certresolver=letsencrypt" - "traefik.http.services.docs.loadbalancer.server.port=80" networks: - proxy deploy: resources: limits: memory: 64M
networks: proxy: external: trueStep 10 - Start the Container
Section titled “Step 10 - Start the Container”cd /opt/docker/docsdocker compose up -dStep 11 - Verify
Section titled “Step 11 - Verify”Visit https://docs.<your_domain>.com in your browser.
Adding New Content
Section titled “Adding New Content”- Create new
.mdxfile insrc/content/docs/ - Run
./build.sh - nginx serves updated content automatically
Adding Downloadable Files
Section titled “Adding Downloadable Files”- Copy files to
public/downloads/ - Run
./build.sh - Link to files:
/downloads/filename.ext
Troubleshooting
Section titled “Troubleshooting”Build fails with content config error
Section titled “Build fails with content config error”Astro 6 requires src/content.config.ts (not src/content/config.ts). Ensure you’re using the new format with docsLoader().
404 errors
Section titled “404 errors”Verify dist/ folder exists and contains index.html.
SSL certificate issues
Section titled “SSL certificate issues”Check Traefik logs:
docker logs traefikEnsure DNS is properly configured and propagating.