tailwindcss CLI no longer works with Docker bind mounts
What version of Tailwind CSS are you using?
4.1.11
What build tool (or framework if it abstracts the build tool) are you using?
@tailwindcss/cli
What version of Node.js are you using?
node:22-slim
What browser are you using?
Chrome
What operating system are you using?
macOS (w/docker)
Reproduction URL
Create a Dockerfile similar to the following:
FROM node:22-slim
WORKDIR /opt/app/
COPY package.json package-lock.json tailwind.css ./
RUN npm install
CMD ["npm", "run", "build-css:dev"]
Create a package.json similar to the following:
{
"scripts": {
"build-css": "tailwindcss -i ./tailwind.css -o ./static/tailwind.css",
"build-css:dev": "tailwindcss -i ./tailwind.css -o ./static/tailwind.css --watch --poll"
},
"devDependencies": {
"@tailwindcss/cli": "^4.1.11",
"@tailwindcss/typography": "^0.5.16",
"tailwind-scrollbar": "^4.0.2",
"tailwindcss": "^4.1.11"
}
}
Create a tailwind.css similar to the following:
@import "tailwindcss" source(none);
@source "templates";
Build and launch the docker image with templates bind mounted into the container.
Modify a file in the templates directory.
Note tailwindcss CLI does not detect the change.
Describe your issue
The --poll option was removed from the tailwindcss CLI and as a result, the --watch option no longer works with docker bind mounts.
The advantage of a bind mount is that we can run the tailwindcss CLI inside a docker container as part of our docker compose file, and the output from the CLI is then available to our app running in a separate container (during development).
However, a bind mount on macOS docker doesn't forward filesystem events, so it's necessary to poll.
The new watcher library being used offers a "brute-force" backend which might help(?), but I don't see a way to select that backend in tailwindcss. https://www.npmjs.com/package/@parcel/watcher
(see also #7725)
Seeing the same problem: source file changes are no longer detected within the docker container, due to the removal of --poll
Have the same issue :( someone a solutions?
If you're encountering this issue, please add a 👍 to the top post. That should help demonstrate how many folks are affected. 😄
As a workaround, I've been using fswatch.
If you're using my example above, place this after the FROM line:
RUN apt-get update \
&& apt-get install -y --no-install-recommends fswatch \
&& rm -rf /var/lib/apt/lists/*
and replace the existing CMD line with this:
CMD npm run build-css; fswatch --monitor=poll_monitor -r -o <paths to monitor...> | xargs -I@ npm run build-css
Replace <paths to monitor...> with the locations you want to watch.
This runs the build once at container startup, then once again each time a file is changed within those paths.
Since the build process is started fresh after each change, I anticipate this will have higher latency than integral polling support.
@DanielBaumert as a workaround I use chokedir: npm install chokidar-cli --save-dev
And then in my package.json I have in one of my projects for example the following:
...
"scripts": {
"tailwind-watch": "SHELL=/bin/bash chokidar '../**/*.{html,js,jsx,ts,tsx}' --ignore '../**/{node_modules,dist,.git}/**' -c 'tailwindcss -i ./index.css -o ../server/static/css/index.css' --initial --polling",
...
}
...
Hey!
Small update: unfortunately @parcel/watcher doesn't support polling like this, and there are open issues, e.g.:
- https://github.com/parcel-bundler/watcher/issues/148
They do have a brute-force backend option, but that doesn't work as expected. They don't implement the subscribe function and crash the process when you try to use that.
Had the same issue, it seems to work with --watch=always:
tailwindcss -i input.css -o output.css --watch=always