Skip to content

Docker: run community and business side by side - #335

Draft
ericholscher wants to merge 7 commits into
mainfrom
side-by-side-docker-envs
Draft

ericholscher wants to merge 7 commits into
mainfrom
side-by-side-docker-envs

Conversation

@ericholscher

@ericholscher ericholscher commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Lets the community and business local environments run at the same time. Before, both published NGINX on port 80 plus webpack (10001), addons (8000), storage (9000/9001) and Elasticsearch (9200), so only one could run.

  • Only NGINX is published on the host now. dockerfiles/nginx/services.conf.template serves the other services by hostname: assets., addons., storage., storage-console. and search.$NGINX_WEB_SERVER_NAME. All of them are HTTP, so hostname routing on port 80 covers them, and no HAProxy/TCP layer is needed. Upstreams resolve per request (resolver + variable), because those containers may start after NGINX or not at all (--no-search).
  • dockerfiles/nginx/side-by-side.conf.template forwards the other environment's domains to its NGINX through host.docker.internal, including websockets. Whichever environment owns port 80 does the forwarding, so start order doesn't matter. Every URL stays the same, so CAS/private docs on business keep working.
  • No configuration: inv docker.up (and docker.compose) publish NGINX on port 80 unless another container already publishes it (docker ps --filter publish=80, which matches the host port). Then they use the environment's side-by-side port: 10080 for community, 10081 for business. Our own NGINX doesn't count, so re-running up doesn't move it, and once the other environment stops, the next up takes port 80 back. RTDDEV_PORT_NGINX overrides it. Compose can't share a single NGINX container across two projects: a shared container_name fails with a name conflict.
  • Template mounts: common/dockerfiles/nginx is mounted at /etc/common/dockerfiles/nginx, and each repo symlinks the templates from its own dockerfiles/nginx/. A file mount nested inside the bind-mounted templates directory doesn't work: Docker Desktop fails to start the container, and Docker leaves an empty mountpoint file in the repository.
  • Storage Host header: both storage blocks pass the original Host, because S3 clients (SigV4, and the RustFS console, which calls the APIs on its own origin) sign it.

Breaking for local workflows: localhost:9000/9001/9200/10001/8000 no longer answer. Use the hostnames above.

Companion PRs: readthedocs/readthedocs.org#13365 (settings, community defaults, docs) and readthedocs/readthedocs-corporate#2158 (business defaults).

I tested with both environments running from these branches, in both orders. The dashboards, docs and .com private docs (CAS) load for both. The other checks all passed on both domains:

  • the webpack CSS and live reload websocket (101)
  • the addons JS
  • the storage console
  • Elasticsearch
  • a presigned POST to storage.devthedocs.com (204)
  • boto3 listing from the host

🤖 Generated with Claude Code

Make every host port configurable with RTDDEV_PORT_* variables (defaults
unchanged), and add an opt-in front proxy (inv docker.front) that owns
port 80 and routes *.devthedocs.com to business and everything else to
community.
The community NGINX routes *.devthedocs.com to business instead
(readthedocs/readthedocs.org#13365).
Both environments mount the same side-by-side template, so whichever one
owns port 80 forwards the other one's domains to it.
A file mount inside the bind-mounted templates directory makes Docker
create an empty mountpoint file in the repository.
Only NGINX is published on the host now. It serves webpack, addons,
storage (API and console) and Elasticsearch on assets., addons.,
storage., storage-console. and search.<domain>, so the side-by-side
forward covers them too and only RTDDEV_PORT_NGINX is needed.
…irect

Pass the Host header to storage so SigV4 clients work, and send / on the
storage console to /rustfs/console/.
inv docker.up and docker.compose publish NGINX on port 80, unless
another container already publishes it: then they use the environment's
side-by-side port, so the second environment needs no configuration.
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.

1 participant