docusaurus
docusaurus copied to clipboard
Docusaurus chooses port 3000 even if it is busy
Have you read the Contributing Guidelines on issues?
- [X] I have read the Contributing Guidelines on issues.
Prerequisites
- [X] I'm using the latest version of Docusaurus.
- [ ] I have tried the
npm run clear
oryarn 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:

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

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.
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 Correct, the explanation for this is that Docusaurus does .listen(3000, "localhost")
, which doesn't cause this problem.
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 :)
Dug deper:
- Docusaurus uses
[email protected]
while Facebook uses[email protected]
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
ashostname
parameter todetect-port-alt
, while Docusaurus uses127.0.0.1
ashostname
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.
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 todetect-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?)
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
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.
PR submitted (https://github.com/facebook/docusaurus/issues/8202)
I will await a review.