Dokploy Deployment Guide for Astro
This guide documents the deployment approach used to deploy an Astro project to Dokploy (Hostinger) with Docker and Nginx.
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:
Dockerfilenginx.conf.dockerignore
3. Dockerfile Strategy (Multi-Stage)
The build has two stages:
- Builder stage (
node:22-alpine)
- Installs pnpm
- Installs dependencies
- Runs
pnpm run build - Produces static output in
dist/
- 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.0in build environments. - Use pnpm v9 in Docker to avoid non-interactive
approve-buildsfailures 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
- Long cache for versioned assets (
- Security headers:
X-Frame-OptionsX-Content-Type-OptionsX-XSS-ProtectionReferrer-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:latestOpen:
http://localhost:8080
Quick checks:
- Home page loads
- Refresh works
- Direct route (for example
/about) works
6. Dokploy Deployment Steps
- Push repo changes to your Git provider.
- Open Dokploy dashboard.
- Create or open your application.
- Select Docker-based deployment (not Nixpacks).
- Ensure configuration:
- Dockerfile path:
Dockerfile - Build context:
.
- Deploy.
- Watch build/runtime logs.
- 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 examplenpm 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 buildIf 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 -t8. Useful Nginx Commands (inside container)
nginx -t
nginx -s reload
nginx -s stop9. Recommended Production Notes
- 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
-
Dockerfilepresent -
nginx.confpresent -
.dockerignorepresent -
docker buildsucceeds 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)
| Setting | Value |
|---|---|
| Source provider | GitHub |
| Repository | lussino/my-first-app |
| Branch | main |
| Build type | Dockerfile |
| Dockerfile path | Dockerfile |
| Build context | . |
| Internal container port | 80 |
| Health check path | / |
| Auto deploy on push | Enabled |
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:
| Variable | Example | Required |
|---|---|---|
PUBLIC_SITE_URL | https://app.yourdomain.com | Yes |
PUBLIC_SITE_NAME | My First App | Optional |
NODE_ENV | production | Yes |
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)
- Merge approved changes into
main. - Confirm
Dockerfile,nginx.conf, and.dockerignoreare present. - Dokploy auto-build triggers from
mainpush. - Check build logs for image build success.
- Check runtime logs for healthy startup.
- Validate
https://<your-domain>/in browser. - Validate one deep route (for example
/about) to confirm SPA fallback.
Rollback SOP
- In Dokploy, open deployments history for
my-first-app-prod. - Redeploy last known healthy image/revision.
- Confirm site and deep-route health checks.
- 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:latestserves 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.
| Key | Your Value |
|---|---|
| Production app name | my-first-app-prod |
| Staging app name | my-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
- Go to Dokploy Dashboard -> Applications.
- Click Create Application (or open existing app).
- Select GitHub as source and choose
lussino/my-first-app.
Screenshot placeholder:
docs/screenshots/01-app-create.png
Step 2: Configure Source and Branch
- Set repository to
lussino/my-first-app. - Set branch to
mainfor production. - Enable auto deploy on push (recommended).
Screenshot placeholder:
docs/screenshots/02-source-branch.png
Step 3: Configure Docker Build
- Build type: Dockerfile.
- Dockerfile path:
Dockerfile. - Build context:
.
Screenshot placeholder:
docs/screenshots/03-docker-build.png
Step 4: Configure Runtime/Network
- Internal container port:
80. - Health check path:
/. - Save settings.
Screenshot placeholder:
docs/screenshots/04-runtime-port-health.png
Step 5: Domain and SSL
- Open Domains (or Routing) in Dokploy.
- Add production domain.
- Enable SSL certificate and wait for issuance.
Screenshot placeholder:
docs/screenshots/05-domain-ssl.png
Step 6: Deploy and Verify
- Click Deploy.
- Watch build logs until success.
- Open your domain and validate home + deep route.
Screenshot placeholder:
docs/screenshots/06-deploy-success.png
Step 7: Rollback Drill (Recommended)
- Open Deployment History.
- Identify last healthy deployment.
- 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.png14. 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=200HOME_CT=text/htmlDEEP_STATUS=301Locationheader for/aboutredirected to/about//about/returnedHTTP/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.