🐛 BUG: `wrangler pages dev` hangs when run in docker
Which Cloudflare product(s) does this pertain to?
Wrangler
What version(s) of the tool(s) are you using?
3.65.0
What version of Node are you using?
22.4.1
What operating system and version are you using?
Linux Debian 12 bookworm
Describe the Bug
Observed behavior
I'm using wrangler to run playwright tests locally against a project that will be hosted by Cloudflare Pages. Everything works fine in Mac OS, but when the same code runs in my CI (using docker), wrangler hangs and never returns a response to any requests. Running the same command locally within docker gave me the same result as on my CI.
There is no logs indicating that a request is received by wrangler, and curl just hangs until stopped manually.
In my actual project I use the Playwright official docker image mcr.microsoft.com/playwright:v1.45.1-jammy, but I was able to reproduce it with the node image node:22 without any of my code.
I also tried switching to Cloudflare Workers instead with some dynamic content, but the result was the same.
Expected behavior
For wrangler to either return a response, or to throw an error if something is missing.
Steps to reproduce
- Create a
Dockerfilelocally and copy this content within it.
FROM node:22
RUN mkdir /dist
RUN echo "<html><body>Hello world</body></html>" > /dist/index.html
RUN npm i -g wrangler
ENTRYPOINT [ "wrangler", "pages", "dev", "/dist", "--port", "3000" ]
- Open a terminal, navigate to the folder where the
Dockerfileis, and create a docker container.
docker build --tag wrangler_reproduction .
docker run --name wrangler wrangler_reproduction
- Open a new tab in the same folder and open a shell in the docker container.
docker exec -it wrangler /bin/bash
# In the docker shell
curl -v http://localhost:3000/index.html
- In my case, the curl request just hangs. You can further inspect the wrangler logs to see that there's nothing of interest within it. My own log has messages around missing
.envand.dev.varsfile, but they're debug messages and adding empty ones didn't help.
more /root/.config/.wrangler/logs/ # press tab to auto-complete to the latest log file
Please provide a link to a minimal reproduction
No response
Please provide any relevant error logs
--- 2024-07-17T21:20:13.038Z debug
🪵 Writing logs to "/root/.config/.wrangler/logs/wrangler-2024-07-17_21-20-12_835.log"
---
--- 2024-07-17T21:20:13.038Z debug
Failed to load .env file ".env": Error: ENOENT: no such file or directory, open '.env'
at Object.openSync (node:fs:562:18)
at Object.readFileSync (node:fs:446:35)
at tryLoadDotEnv (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:159217:72)
at loadDotEnv (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:159226:12)
at /usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:202152:20
at /usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:165885:16
at maybeAsyncResult (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:164106:44)
at /usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:165884:14
at /usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:164093:22
at Array.reduce (<anonymous>) {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: '.env'
}
---
--- 2024-07-17T21:20:14.642Z log
⛅️ wrangler 3.65.0
-------------------
---
--- 2024-07-17T21:20:14.643Z debug
No experimental flag store instantiated
---
--- 2024-07-17T21:20:14.643Z debug
Attempted to use flag "JSON_CONFIG_FILE" which has not been instantiated
---
--- 2024-07-17T21:20:14.719Z warn
▲ [WARNING] No compatibility_date was specified. Using today's date: 2024-07-17.
❯❯ Add one to your wrangler.toml file: compatibility_date = "2024-07-17", or
❯❯ Pass it in your terminal: wrangler pages dev [<DIRECTORY>] --compatibility-date=2024-07-17
See https://developers.cloudflare.com/workers/platform/compatibility-dates/ for more information.
---
--- 2024-07-17T21:20:14.720Z log
No Functions. Shimming...
---
--- 2024-07-17T21:20:14.743Z debug
Failed to load .env file "/.dev.vars": Error: ENOENT: no such file or directory, open '/.dev.vars'
at Object.openSync (node:fs:562:18)
at Object.readFileSync (node:fs:446:35)
at tryLoadDotEnv (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:159217:72)
at loadDotEnv (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:159226:12)
at getVarsForDev (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:198833:18)
at getBindings (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:208793:10)
at getResolvedBindings (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:208663:20)
at getBindingsAndAssetPaths (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:208693:15)
at getDevReactElement (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:208326:40)
at startDev (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:208393:60) {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: '/.dev.vars'
}
---
--- 2024-07-17T21:20:14.745Z debug
No folder available to cache configuration
---
--- 2024-07-17T21:20:14.748Z debug
Metrics dispatcher: Dispatching disabled - would have sent {"type":"event","name":"run dev","properties":{"local":true,"usesTypeScript":true}}.
---
--- 2024-07-17T21:20:14.827Z log
⎔ Starting local server...
---
--- 2024-07-17T21:20:15.123Z log
⎔ Reloading local server...
---
--- 2024-07-17T21:20:15.254Z debug
Metrics dispatcher: Dispatching disabled - would have sent {"type":"event","name":"run pages dev","properties":{}}.
---
I'm unfortunately unable to reproduce this—I followed your steps and everything worked fine, with the correct response coming through from the Worker. Could you provide a link to a failing CI job, or try and reproduce this in GitHub Actions?
Thanks for looking into this! I've managed to reproduce it in GitHub Actions, here is a link to the failing CI job (from this PR).
This is the GitHub Actions file:
name: docker
on: pull_request
jobs:
docker:
name: Docker
runs-on: ubuntu-latest
container:
image: node:22
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install wrangler
run: npm i -g wrangler
- name: Run wrangler
run: wrangler pages dev /dist --port 3000 &
- name: Wait for wrangler to be up
run: sleep 20s
- name: Request the page
run: curl -v http://localhost:3000/index.html
timeout-minutes: 1
When removing the Run wrangler command, the curl fails right away, so I believe wrangler is at least somewhat being reached.
I'm seeing similar timeout behaviour when running Playwright tests against a wrangler pages dev server in a container within GitHub Actions (but works fine locally with wrangler). However, when I swap wrangler out for another HTTP server, Playwright does not timeout.
Playwright is launching wrangler as a webServer like this (from playwright.config.ts):
/* Run your local dev server before starting the tests */
webServer: {
command: 'npm start',
url: 'http://localhost:3000/',
reuseExistingServer: !process.env.CI,
},
...
And the npm start command is launching wrangler (from package.json):
"scripts": {
"start": "wrangler pages dev public --port 3000 --compatibility-date=2024-08-27",
"test": "playwright test"
},
Which then times out (log below from GitHub Actions):
Run DEBUG=pw:webserver npx playwright test
2024-08-27T19:42:28.708Z pw:webserver HTTP GET: http://localhost:3000/
2024-08-27T19:42:29.021Z pw:webserver Error while checking if http://localhost:3000/ is available: connect ECONNREFUSED ::1:3000
2024-08-27T19:42:29.021Z pw:webserver Starting WebServer process npm start...
2024-08-27T19:42:29.026Z pw:webserver Process started
2024-08-27T19:42:29.026Z pw:webserver Waiting for availability...
2024-08-27T19:42:29.027Z pw:webserver HTTP GET: http://localhost:3000/
[WebServer]
> [email protected] start
> wrangler pages dev public --port 3000 --compatibility-date=2024-08-27
2024-08-27T19:42:29.329Z pw:webserver Error while checking if http://localhost:3000/ is available: connect ECONNREFUSED ::1:3000
2024-08-27T19:42:29.330Z pw:webserver Waiting 100ms
2024-08-27T19:42:29.433Z pw:webserver HTTP GET: http://localhost:3000/
2024-08-27T19:42:29.735Z pw:webserver Error while checking if http://localhost:3000/ is available: connect ECONNREFUSED ::1:3000
2024-08-27T19:42:29.735Z pw:webserver Waiting 250ms
[WebServer]
⛅️ wrangler 3.72.2 (update available 3.72.3)
-------------------------------------------------------
[WebServer] No Functions. Shimming...
2024-08-27T19:42:29.985Z pw:webserver HTTP GET: http://localhost:3000/
[WebServer] ⎔ Starting local server...
[WebServer] [wrangler-UserWorker:wrn] The latest compatibility date supported by the installed Cloudflare Workers Runtime is "2024-08-21",
but you've requested "2024-08-27". Falling back to "2024-08-21"...
Features enabled by your requested compatibility date may not be available.
Upgrade to `[email protected]` to remove this warning.
[WebServer] [wrangler:inf] Ready on http://localhost:3000
2024-08-27T19:43:00.297Z pw:webserver Error while checking if http://localhost:3000/ is available: Request to http://localhost:3000/ timed out after 30000ms
2024-08-27T19:43:00.298Z pw:webserver Waiting 500ms
2024-08-27T19:43:00.299Z pw:webserver Error while checking if http://localhost:3000/ is available: socket hang up
2024-08-27T19:43:00.799Z pw:webserver HTTP GET: http://localhost:3000/
Error: Timed out waiting 60000ms from config.webServer.
2024-08-27T19:43:29.074Z pw:webserver Error while checking if http://localhost:3000/ is available: read ECONNRESET
2024-08-27T19:43:29.074Z pw:webserver Waiting 1000ms
Error: Process completed with exit code 1.
If I swap wrangler out for another HTTP server, Playwright can connect fine (I want to use Wrangler in order to test my CF environment more accurately and things like headers/redirect config):
"scripts": {
"start": "npx http-server -p 3000",
"test": "playwright test"
},
Lot of snippets so apologies if it's unclear. I can share an example repo if that's going to be clearer.
I see the same behavior in a Docker container locally.
My image is node:18
# npx wrangler dev --port=9110 --show-interactive-dev-session=false &
⛅️ wrangler 3.78.2
-------------------
Your worker has access to the following bindings:
- <omitted>
⎔ Starting local server...
[wrangler:inf] Ready on http://localhost:9110
# curl --verbose localhost:9110
* Trying 127.0.0.1:9110...
* Connected to localhost (127.0.0.1) port 9110 (#0)
> GET / HTTP/1.1
> Host: localhost:9110
> User-Agent: curl/7.88.1
> Accept: */*
>
It just hangs.
I saw a few places around the web mentioning to make sure WRANGLER_SEND_METRICS env variable was false, but it doesn't make a difference.
# echo $WRANGLER_SEND_METRICS
false
Will using the --ip option make it accessible?
$ wrangler pages dev public --port 3000 --ip=0.0.0.0
@dijitali For playwright tests, specifying the port only helped fixed the issue (DO NOT SPECIFY URL i.e. localhost)
I am seeing the same issue on a workers project, running: npx wrangler dev. the server appears to start, but making request from within in the container: curl http://localhost:8787 just hangs. If you exit the wrangler dev server curl exits immediately with the error: curl: (56) Recv failure: Connection reset by peer.
Running with --ip=0.0.0.0 npx wrangler dev --ip=0.0.0.0 seems to work around the issue -- curl http://localhost:8787 succeeds in that case.
I see the same issue when going through the oath login flow using npx wrangler deploy -- the https://dash.cloudflare.com URL appears in the terminal, I go to that URL, and click allow, then my browser just spins as it tries redirect to the localhost (my machine is set to map the localhost:8976 to the container's port 8976), and eventually my browser says that it's unable to load http://localhost:8976/.... and the wrangler deploy times out in the terminal.
I have not been able to find a similar work around for this issue.
Edit: Found a workaround for the OAuth callback -- before running something that requires authorization (such as npx wrangler deploy), run npx wrangler login --callback-host='0.0.0.0' which will trigger the oauth flow -- and, assuming you've setup port forward from localhost:8787 to 8787 in your container, it seems to work.
npx wrangler dev --ip=0.0.0.0 doesn't work all the time for me, switching it to npx wrangler dev --ip=127.0.0.1 seemed to bring the worker back to life.
had exact same problem. adding --ip=127.0.0.1 solved the problem but this was not happening on a different machine with different distribution of Linux. so I'm wondering if it is a problem of environment setup or the wrangler.
Just chiming in that this is happening on WSL Ubuntu for me when using Wrangler for local development of workers on Windows. Unfortunately I'm stuck in WSL due to being on an ARM64 processor for now. Seems like a random chance of a hang after changing a file during the reload.
Just tried this with Wrangler 4.0.0 and I appear to have the same issue. Adding a --log-level debug floods the console with exceptions such as:
workers util.c++ 333: info: exception = kj/async-io-unix.c++: 1524: disconnected: connect(): Connection refused
As mentioned in the other comments, adding --ip=127.0.0.1 seems to magically fix the problem.
@lrapoport-cf note that this problem is not restricted to pages and impacts workers/wrangler generally. Running the exact same worker outside of Docker works fine without adding the --ip=127.0.0.1 argument.