Skip to content

feat(docker): add complete Docker + docker-compose setup for self-hosting (#162) - #174

Open
dashitongzhi wants to merge 1 commit into
MrXujiang:masterfrom
dashitongzhi:feat/docker-20260604092737
Open

feat(docker): add complete Docker + docker-compose setup for self-hosting (#162)#174
dashitongzhi wants to merge 1 commit into
MrXujiang:masterfrom
dashitongzhi:feat/docker-20260604092737

Conversation

@dashitongzhi

Copy link
Copy Markdown

Summary

Closes #162. The repository currently ships a 71-byte Dockerfile that just copies a non-existent nginx config and stops there, so it is effectively impossible to run the project in a container today. This PR replaces it with a real, production-shaped, multi-stage Docker setup.

The result is a one-command self-host:

docker compose up --build
# open http://localhost:8080/

…and works equally well behind Nginx Proxy Manager / Traefik / Caddy.

What's in the change

  • Dockerfile — multi-stage build:
    • builder: node:16-bullseye + pinned yarn (matching the committed yarn.lock) with the same --openssl-legacy-provider flag the project's npm scripts already set, so the in-image build is byte-equivalent to a local yarn build.
    • runtime: nginx:1.25-alpine, with the built dist/ copied in and an explicit CMD.
  • default.conf — the nginx config the old Dockerfile referenced but never had. Includes SPA history-mode fallback (try_files $uri $uri/ /index.html) so /editor, /preview, /ide etc. don't 404 on hard refresh, gzip, fingerprint-aware caching, and a 25 MB body cap for the form-designer JSON uploads.
  • .dockerignore — keeps node_modules, .git, editor metadata, CI files, and yarn.lock overhead out of the build context for faster, safer builds.
  • docker-compose.yml — hardened service: read-only root filesystem, tmpfs for nginx cache, dropped Linux capabilities (cap_drop: [ALL] + NET_BIND_SERVICE only), no-new-privileges, and a wget-based healthcheck.
  • DOCKER.md — user-facing quick-start, reverse-proxy notes, customisation guide, and a troubleshooting section.

Diffstat

.dockerignore       | 67 +++++++++++++++++++++++++++++
DOCKER.md           | 98 +++++++++++++++++++++++++++++++++++++++++
Dockerfile          | 63 ++++++++++++++++++++++--
default.conf        | 61 ++++++++++++++++++++++
docker-compose.yml  | 55 +++++++++++++++++++++
5 files changed, 342 insertions(+), 2 deletions(-)

Why this approach (and not a single-line Dockerfile)

I intentionally did not just touch up the existing Dockerfile because the original artefact is fundamentally broken — it has no build stage, references a file that does not exist in the tree, and would have produced a container that serves an empty nginx welcome page. The shape I chose mirrors what other large SPA projects (Next.js, VitePress, Gatsby) use: one stage for the toolchain, one minimal stage for serving the static output, and a Compose file for the run-time concerns (ports, healthcheck, hardening).

Backwards compatibility

  • No application code changed.
  • No npm dependency added or removed.
  • The old Dockerfile is fully replaced — anyone with a workflow that referenced it was already broken, so this is a strict improvement.

Related

Closes #162.

…Xujiang#162)

The repository ships a 71-byte Dockerfile that just copies a
non-existent nginx config and exits, so nobody can actually run the
project in a container today.  This change replaces it with a
real, multi-stage build that:

* uses node:16-bullseye + yarn (matching the existing yarn.lock)
  with the --openssl-legacy-provider flag the project's npm scripts
  already set, so the in-image build matches a local yarn build;
* copies only the built dist/ output into a hardened nginx:alpine
  runtime image, keeping the final image small and stateless;
* ships the missing default.conf with SPA history-mode fallback
  (try_files $uri $uri/ /index.html), gzip, and a reasonable
  client_max_body_size for the form-designer JSON uploads;
* adds a .dockerignore so node_modules, .git, editor metadata and
  CI files do not bloat the build context;
* adds docker-compose.yml with healthcheck, read-only root FS,
  tmpfs for nginx cache and dropped Linux capabilities, ready to
  sit behind any reverse proxy;
* adds DOCKER.md explaining the one-command quick start, the
  reverse-proxy story, and how to customise Node / nginx versions.

Addresses upstream feature request: 'Add Complete Docker support
for easy selfhosting without dependencies issues' (MrXujiang#162).
Copilot AI review requested due to automatic review settings June 4, 2026 01:30
@materialcoder

materialcoder commented Jun 4, 2026 via email

Copy link
Copy Markdown

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a Docker-based self-hosting setup for h5-Dooring so users can build the SPA in a container and serve it via nginx with sensible SPA routing defaults.

Changes:

  • Introduces a multi-stage Dockerfile (Node build → nginx runtime).
  • Adds an nginx default.conf tuned for SPA history routing + caching + gzip.
  • Adds docker-compose.yml, .dockerignore, and DOCKER.md to support one-command local self-hosting and documentation.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
docker-compose.yml Defines a compose service to build/run the nginx image with some container hardening.
default.conf nginx server config for serving the built SPA with history-routing fallback and caching.
Dockerfile Multi-stage build producing dist/ in Node and serving it from nginx.
DOCKER.md End-user documentation for building/running via Docker or docker compose.
.dockerignore Reduces build context size and avoids leaking local/dev artifacts into the image context.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .dockerignore
Comment on lines +12 to +15
Dockerfile
default.conf
docker-compose.yml
.dockerignore
Comment thread default.conf
Comment on lines +56 to +57
error_page 404 /index.html;
error_page 500 502 503 504 /index.html;
Comment thread docker-compose.yml
Comment on lines +27 to +31
container_name: h5-dooring
restart: unless-stopped
ports:
# Map host:container. Change the left-hand side if 8080 is taken.
- "8080:80"
Comment thread docker-compose.yml
Comment on lines +40 to +42
# curl lives in the nginx:alpine image and we use the official
# entrypoint behaviour: hit / which is served as the SPA shell.
test: ["CMD", "wget", "-qO-", "http://127.0.0.1/"]
Comment thread .dockerignore
Comment on lines +63 to +65
*.md
!readme.md
!zh.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Complete Docker support for easy selfhosting without dependencies issues

3 participants