codekitchen / dinghy

faster, friendlier Docker on OS X. Deprecated.
MIT License
2.12k stars 109 forks source link

Issues listening for file changes #264

Open ghost opened 6 years ago

ghost commented 6 years ago

Hi there,

First of all wanted to really give my thanks to you for this amazing tool! It really made my life easier using docker under macOs.

Sadly though I'm opening this issue because I am looking for a fix for the following scenario.

I am developing in Go and I'm using this https://github.com/githubnemo/CompileDaemon in order to listen to file changes and automatically rebuild my go binary.

However when I boot up dinghy and sequently my Go container every change I make in my IDE will not get picked up by the daemon. But when I don't use dinghy and just use native docker for mac without any magic the daemon works correctly.

Any idea what kind of fix I can apply to solve this annoying issue? Cuz as of now it kind of forces me to always skip on using dinghy for my Go projects.

I really appreciate any help you could provide!

Some additional info:

Dinghy Version 4.6.1 Virtualbox Version 5.1.30 r118389 (Qt5.6.3) Boot2Docker version 17.09.1-ce, build HEAD : e7de9ae - Fri Dec 8 19:41:36 UTC 2017 Docker version 17.09.1-ce, build 19e2cf6 Firewall deactivated

dinghy-FsEvents.output is empty

PS. I should probably mention as well that the file actually does update correctly inside the container if I modify it in my IDE, it just doesn't trigger a rebuild event for the daemon.

Running fsevents_to_vm start ./ manually I get this output:

/Library/Ruby/Gems/2.3.0/gems/net-ssh-2.9.4/lib/net/ssh/transport/session.rb:67:in `initialize': Object#timeout is deprecated, use Timeout.timeout instead.
Error sending event: Connection refused - connect(2) for nil port 22
    /Library/Ruby/Gems/2.3.0/gems/net-ssh-2.9.4/lib/net/ssh/transport/session.rb:70:in `initialize'
    /Library/Ruby/Gems/2.3.0/gems/net-ssh-2.9.4/lib/net/ssh/transport/session.rb:70:in `open'
    /Library/Ruby/Gems/2.3.0/gems/net-ssh-2.9.4/lib/net/ssh/transport/session.rb:70:in `block in initialize'
    /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/timeout.rb:74:in `timeout'
    /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/timeout.rb:120:in `timeout'
    /Library/Ruby/Gems/2.3.0/gems/net-ssh-2.9.4/lib/net/ssh/transport/session.rb:67:in `initialize'
    /Library/Ruby/Gems/2.3.0/gems/net-ssh-2.9.4/lib/net/ssh.rb:207:in `new'
    /Library/Ruby/Gems/2.3.0/gems/net-ssh-2.9.4/lib/net/ssh.rb:207:in `start'
    /Library/Ruby/Gems/2.3.0/gems/fsevents_to_vm-1.1.3/lib/fsevents_to_vm/ssh_emit.rb:24:in `ssh'
    /Library/Ruby/Gems/2.3.0/gems/fsevents_to_vm-1.1.3/lib/fsevents_to_vm/ssh_emit.rb:14:in `event'
    /Library/Ruby/Gems/2.3.0/gems/fsevents_to_vm-1.1.3/lib/fsevents_to_vm/cli.rb:30:in `block in start'
    /Library/Ruby/Gems/2.3.0/gems/fsevents_to_vm-1.1.3/lib/fsevents_to_vm/watch.rb:14:in `block (2 levels) in run'
    /Library/Ruby/Gems/2.3.0/gems/fsevents_to_vm-1.1.3/lib/fsevents_to_vm/watch.rb:12:in `each'
    /Library/Ruby/Gems/2.3.0/gems/fsevents_to_vm-1.1.3/lib/fsevents_to_vm/watch.rb:12:in `block in run'
    /Library/Ruby/Gems/2.3.0/gems/rb-fsevent-0.9.8/lib/rb-fsevent/fsevent.rb:45:in `run'
    /Library/Ruby/Gems/2.3.0/gems/fsevents_to_vm-1.1.3/lib/fsevents_to_vm/watch.rb:17:in `run'
    /Library/Ruby/Gems/2.3.0/gems/fsevents_to_vm-1.1.3/lib/fsevents_to_vm/cli.rb:24:in `start'
    /Library/Ruby/Gems/2.3.0/gems/thor-0.19.4/lib/thor/command.rb:27:in `run'
    /Library/Ruby/Gems/2.3.0/gems/thor-0.19.4/lib/thor/invocation.rb:126:in `invoke_command'
    /Library/Ruby/Gems/2.3.0/gems/thor-0.19.4/lib/thor.rb:369:in `dispatch'
    /Library/Ruby/Gems/2.3.0/gems/thor-0.19.4/lib/thor/base.rb:444:in `start'
    /Library/Ruby/Gems/2.3.0/gems/fsevents_to_vm-1.1.3/exe/fsevents_to_vm:4:in `<top (required)>'
    /usr/local/bin/fsevents_to_vm:22:in `load'
    /usr/local/bin/fsevents_to_vm:22:in `<main>'
cayter commented 6 years ago

@nrko I bumped into the same issue when trying to use dinghy with go framework like buffalo. However, I workaround it by using gin reload utility. Here is the solution https://github.com/gobuffalo/buffalo/issues/620, hope that helps.

codekitchen commented 6 years ago

The fvevents_to_vm error is because you need to pass in more flags to get it running manually, I'll update the README for that project.

I'm not familiar with CompileDaemon but it looks like it uses inotify underneath to watch to file changes, so I'm a little surprised it doesn't "just work". Just to make sure, is the code you're editing in your HOME folder somewhere? Dinghy only syncs and watches the user's home dir.

If you install inotifywait in the same container and run inotifywait /your/code/dir, does it output an event when you modify the file? That'd at least show us whether inotify is generating the event as expected.

ghost commented 6 years ago

@cayter Thanks for that! Altho I would prefer not to do something so "hacky".:)

I confirm that the code I am editing is in my HOME folder.

I just installed inotifywait inside the container and ran the command but I am not getting anything at all while modifying the files.

Setting up watches.
Watches established.

That's all I have unfortunately.

I also ran the fsevents_to_vm start --ssh-identity-file ~/.docker/machine/machines/dinghy/id_rsa --ssh-ip $(dinghy ip) ./

and now I only get this:

/Library/Ruby/Gems/2.3.0/gems/net-ssh-2.9.4/lib/net/ssh/transport/session.rb:67:in `initialize': Object#timeout is deprecated, use Timeout.timeout instead.
/Library/Ruby/Gems/2.3.0/gems/net-ssh-2.9.4/lib/net/ssh/transport/session.rb:84:in `initialize': Object#timeout is deprecated, use Timeout.timeout instead.
codekitchen commented 6 years ago

Hm then inotify events aren't even getting triggered, this may be difficult to debug remotely. Are you able to share your docker container config, either the docker run command or the docker-compose config as applicable?

How about this minimal test from the fsevents_to_vm readme? You don't need to run fsevents_to_vm manually for this:

docker run --rm -it -v $HOME:/fstest ubuntu:trusty
# inside the container
apt-get update && apt-get install -y inotify-tools
inotifywait /fstest

Then touch $HOME/test on your host computer from another shell, and inotifywait inside the container should emit an event for that touch, it should look like /fstest/ ATTRIB test

codekitchen commented 6 years ago

Oh also let's make sure the daemon is still running and didn't die due to https://github.com/codekitchen/dinghy/issues/262 -- do you see a fsevents_to_vm process running on your host computer when dinghy is running? dinghy status will tell you.

ghost commented 6 years ago

I know it's really hard to debug like this remotely and I really appreciate the help!

So I did the fsevents_to_vm minimal test and I correctly got the output /fstest/ ATTRIB test. Then that got me curious and I went back to my original container and again started inotifywait ./ inside of it and outside the container I simply did the same test with touch test in the directory of the project and I correctly got ./ ATTRIB test as the output in the container. But unfortunately I get no events if I just edit the files. All this time the fsevents_to_vm process was correctly running on my host computer.

My Dockerfile config is as follows:

FROM golang:alpine

ENV APP_DIR $GOPATH/src/github.com/nrko/project
ENV CT_COMMAND --version

# install go dep
RUN apk update \
    && apk add ca-certificates git \
    && go get -u github.com/golang/dep/cmd/dep

# Install dependencies
RUN apk add --update alpine-sdk \
    && rm -rf /var/cache/apk/*

# Setup file system
RUN mkdir -p ${APP_DIR} \
    && mkdir /var/log/project \
    && chmod 755 /var/log/project

COPY . ${APP_DIR}
WORKDIR ${APP_DIR}

RUN make deps
RUN make deps-dev

CMD CompileDaemon -build="make install" -command="ct ${CT_COMMAND}"

I tried to edit the file with vim inside my host computer while in the container I had inotifywait ./ and again it picked it up however the CompileDaemon still didn't pick up anything to rebuild. Also if I edit it inside Sublime Text or GoLand it doesn't pick up anything .

I'm not sure if it helps but my GoLand IDE keeps asking me if I want to keep memory changes or load file system changes when it has to save the file. Memory changes would be my actual changes and file system changes would be the file exactly like before. All of this does not happen if I don't use dinghy.

codekitchen commented 6 years ago

Oh OK that's good info thanks. With that extra debug info, my best guess is that this is the same issue covered in https://github.com/codekitchen/fsevents_to_vm/issues/7 , which I had honestly forgotten about until I just started looking through the project again, I wish I'd made that connection sooner.

Basically, right now fsevents_to_vm just modifies the mtime of the file in the VM, no matter what actually happened on the host, and some apps don't listen to ATTRIB inotify events, only actual write events.

I still think this is probably fixable, I just haven't had a chance to dig into it yet. It sounds like it is a fairly widespread issue though, so I'll try to schedule some time for that soon.

ghost commented 6 years ago

That's great news if it can be fixed! I really appreciate you taking the time to look into this!

Altho I'm not very familiar with the fsevents_to_vm codebase let me know if I can help somehow.

codekitchen commented 6 years ago

I've got a WIP branch that simulates WRITE_CLOSE events, which appears to be enough to fix that original filed issue.

However, it doesn't look like that's good enough for the inotify.go library (and thus CompileDaemon), which doesn't watch for WRITE_CLOSE and requires an actual MODIFY event. The only way to get a modify event is to actually modify the file in the docker VM, which is of course a lot more problematic... I'll have to think about it for a while. I'm not sure what the solution could be yet.