Bootstrap CodePress Live Dev Server recipe + dev Dockerfile - #58
Open
codepress-dev[bot] wants to merge 1 commit into
Open
Conversation
Author the committed Live Dev Server artifacts for this repo so previews boot
from repo-owned files instead of a runtime heuristic.
Discovered one runnable frontend: web/ (create-react-app 1.0.10, Yarn 1).
The Django app in server/ is same-origin only -- it serves the built React
bundle through its catch-all URL and has no CORS surface and no cross-origin
caller -- so no preview-CORS change was made. No staging backend URL was
found, so staging_backend_url is intentionally omitted.
Verified end to end on the pinned node:18-bookworm base:
- yarn install --frozen-lockfile succeeds against the 2017 lockfile
- react-scripts start compiles and serves HTTP 200
- binds 0.0.0.0:3000 and answers on a non-loopback address
- accepts a *.preview.codepress.dev Host header (host check off)
- /sockjs-node/info reports websocket support
- a source edit triggers a second successful compile (hot reload works)
Node 18 is pinned deliberately: this toolchain's websocket-driver 0.6.5 calls
process.binding('http_parser'), which Node 18 still provides but newer Node
removes -- the dev server crashes on boot there.
Co-authored-by: dev@codepress.dev <dev@codepress.dev>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This sets up the files CodePress needs to run live, shareable previews of the React app in this repo. Previously the preview system had to guess how to start your frontend; now the repo itself declares it, so previews boot the same way every time and hot reload works while you edit.
The repo has one runnable frontend (
web/, a create-react-app project) and a Django backend (server/). Only the frontend needs preview artifacts. Because the app is 2017-era (create-react-app 1.0.10), the interesting question was whether it still runs at all on a modern base image — so rather than assume, I installed its dependencies and actually booted the dev server to confirm it compiles, serves the page, and hot-reloads. It does.Two things were deliberately left alone. The Django app serves the built React bundle from its own catch-all URL, so it is same-origin and has no cross-origin browser callers and no CORS configuration at all — there is nothing to open up for previews, and adding CORS would be inventing a problem. And no staging backend URL exists anywhere in the repo, so none was recorded rather than guessing one.
Technical details
Adds
.codepress/dev-server/recipe.json(schema_version: 1) with a singlefrontends[]entry forweb/, plus.codepress/dev-server/Dockerfile.web. No application code is touched.Recipe entry (
web):working_dir: "web",framework: "cra",package_manager: "yarn",dev_port: 3000,install_command: "yarn install --frozen-lockfile",dependency_manifests: ["web/yarn.lock"](the per-app lockfile — there is no root lockfile),system_packages: ["procps"],size: "medium". Noprebuild_command: thepostbuildscript inweb/package.jsoncopies a production build into Django's static dir and is not a dev-server prerequisite.Why the base image is
node:18-bookwormand not current LTS. This is the load-bearing decision.sockjs@0.3.18→faye-websocket→websocket-driver@0.6.5callsprocess.binding('http_parser'). I verified empirically that Node 18.20.8 still provides that binding (deprecated) while Node 25 does not — on Node 25 the dev server dies at boot withError: No such module: http_parser. Node 18 is also the oldest Node with an official-bookwormvariant, so it is simultaneously the most conservative choice available and the newest one that works. Pulled from thepublic.ecr.awsmirror; full-bookworm, not-slim, since deps install at runtime and may need node-gyp.No
--openssl-legacy-provider. Worth flagging because it is the usual reflex for a toolchain this old. It is not needed here:webpack@2.6.1defaultsoutput.hashFunctionto md5 (WebpackOptionsDefaulter.js), not md4. md4 became the default in webpack 4, so areact-scriptsupgrade to v2+ would need the flag on OpenSSL 3 — there is a comment in the Dockerfile saying exactly that, so a future upgrader is not left guessing.Bind and HMR wiring.
react-scripts@1.0.10readsHOSTandPORTfrom env (confirmed in itsscripts/start.js), so the CMD mapsHOST="${CODEPRESS_BIND_HOST:-0.0.0.0}"at runtime. This is deliberately not anENV HOST=$CODEPRESS_BIND_HOSTalias, which Docker would resolve at build time and freeze, discarding the runtime override.There is no HMR client-port knob to set on this version, and that turns out to be fine:
react-dev-utils@3.0.2'swebpackHotDevClientbuilds its SockJS URL fromwindow.location(protocol + hostname + port +/sockjs-node), so behind the preview proxy it dialswss://<preview-host>/sockjs-nodeon 443 by itself.WDS_SOCKET_PORTis wired fromCODEPRESS_HMR_CLIENT_PORTanyway — inert on this version (it landed inreact-scripts3.4+), but it keeps the runtime contract uniform and survives an upgrade.DANGEROUSLY_DISABLE_HOST_CHECK=trueis set explicitly.react-scripts'webpackDevServer.config.jscomputesdisableHostCheck: !proxy || DANGEROUSLY_DISABLE_HOST_CHECK === 'true', so with noproxyfield inweb/package.jsonthe check is already off today — pinning it means adding aproxyfield later cannot silently start rejecting per-session preview hostnames.BROWSER=nonestopsopenBrowserfrom trying to launch a browser in a headless container.Preview CORS: intentionally no change. The gate requires a backend that serves cross-origin browser clients.
server/fails it on every count:django-cors-headersis absent fromPipfileandINSTALLED_APPS, there is no CORS middleware or setting anywhere,web/srcmakes zero network calls (nofetch/axios, noproxy), andserver/server/urls.pyends in a catch-all renderingindex.htmlfrom the copied React build — i.e. same-origin by construction. Independently, there is no staging config path to scope such an edit to (a singlesettings.pywithDEBUG = True, no settings package, no.env.staging, no CI/deploy config), and adding preview origins to production CORS is exactly what that scoping rule exists to prevent.Social auth: not applicable.
web/has no sign-in flow; its only "auth" is a local redux action toggling a boolean with no network call.samples/auth-web/does contain a GitHub OAuth link, but it is unreferenced sample code with nopackage.jsonand no entry point, and is not part of any runnable frontend.Changes
.codepress/dev-server/recipe.json— schema_version 1, onefrontends[]entry for theweb/create-react-app frontend.codepress/dev-server/Dockerfile.web— thin, dev-mode image onnode:18-bookworm(no bakednode_modules, no source COPY, no CodePress binary)websocket-driver@0.6.5needsprocess.binding('http_parser'), which newer Node removesHOSTfromCODEPRESS_BIND_HOSTandWDS_SOCKET_PORTfromCODEPRESS_HMR_CLIENT_PORTat runtime in the CMDBROWSER=noneandDANGEROUSLY_DISABLE_HOST_CHECK=trueso the dev server runs headless and accepts per-session preview hostnamesstaging_backend_url— no staging URL exists in the repo, and a guess would risk pointing previews at the wrong backendTest plan
docker build -f .codepress/dev-server/Dockerfile.web -t drx-web .— it should succeed and stay thin (nonode_moduleslayer).web/, runyarn install --frozen-lockfile, thenHOST=0.0.0.0 PORT=3000 BROWSER=none npx react-scripts start. ExpectCompiled successfully!and HTTP 200 fromcurl http://127.0.0.1:3000/(the HTML should contain<div id="root"></div>and/static/js/bundle.js).curl http://<container-or-host-ip>:3000/returns HTTP 200 (ss -lntshould show0.0.0.0:3000).curl -H 'Host: abc123-de116f94b7ab06ad.preview.codepress.dev' http://127.0.0.1:3000/returns HTTP 200 and the app HTML.curl http://127.0.0.1:3000/sockjs-node/inforeturns HTTP 200 with"websocket":true.web/src/containers/home/Home.jsand save. The log should print a secondCompiled successfully!, andcurl http://127.0.0.1:3000/static/js/bundle.js | grep <your-string>should find the edit.git grep -i cors -- server/returns nothing, andgit grep -nE 'fetch\(|axios' -- web/srcreturns nothing — confirming the Django app is same-origin with no CORS surface to change.Open items
docker build-ed: Docker is unavailable in this bootstrap environment. Everything the image does was verified directly on a realnode:18.20.8toolchain (install, compile, bind, host check,/sockjs-node, hot reload), but the first CodePress dev-image build is the first time the Dockerfile is executed as written.websocket-driver@0.6.5needsprocess.binding('http_parser'), but the durable fix is to bumpwebsocket-driverto >= 0.7 (which uses a pure-JS parser). The declared range is already open-ended (websocket-driver@>=0.5.1), so a lockfile refresh would satisfy it — after which a newer Node base becomes possible. Out of scope here since it changes application dependency resolution.yarn install --frozen-lockfilewas verified against the currentweb/yarn.lockand succeeded (897 packages). It depends on 2017-era tarballs remaining available on the registry, so an unpublished transitive package would surface as an install failure rather than a config problem.staging_backend_urlin the recipe; nothing in the repo pointed to one.Authors
Generated with CodePress · View the chat session
Co-authored-by: dev@codepress.dev dev@codepress.dev