abiosoft / colima

Container runtimes on macOS (and Linux) with minimal setup
MIT License
18.93k stars 382 forks source link

NodeJS hot reload issue #261

Closed tcastelly closed 10 months ago

tcastelly commented 2 years ago

Kindly jump to https://github.com/abiosoft/colima/issues/261#issuecomment-1484677394 for most recent update.


Hello,

I switched from Docker Desktop to Colima. I noticed an issue with "watcher" on bind volume. I created a repository: https://github.com/shenron/colima-hot-reload-issue

The container is not able to see when a file has been updated. But if I touch the file from the container it works. I guess it's linked to the volume.


I'm using the Macbook Pro M1 Max with:

colima version 0.3.4
git commit: 5a4a70481ca8d1e794677f22524e3c1b79a9b4ae

runtime: docker
arch: aarch64
client: v20.10.14
server: v20.10.11
limactl version 0.9.2
ggoodman commented 2 years ago

The way colima binds host directories into the guest VM means that certain filesystem events are not observed / generated.

You can work around this by using --legacy-watch in nodemon that will fall back to polling instead of the fsevents integration.

tcastelly commented 2 years ago

Hello, thank you for your answer.

The legacy is a workaround, but unfortunately in my use case it's very slow and use a lot of cpu. It's not the best, but for now when I finished to edit my code I "touch" the entrypoint of the application.

docker exec -ti $CONTAINER_ID touch /usr/src/app/src/index.ts

luiz290788 commented 2 years ago

I'm facing the same issue with ts-node-dev. Is this an issue that will eventually be solved by colima or we will never receive the same events when using colima?

abiosoft commented 2 years ago

Is this an issue that will eventually be solved by colima or we will never receive the same events when using colima?

I am working on a workaround taking a similar approach to https://github.com/abiosoft/colima/issues/261#issuecomment-1116466858 while leveraging inotify.

I paused due to some issues with the Go library at the time, but I will revisit it.

matthewdickinson commented 1 year ago

Is this an issue that will eventually be solved by colima or we will never receive the same events when using colima?

I am working on a workaround taking a similar approach to #261 (comment) while leveraging inotify.

I paused due to some issues with the Go library at the time, but I will revisit it.

It would be great to have this feature completed. Is there a work-in-progress branch that I could possibly help continue/test?

alikhanich commented 1 year ago

Hi, is there any progress on that? If you need some help, I may push our development team to help you. We need this so our frontend team could work using colima. Docker for mac is not an option for us)

abiosoft commented 1 year ago

@djirik support for virtiofs mounts is imminent and would be part of the next release.

It has been merged into master upstream in Lima and currently being integrated and tested in Colima, the early results have been quite impressive.

Virtiofs is same tech used by Docker Desktop for the fast volume speeds.

alikhanich commented 1 year ago

@abiosoft thank you very much

alikhanich commented 1 year ago

@abiosoft Hi, do you have an idea when would it be available?

abiosoft commented 1 year ago

@djirik within the next week or two https://github.com/abiosoft/colima/issues/497#issuecomment-1345257182.

You can actually test it now if you can build Colima from source (and brew install --HEAD lima), it's on the support-vz branch.

brew install --HEAD colima
alikhanich commented 1 year ago

@abiosoft hi again, I've succesfully switched to virtiofs on macOs 13. However nodemon still does not see updated files.

colima status
INFO[0000] colima is running using macOS Virtualization.Framework
INFO[0000] arch: aarch64
INFO[0000] runtime: docker
INFO[0000] mountType: virtiofs
INFO[0000] socket: unix:///Users/hacker/.colima/default/docker.sock

--legacy-watch for nodemon doesn't seem to be helping at all. btw we are using nuxt framework, maybe it is something related with it?

abiosoft commented 1 year ago

@abiosoft hi again, I've succesfully switched to virtiofs on macOs 13. However nodemon still does not see updated files.

@djirik hmmm 🤔 did you reset. i.e. colima delete && colima start ?

Is your project something that I can try to reproduce? I have tested with a number of development environments that provides live reload and it has worked fine.

abiosoft commented 1 year ago

@djirik also, kindly confirm lima --version is v0.14.0?

alikhanich commented 1 year ago

@abiosoft yes, I have reset it. Unfortunately, I can not share source code, as it is under NDA.

limactl version 0.14.0

I can ask frontend team if they can make sample project without production code.

alikhanich commented 1 year ago

@abiosoft I have recreated colima again just to be sure, seems like it changed things a bit, now I'm having a lot of permission/access rights errors, I will fix it and return with more feedback.

alikhanich commented 1 year ago

@abiosoft File permissions are hell with virtiofs. I can't even launch node project with volume mounts. Can not figure out how to set user:group in compose file.

abiosoft commented 1 year ago

@abiosoft File permissions are hell with virtiofs. I can't even launch node project with volume mounts. Can not figure out how to set user:group in compose file.

Do you have an idea of the userId in the container? You can check by running id -u in the container. What docker image are you using?

alikhanich commented 1 year ago
version: '3.9'
services:
  nuxt:
    build:
      dockerfile: ../docker/nuxt/Dockerfile
      context: ./source
      target: node_base
    image: ${NUXT_IMAGE_NAME:-localhost/nuxt}:${NUXT_IMAGE_TAG:-latest}
    # user: $DEV_LOCAL_UID:$DEV_LOCAL_GID # here I've tried 501:20, 1000:1000, 501:1000, 0:0
    restart: 'no'
    environment:
      FORCE_COLOR: '1'
      NPM_TOKEN: $NPM_TOKEN
    entrypoint: sh
    command:
      - -xec
      - |-
        npm run npm-auth-repo --loglevel verbose
        npm install --loglevel verbose
        npm run dev --loglevel verbose
    volumes:
      - ./source:/app
      - ./volumes/nuxt/HOME:/home/node
FROM node:16.17.1-alpine AS node_base
WORKDIR /app

ENV HOST 0.0.0.0

EXPOSE 3000

Everytime I'm getting either 243 error from node, or permission denied for creating files in ./volumes/nuxt/HOME. I've also tried chmod +rwx on HOME dir without effect.

abiosoft commented 1 year ago

@djirik as an unrecommended stopgap, the permission denied error should go away if you run chmod -R 777 ./volumes/nuxt/HOME.

Give me a moment, let me try to reproduce your error using the node:16.17.1-alpine image.

abiosoft commented 1 year ago

@djirik out of curiosity, why is /home/node getting mounted?

alikhanich commented 1 year ago

@abiosoft I've tried with 777, but it didn't have any effect. Yes, /home/node is mounted. .npm dir is created and after that it says permission denied)

abiosoft commented 1 year ago

@djirik I am unable to reproduce your permission issues. You can send me an email at the email on my GitHub profile and we can schedule a session to troubleshoot this.

As for the hot reload issue, I can confirm it is not yet fixed with virtiofs. Apparently, I was testing with a dotnet project and it works fine, and thereby assumed it catered for all other environments (including the node stack) as well.

codingluke commented 1 year ago

I can confirm that also on my nodejs project mounted volumes are not "touched" in the container. I encounter no permission issues though.

alikhanich commented 1 year ago

@codingluke what is your node version? can you please share you Dockerfile and docker-compose?

alikhanich commented 1 year ago

@abiosoft I have sent you an email

codingluke commented 1 year ago

@djirik I use the latest 18.12.1. It is a docusaurus/marp project.

node version

alikhanich commented 1 year ago

@codingluke I get it now, you are not mounting sources and NODE_HOME into container, this is why you don't have permission issues I guess.

codingluke commented 1 year ago

correct and I would recommend to only mount the part which is edited locally. I don't see the need to share node_modules and co. For persistence I would use docker volumes. Of course there might be some reason to do it differently.

alikhanich commented 1 year ago

@abiosoft I have skipped mounting /home/node, as it was found unnecessary, but hot reload is still not working :(.

The working behavior is like this:

  1. update file
  2. touch file in colima ssh
  3. refresh is triggered.

Can we steal something from Docker Desktop, so it would work?

abiosoft commented 1 year ago

I assumed virtiofs will enable hot reload out of the box. Since that has now turned out not to be the case, this would be resumed https://github.com/abiosoft/colima/issues/261#issuecomment-1219565057.

igorjacauna commented 1 year ago

If helps, I created this simple repo that reproduce the issue.

The server only restarts if run docker-compose exec app touch index.js like was mentioned here.

codingluke commented 1 year ago

I know it is not directly fitting this thread. However, I thought as a workaround for nodejs projects this could help. Instead of binding the host volumes just sync it.

rmachado-studocu commented 1 year ago

Hey @abiosoft, is it still expectable a solution for the lack of fsevents (based on your comment)?

abiosoft commented 1 year ago

Hey @abiosoft, is it still expectable a solution for the lack of fsevents (based on your comment)?

Yes !

abiosoft commented 1 year ago

Can someone try out the development version brew install --HEAD colima and try the experimental --mount-inotify flag?

colima start --mount-inotify
rmachado-studocu commented 1 year ago

Can someone try out the development version brew install --HEAD colima and try the experimental --mount-inotify flag?

colima start --mount-inotify

I'll try that today! Thanks!

tcastelly commented 1 year ago

Can someone try out the development version brew install --HEAD colima and try the experimental --mount-inotify flag?

colima start --mount-inotify

Hello,

Thank you for the work. The good point, the container detect the change and the application restart. But I don't know how it's possible, it depends how the file has been updated the behavior is not the same.

Touch the file in command line and the application restart in a loop

touch index.js

Update the file with vim seams to work, the application restart once. And finally update the file with Webstorm and the application restart for ever.

For me, to reproduce the issue is easy. I've just cloned the repository in the first comment (https://github.com/shenron/colima-hot-reload-issue) and touch the index.js file.

rmachado-studocu commented 1 year ago

Hey @abiosoft ...

I've tried it but doesn't seem to work 🤔

My colima version: colima version HEAD-30efd6c

My colima start command: colima start --mount "<path1>:w" --mount "<path2>:w" --cpu 4 --memory 8 --vm-type vz --mount-type virtiofs --mount-inotify

Is there something possibly incompatible with the inotify implementation? 🤔

And by not working, it means I have a nextjs container with HMR (Hot Module Reload, sort of a "update page/components on change"). In VSCode I use an extension called "RunOnSave" which allows me to execute docker exec nextjs touch ${relativeFilePath} commands ... that triggers the HMR, as expected.

When running colima with --mount-inotify and without the extension, it doesn't trigger HMR.

henrik242 commented 1 year ago

I've got the same problem, which has been discussed in a different (closed) issue. I'll follow up here instead, since our issues are identical. With the --very-verbose option to colima I can see in daemon.log that a file change is detected, but the edited file isn't touched or hot reloaded.

rmachado-studocu commented 1 year ago

Hmmm first of all, just found out today that the only way to get that daemon.log is by triggering the colima daemon start default --inotify then follow it by colima start ... command

Next, yes I do see the same repeated inotify entries... In my case I'd guess that because the volumes are writable it is triggering a loop, where the host detects the write and sets again the modified datetime to the file written inside of the container, which triggers sort of a loop 🤔

(Next I'm trying without the :w in the mounts)

abiosoft commented 1 year ago

Hmmm first of all, just found out today that the only way to get that daemon.log is by triggering the colima daemon start default --inotify then follow it by colima start ... command

@rmachado-studocu you should never have to do that. It is an internal command and would be blocked from manual executation in future releases. Colima itself uses the command, that's why it's an hidden command and not visible in the cli docs.

You can always view the daemon logs at ~/.colima/default/daemon/daemon.log. You can swap out default with the profile name if using separate profile. It can get very noisy in verbose mode.

tail -f ~/.colima/default/daemon/daemon.log
abiosoft commented 1 year ago

Thanks for your valuable feedbacks, I will iterate on the feature and update the thread accordingly.

rmachado-studocu commented 1 year ago

You can always view the daemon logs at ~/.colima/default/daemon/daemon.log.

Well, that file was never created... only when I had the daemon running it was created. (even with --verbose and --very-verbose)

Thank you for your hard work! 😉

abiosoft commented 1 year ago

Can you try again with brew install --head colima? colima version should be git commit e60e11652f72be1ab18b789ce024f761b5d37629.

The infinite reload issue should be fixed now.

The repo in the first comment now works from my tests https://github.com/shenron/colima-hot-reload-issue). i.e. while editing the file on the host.

...
> watch@1.0.0 watch
> nodemon index.js

[nodemon] 2.0.21
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node index.js`
run on 1337
[nodemon] restarting due to changes...
[nodemon] starting `node index.js`
run on 1337
[nodemon] restarting due to changes...
[nodemon] starting `node index.js`
run on 1337

PS: I do notice that NextJS requires that the webpage is open before live-reload works. It may be same for some other JS frameworks.

tcastelly commented 1 year ago

image

I re-created the vm. I still have the same issue. A simple touch from the host and the application restart for ever.

rmachado-studocu commented 1 year ago

Yeah I have the same ... in my case I have one of the containers running bundling and gulp tasks, which creates a bunch of touch: <filepath>: Operation not permitted lines ...

Also, again, without colima daemon start --inotify I cannot have the daemon.log created 🤷 I have to run that command before the colima start for some reason ...

Lastly, when changing the files, it still doesn't reload ... Btw, a bit more info on my case, I'm using docker-compose to start the containers... would that interfere? (yes the containers' mounts are already with :rw configurations)

abiosoft commented 1 year ago

@rmachado-studocu I think you are doing it wrong.

All you need is the following. Running the daemon directly will have unpredictable behaviour. Maybe reset the VM just to be sure.

colima start --mount-inotify 
abiosoft commented 1 year ago

I re-created the vm. I still have the same issue. A simple touch from the host and the application restart for ever.

Something is off, did you use the touch.sh script?

tcastelly commented 1 year ago

Something is off, did you use the touch.sh script?

I've just executed a:

touch index.js


btw, I'm using m1 architecture, I don't know if it makes a difference.


$ colima ls
default    Running    aarch64    4       4GiB      100GiB    docker
abiosoft commented 1 year ago

@tcastelly I'm also on m1 device.

You can see a video demonstration of the behaviour I am getting, it's working fine for me. https://youtu.be/m3JbS9q7ukg