docusaurus icon indicating copy to clipboard operation
docusaurus copied to clipboard

Docusaurus chooses port 3000 even if it is busy

Open JonnyBurger opened this issue 2 years ago • 6 comments

Have you read the Contributing Guidelines on issues?

Prerequisites

  • [X] I'm using the latest version of Docusaurus.
  • [ ] I have tried the npm run clear or yarn clear command.
  • [ ] I have tried rm -rf node_modules yarn.lock package-lock.json and re-installing packages.
  • [ ] I have tried creating a repro with https://new.docusaurus.io.
  • [ ] I have read the console error message carefully (if applicable).

Description

On macOS, consider the following script server.js:

const http = require("http");

const port = 3000;

const requestListener = function (req, res) {
    res.writeHead(200);
    res.end("My first server!");
};

const server = http.createServer(requestListener);

server.listen(port,  () => {
    console.log(`Server is running on http://localhost:${port}`);
});

Run it using node server.js. Then start a Docusaurus project (running on v2.1.0 in my case). The documentation server will start on port 3000, although it is busy. If you then open Docusaurus in Chrome:

image it opens my server.

however, if I use curl, I get the docusaurus page!

Screenshot 2022-10-11 at 11 52 58

If my server passes a host:

- server.listen(port,  () => {
+ server.listen(port, "localhost",  () => {

then Docusaurus will correctly identify that the port is busy and asks if I want to choose another port. Nonetheless I see it as a bug in Docusaurus or one of it's dependencies.

Possible solution

Although used by less people, this logic for finding a free port works now in Remotion without bug reports coming in: https://github.com/remotion-dev/remotion/blob/main/packages/renderer/src/get-port.ts

I am happy to chat on Discord how to investigate it together!

Reproducible demo

No response

Steps to reproduce

As above

Expected behavior

Busy port detection kicks in and asks if a different port should be used

Actual behavior

Server gets started and a conflict is created

Your environment

  • Docusaurus version used: v2.1.0
  • Environment name and version (e.g. Chrome 89, Node.js 16.4): Node 16.7
  • Operating system and version (e.g. Ubuntu 20.04.2 LTS): macOS

Self-service

  • [X] I'd be willing to fix this bug myself.

JonnyBurger avatar Oct 11 '22 09:10 JonnyBurger

I've discovered the same recently. It doesn't seem to reproduce with two Docusaurus servers—only when one port is running something else.

Josh-Cena avatar Oct 11 '22 17:10 Josh-Cena

@Josh-Cena Correct, the explanation for this is that Docusaurus does .listen(3000, "localhost"), which doesn't cause this problem.

JonnyBurger avatar Oct 12 '22 08:10 JonnyBurger

Although used by less people, this logic for finding a free port works now in Remotion without bug reports coming in: remotion-dev/remotion@main/packages/renderer/src/get-port.ts

😄

As far as I remember this code was copied from CRA in https://github.com/facebook/docusaurus/issues/3005 and we use the detect-port library: https://github.com/node-modules/detect-port

It seems to use a similar approach of attempting to create the server: https://github.com/node-modules/detect-port/blob/master/lib/detect-port.js#L101

Maybe we don't pass it the correct params? Or maybe it's worth opening a bug in that lib directly so that the whole ecosystem benefits from a fix?

If anyone wants to investigate if detect-port has a bug or not that would be convenient :)

slorber avatar Oct 12 '22 10:10 slorber

Dug deper:

detect-port-alt uses 4 steps to determine the port (see their comments): https://unpkg.com/[email protected]/lib/detect-port.js

detect-port uses only 3steps to determine the port, and the logic is significantly different: https://unpkg.com/[email protected]/lib/detect-port.js

  • Facebooks passes 0.0.0.0 as hostname parameter to detect-port-alt, while Docusaurus uses 127.0.0.1 as hostname parameter

I found that if Docusaurus switches to detect-port-alt, and uses 0.0.0.0 instead, it also detects the busy port like CRA. Only tested on macOS though.

JonnyBurger avatar Oct 12 '22 11:10 JonnyBurger

Thanks 💯

If only someone could just create a shared package that works for everyone 😅 looks like CRA is using detect-port-alt now (published by Dan Abramov, no fork repo linked 😓 ). That probably was for a good reason.

Interesting related CRA issues:

  • https://github.com/facebook/create-react-app/pull/2126 (led to forking)
  • https://github.com/facebook/create-react-app/pull/2209 (@timer/detect-port introduction, before renaming it to detect-port-alt)
  • https://github.com/facebook/create-react-app/issues/12417 (we should be able to run 2 Docusaurus with different hosts on same port?)

slorber avatar Oct 12 '22 15:10 slorber

Docusaurus defaults to binding to the loopback interface, which does not conflict with another process attempting to listening on all interfaces.

The dev tool will detect a conflict in this case if the host is set to 0.0.0.0 :

$ npx docusaurus start -h 0.0.0.0
✔ [WARNING] Something is already running on port 3000. Probably:
  `node server.js` (pid 44444) in "/private/tmp"

Perhaps the default should be changed? Note that 0.0.0.0 will expose the dev server to other devices. This is arguably a good thing since you can preview changes on your phone if it is on the same network

SheetJSDev avatar Jan 06 '23 16:01 SheetJSDev

Here's what works for me now:

npm script:

docusaurus start --port $(detect 3000)

and have detect-port installed as a dev dependency

Not sure whether this will work on Windows with the expansion.

I imagine that upgrading to latest detect-port could fix it? Although I see next dev being run when docusaurus starts.

xixixao avatar Aug 11 '23 21:08 xixixao

PR submitted (https://github.com/facebook/docusaurus/issues/8202)

I will await a review.

jack-robson avatar Oct 20 '23 14:10 jack-robson