bacon icon indicating copy to clipboard operation
bacon copied to clipboard

File watcher doesn't work on mounted files on Docker (Windows host)

Open casab opened this issue 11 months ago • 9 comments

I am running bacon --headless run-long on a docker dev container to hot reload. Container is using volume mounted from Windows host and bacon should be watching the files on that volume. Running on windows and running on linux works fine. But for some reason file watcher doesn't seem to work on this specific case.

I think bacon checks for the file changes by listening inotify events. Is there any option that uses polling instead that I have missed?

casab avatar Jan 21 '25 20:01 casab

Is there any option that uses polling instead that I have missed?

No, there's none today.

Canop avatar Jan 21 '25 20:01 Canop

I checked out how notify-rs defines watchers. And how bacon uses notify. RecommendedWatcher fallsback to PollWatcher when the target is not available. Also it's advised to use PollWatcher in such cases; https://docs.rs/notify/latest/notify/#network-filesystems

I found similar issues around. Especially this;

https://github.com/notify-rs/notify/issues/254

So, I tried modifying Watcher in src/watcher.rs. I have replaced RecommendedWatcher with PollWatcher, with this config;

Config::default()
                .with_poll_interval(Duration::from_secs(5))
                .with_compare_contents(true)

Still didn't work. I thought if I could be sure that PollWatcher works for every system. I could just add a new option like --poll <seconds`> or add some logic that checks for wsl. But, oh well...

casab avatar Jan 21 '25 22:01 casab

I was also encountering this exact same problem with a mac host today.

tmanuszak avatar Jan 22 '25 02:01 tmanuszak

When watching files in WSL on a 9p-mount (like the host C: drive is) inotify is not supported by WSL ( https://github.com/microsoft/WSL/issues/4739 ). This makes it impossible to use bacon in WSL /c/ drive while editing the source code on the Windows host C: drive.

An option for a polling watcher would really help here.

mbuesch avatar Jun 03 '25 19:06 mbuesch

@casab @tmanuszak @mbuesch Can you provide feedback on https://github.com/Canop/bacon/pull/365 ?

Canop avatar Jun 04 '25 11:06 Canop

@casab @tmanuszak @mbuesch Can you provide feedback on #365 ?

I tried running what's in #365 but it does not seem to work for my use case. I am running bacon my-test-job (see below) in a container based off the official Rust image. The container is using a volume mounted from my Mac host and bacon should be watching the files on that volume but the file watcher does not seem to be working still. I am able to get this working when running bacon on my Mac.

Here is a snippet of my bacon.toml file

[jobs.my-test-job]
command = [
    "cargo", "run", "--bin", "testing"
]
need_stdout = true
allow_warnings = true
background = false
on_change_strategy = "kill_then_restart"

DMallare avatar Jun 11 '25 21:06 DMallare

@casab @tmanuszak @mbuesch Can you provide feedback on #365 ?

I tried running what's in #365 but it does not seem to work for my use case. I am running bacon my-test-job (see below) in a container based off the official Rust image. The container is using a volume mounted from my Mac host and bacon should be watching the files on that volume but the file watcher does not seem to be working still. I am able to get this working when running bacon on my Mac.

Here is a snippet of my bacon.toml file

[jobs.my-test-job]
command = [
    "cargo", "run", "--bin", "testing"
]
need_stdout = true
allow_warnings = true
background = false
on_change_strategy = "kill_then_restart"

Similar issues on similar setup for me on mac host. Something interesting is that for me it notices changes in the bacon.toml file instantly, but never seems to with the rs files. After trying a bunch of configurations, I did end up having luck with using watch in the compose file to sync the files, which I'd have thought would be redundant.

services:
  rust:
    ...
    develop:
      watch:
        - action: sync
          path: ./rust/web/src
          target: /app/web/src

Feels like a workaround, and I was also intrigued that it would see the toml file change 🙃

jsnelling avatar Sep 27 '25 22:09 jsnelling

@jsnelling can you provide the exact reproduction info (a Dockerfile, maybe) ? I'll try on my mac and see if I can tune the watcher.

Canop avatar Sep 28 '25 05:09 Canop

@jsnelling can you provide the exact reproduction info (a Dockerfile, maybe) ? I'll try on my mac and see if I can tune the watcher.

@Canop Hi! Yes! I encountered it when experimenting with a devcontainers workflow. So there was a base dockerfile for the devcontainer to edit in and run bacon test in the bottom terminal, and one for the rust service to run bacon run-long and serve the rust api to the other containers.

# Dockerfile
FROM mcr.microsoft.com/devcontainers/rust

RUN cargo install --locked bacon 

ENV DUCKDB_VERSION=1.4.0
RUN wget https://github.com/duckdb/duckdb/releases/download/v1.4.0/libduckdb-linux-arm64.zip \
  && unzip libduckdb-linux-arm64.zip -d /tmp/libduckdb\
  && mkdir -p /usr/local/include /usr/local/lib \
  && mv /tmp/libduckdb/duckdb.* /usr/local/include/ \
  && mv /tmp/libduckdb/libduckdb.so /usr/local/lib/ \
  && rm -rf /tmp/libduckdb libduckdb-linux-arm64.zip \
  && ldconfig /usr/local/lib/libduckdb.so

ENV DUCKDB_LIB_DIR=/usr/local/lib
ENV DUCKDB_INCLUDE_DIR=/usr/local/include
# Dockerfile
FROM rust:1.90-alpine3.22

RUN apk add --no-cache \
  bash \
  cmake \
  curl \
  g++ \
  gcc \
  git \ 
  make \
  musl-dev \
  ninja \
  openssl-dev \
  pkgconf

WORKDIR /app

RUN cargo install --locked bacon 

ENV DUCKDB_VERSION=1.4.0
RUN wget https://github.com/duckdb/duckdb/releases/download/v1.4.0/libduckdb-linux-arm64.zip \
  && unzip libduckdb-linux-arm64.zip -d /tmp/libduckdb\
  && mkdir -p /usr/local/include /usr/local/lib \
  && mv /tmp/libduckdb/duckdb.* /usr/local/include/ \
  && mv /tmp/libduckdb/libduckdb.so /usr/local/lib/ \
  && rm -rf /tmp/libduckdb libduckdb-linux-arm64.zip \
  && ldconfig /usr/local/lib/libduckdb.so

ENV DUCKDB_LIB_DIR=/usr/local/lib
ENV DUCKDB_INCLUDE_DIR=/usr/local/include

EXPOSE 8000

CMD ["cargo", "run", "--bin", "web"]

then inside the container there was a basic bacon.toml from bacon --init that I tested different things like explicit watches but ended at the default. docker compose brought up the rust container and gave it a different command

# docker-compose.yml
services:
  rust: 
    build:
      context: ./rust
      dockerfile: Dockerfile
    environment: 
      CARGO_HOME: /cargo
    ports:
      - "8000:8000"
    volumes:
      - ./rust:/app
      - rust-target:/app/target
      - rust-volume:/cargo
    command: ["bacon", "--headless", "run-long"]
#    develop:
#      watch:
#        - action: sync
#          path: ./rust/src
#          target: /app/src

and VSCode brought up the devcontainer what I found was that with these files

$ tree rust/ -L 2
rust/
├── bacon.toml
├── Cargo.lock
├── Cargo.toml
├── Dockerfile
├── macros
│   ├── Cargo.toml
│   └── src
├── Rocket.toml
├── src
│   └── main.rs
└── target
    └── debug

that i saved the bacon.toml file from vscode window connected to the devcontainer, that the rust container with bacon watching would instantly start recompiling, but if I did the same thing with the src/main.rs there was no response and it didn't recompile. For the bacon test running side the same devcontainer that vscode was connected to and saving in, saving the main.rs did rerun the tests. When I uncomment the watch configuration in the docker-compose related to the container that's running cargo --headless run-long then saving a .rs file will trigger bacon to rebuild the api I hope this helps! Thank you!!

jsnelling avatar Sep 28 '25 16:09 jsnelling