Skip to Content
chalvien 1.0 is released
DocumentationGuidesAstroDokploy Deployment

Dokploy Deployment Guide for Your Astro App

This guide documents the deployment approach we used deploying an Astro project to Dokploy (Hostinger) with Docker and Nginx.

1. Goal

Deploy a static Astro site using:

  • Docker multi-stage build
  • Nginx as the runtime web server
  • Dokploy as the deployment platform

Why this approach:

  • Lower memory usage than running Node in production for static files
  • Faster static file delivery
  • Smaller production image

2. Project Files Used

These files are used for deployment:

  • Dockerfile
  • nginx.conf
  • .dockerignore

3. Dockerfile Strategy (Multi-Stage)

The build has two stages:

  1. Builder stage (node:22-alpine)
  • Installs pnpm
  • Installs dependencies
  • Runs pnpm run build
  • Produces static output in dist/
  1. Runtime stage (nginx:alpine)
  • Copies nginx.conf
  • Copies built files from dist/ into Nginx web root
  • Exposes port 80
  • Starts Nginx in foreground

Result: production container serves static files with Nginx only.

Important compatibility notes for this repo:

  • Astro 6 requires Node >=22.12.0 in build environments.
  • Use pnpm v9 in Docker to avoid non-interactive approve-builds failures from newer pnpm defaults.

4. Nginx Config Essentials

The Nginx config in this project includes:

  • Gzip compression for text assets
  • Cache rules:
    • Long cache for versioned assets (.js, .css, fonts, svg)
    • Medium cache for images
    • No cache for HTML
  • Security headers:
    • X-Frame-Options
    • X-Content-Type-Options
    • X-XSS-Protection
    • Referrer-Policy
  • SPA-style fallback:
    • try_files $uri $uri/ /index.html;

This fallback is important when users open deep routes directly.

5. Local Test Workflow

From project root:

docker build -t my-astro-app:latest .
docker run -p 8080:80 my-astro-app:latest

Open:

  • http://localhost:8080

Quick checks:

  • Home page loads
  • Refresh works
  • Direct route (for example /about) works

6. Dokploy Deployment Steps

  1. Push repo changes to your Git provider.
  2. Open Dokploy dashboard.
  3. Create or open your application.
  4. Select Docker-based deployment (not Nixpacks).
  5. Ensure configuration:
  • Dockerfile path: Dockerfile
  • Build context: .
  1. Deploy.
  2. Watch build/runtime logs.
  3. Attach domain and SSL in Dokploy.

7. Troubleshooting

Build fails during pnpm install

Possible causes:

  • Lockfile out of sync
  • pnpm version mismatch
  • network/cache issue in build environment

If you see ERR_PNPM_IGNORED_BUILDS during Docker build:

  • Pin pnpm to v9 in Dockerfile (for example npm install -g pnpm@9).
  • Rebuild image.

If you see Astro Node version error:

  • Ensure Docker builder image uses Node 22+ (for example node:22-alpine).

Try:

pnpm install pnpm run build

If local works, rebuild image with no cache:

docker build --no-cache -t my-astro-app:latest .

Build succeeds but app is blank/404 on refresh

  • Verify Nginx fallback exists:
location / { try_files $uri $uri/ /index.html; }

Container starts but not reachable

  • Confirm Dokploy published port correctly
  • Confirm container listens on port 80 (Nginx)
  • Check Dokploy service/domain routing and SSL settings

Validate Nginx config inside container

nginx -t

8. Useful Nginx Commands (inside container)

nginx -t nginx -s reload nginx -s stop
  • Keep Astro output static when possible.
  • Cache immutable assets aggressively.
  • Keep HTML non-cached for safe updates.
  • Keep image small by using multi-stage Docker builds.
  • Monitor Dokploy logs after each deployment.

10. Quick Reference Checklist

  • Dockerfile present
  • nginx.conf present
  • .dockerignore present
  • docker build succeeds locally
  • docker run -p 8080:80 ... serves site
  • Docker deployment selected in Dokploy
  • Domain + SSL configured

11. Hostinger Dokploy Appendix (Project-Specific)

Use this section as your default runbook for this repository.

Repository Mapping

  • Repository: lussino/my-first-app
  • Production branch: main
  • Suggested Dokploy app name: my-first-app-prod
  • Suggested staging app name: my-first-app-staging

Copy-Ready Dokploy Settings (Production)

SettingValue
Source providerGitHub
Repositorylussino/my-first-app
Branchmain
Build typeDockerfile
Dockerfile pathDockerfile
Build context.
Internal container port80
Health check path/
Auto deploy on pushEnabled

Domain and Routing

  • Add your production domain in Dokploy (for example, app.yourdomain.com).
  • Ensure HTTPS/SSL is enabled in Dokploy.
  • If you use a root domain and www, set a single canonical host and redirect the other.

Environment Variables Convention

This Astro setup is static-first. If you do not use runtime server code, you may need few or no runtime env vars.

If needed, define variables in Dokploy using this naming approach:

  • Public values exposed to client bundle: PUBLIC_*
  • Private values for build-time only: non-PUBLIC_*

Recommended starter set:

VariableExampleRequired
PUBLIC_SITE_URLhttps://app.yourdomain.comYes
PUBLIC_SITE_NAMEMy First AppOptional
NODE_ENVproductionYes

Suggested Branch Strategy

  • main -> production Dokploy app (my-first-app-prod)
  • develop -> staging Dokploy app (my-first-app-staging)

This lets you validate changes in staging before promoting to production.

Deployment SOP (Production)

  1. Merge approved changes into main.
  2. Confirm Dockerfile, nginx.conf, and .dockerignore are present.
  3. Dokploy auto-build triggers from main push.
  4. Check build logs for image build success.
  5. Check runtime logs for healthy startup.
  6. Validate https://<your-domain>/ in browser.
  7. Validate one deep route (for example /about) to confirm SPA fallback.

Rollback SOP

  1. In Dokploy, open deployments history for my-first-app-prod.
  2. Redeploy last known healthy image/revision.
  3. Confirm site and deep-route health checks.
  4. Create a follow-up fix branch before next production deploy.

Pre-Deploy Checklist for This Repo

  • Local docker build -t my-astro-app:latest . succeeds
  • Local docker run -p 8080:80 my-astro-app:latest serves correctly
  • Home route and one deep route load
  • Domain points to Dokploy service
  • SSL certificate is active

12. Quick Personalization Block (Fill Once)

Fill this section with your real values and keep it updated.

KeyYour Value
Production app namemy-first-app-prod
Staging app namemy-first-app-staging
Production domain<set-your-domain>
Staging domain<set-your-staging-domain>
Git branch (prod)main
Git branch (staging)develop

Tip: after filling this table, reuse these values in Dokploy settings to avoid drift.

13. Dokploy UI Walkthrough (With Screenshot Placeholders)

Use this as a visual checklist. Replace each placeholder with your own screenshot.

Step 1: Create or Open Application

  1. Go to Dokploy Dashboard -> Applications.
  2. Click Create Application (or open existing app).
  3. Select GitHub as source and choose lussino/my-first-app.

Screenshot placeholder:

  • docs/screenshots/01-app-create.png

Step 2: Configure Source and Branch

  1. Set repository to lussino/my-first-app.
  2. Set branch to main for production.
  3. Enable auto deploy on push (recommended).

Screenshot placeholder:

  • docs/screenshots/02-source-branch.png

Step 3: Configure Docker Build

  1. Build type: Dockerfile.
  2. Dockerfile path: Dockerfile.
  3. Build context: .

Screenshot placeholder:

  • docs/screenshots/03-docker-build.png

Step 4: Configure Runtime/Network

  1. Internal container port: 80.
  2. Health check path: /.
  3. Save settings.

Screenshot placeholder:

  • docs/screenshots/04-runtime-port-health.png

Step 5: Domain and SSL

  1. Open Domains (or Routing) in Dokploy.
  2. Add production domain.
  3. Enable SSL certificate and wait for issuance.

Screenshot placeholder:

  • docs/screenshots/05-domain-ssl.png

Step 6: Deploy and Verify

  1. Click Deploy.
  2. Watch build logs until success.
  3. Open your domain and validate home + deep route.

Screenshot placeholder:

  • docs/screenshots/06-deploy-success.png
  1. Open Deployment History.
  2. Identify last healthy deployment.
  3. Trigger redeploy for that revision.

Screenshot placeholder:

  • docs/screenshots/07-rollback.png

Optional Folder Convention for Screenshots

If you want to keep screenshots in this repo, use:

docs/ screenshots/ 01-app-create.png 02-source-branch.png 03-docker-build.png 04-runtime-port-health.png 05-domain-ssl.png 06-deploy-success.png 07-rollback.png

14. Verified Smoke Test (Executed)

This section records a real local verification run against the built Docker image.

Command Used

cid=$(docker run -d --rm -p 8080:80 my-astro-app:latest) curl -sS -o /tmp/home.html -w "HOME_STATUS=%{http_code}\nHOME_CT=%{content_type}\n" http://localhost:8080/ curl -sS -o /tmp/deep.html -w "DEEP_STATUS=%{http_code}\nDEEP_CT=%{content_type}\n" http://localhost:8080/about curl -sS -I http://localhost:8080/about curl -sS -I http://localhost:8080/about/ docker stop "$cid"

Observed Results

  • HOME_STATUS=200
  • HOME_CT=text/html
  • DEEP_STATUS=301
  • Location header for /about redirected to /about/
  • /about/ returned HTTP/1.1 200 OK

Interpretation:

  • Container is serving the Astro site correctly via Nginx.
  • Deep route behavior is correct for trailing-slash canonicalization.

Note:

  • A brief connection reset can happen immediately after container startup in fast local checks. Retrying the request resolves it once Nginx is fully ready.