DEV Community

szokker
szokker

Posted on

The Day Docker Refused to Start My Website (And Why It Was My Fault)

A few weeks ago, everything was running perfectly.
My tutorial site was fully automated.
Every morning:
Content generated
Astro built the static files
Docker restarted NGINX
The new version went live
It felt clean. Controlled. Professional.
Then one restart killed the entire site.
No warning.
No partial failure.
Just… dead.
The Error
Docker wouldn’t start the NGINX container.
The only message:

Bind mount failed: '/volume1/docker/tutorialshub/dist' does not exist

That was it.
No stack trace.
No helpful explanation.
Just refusal.
And the site was offline.
My First Thought: “Docker is Broken.”
I checked:
docker-compose.yml
NGINX config
Port mappings
Permissions
Everything looked correct.
The volume mapping was simple:

./dist:/usr/share/nginx/html

This had been working for weeks.
So what changed?
The Missing Folder
I SSH’d into my Synology NAS and navigated to:

/volume1/docker/tutorialshub/

There was no dist folder.
And suddenly everything made sense.
Astro generates /dist during build.
No build → no folder.
No folder → Docker refuses to mount it.
Docker wasn’t broken.
It was protecting me.
The Real Problem: Deployment Order
Here’s what happened:
I triggered a container restart
The build step hadn’t completed
/dist didn’t exist
Docker tried to mount it
Docker aborted startup
Static sites look simple.
But they depend entirely on build artifacts.
If your artifact doesn’t exist,
your “application” doesn’t exist.
Why Docker Refuses Missing Paths
I learned something important that day.
Docker bind mounts are strict by design.
If you use a bind mount:

./dist:/usr/share/nginx/html

Docker assumes:
“You, the operator, guarantee that this path exists.”
If it doesn’t, Docker fails immediately.
It doesn’t auto-create.
It doesn’t guess.
It doesn’t forgive.
And honestly — that’s good.
Because silent failures are worse.
The Fix (And the Embarrassment)
The solution was painfully simple.
Run the build first.

npm run build
docker-compose down
docker-compose up -d

That’s it.
But the lesson wasn’t about the command.
It was about architecture.
Static Sites Shift Complexity
We love static sites because:
No backend
No runtime logic
No database
Fast performance
But static doesn’t remove complexity.
It shifts it.
From runtime → to deployment time.
Your build artifact becomes your application.
If you mishandle that artifact,
everything breaks instantly.
The SEO Side Effect
While the container was failing:
Pages returned 404
Sitemap became inaccessible
Google Search Console stalled indexing
Infrastructure stability isn’t just DevOps vanity.
It directly affects SEO trust.
That was an unexpected lesson.
What I Changed After
I stopped relying on manual sequencing.
Instead of:
Build → Restart → Hope
I added validation.
Now my deploy script:
Builds
Verifies /dist exists
Only then restarts containers
I’m also experimenting with a multi-stage Docker build
to remove bind mounts completely.
Because the cleanest solution is:
No filesystem dependency at all.
What This Taught Me
Self-hosting teaches you fast.
Docker isn’t “magic.”
Static sites aren’t “simple.”
Automation hides fragility.
But failures like this are valuable.
Because they expose architectural weaknesses.
And once you see them,
you can design better systems.
If you're containerizing static frameworks like Astro,
double-check your build artifacts before restarting anything.
That one missing folder cost me an afternoon —
and temporarily killed my site.
Lesson learned.
If there’s interest, I can write a deeper technical breakdown of the deployment architecture and the improvements I’m implementing next.
The full technical write-up is here:

Top comments (0)