quart icon indicating copy to clipboard operation
quart copied to clipboard

Hot reload cause a permission denied error in docker container

Open cooolinx opened this issue 1 year ago • 2 comments

Hot reload cause a permission denied error in docker container:

Traceback (most recent call last):
  File "/app/z.py", line 9, in <module>
    app.run()
  File "/usr/local/lib/python3.11/site-packages/quart/app.py", line 864, in run
    restart()
  File "/usr/local/lib/python3.11/site-packages/quart/utils.py", line 164, in restart
    os.execv(executable, [executable] + args)
PermissionError: [Errno 13] Permission denied

How to replicate the bug:

  1. Into a docker container docker run --rm -it -v $PWD:/app python:3.11-alpine ash (mount current directory)
  2. Install pip install quart
  3. Create a app.py, code copy from https://pgjones.gitlab.io/quart/tutorials/quickstart.html
  4. Run python /app/app.py
  5. Try to change app.py and you will see the error

When I try to replicate it outside of docker container, hot-reload works fine.

Environment:

  • Python version: 3.11.9
  • Quart version: 0.19.6

cooolinx avatar Jun 20 '24 12:06 cooolinx

And then when I tried to look into https://github.com/pallets/quart/blob/2fc6d4fa6e3df017e8eef1411ec80b5a6dce25a5/src/quart/utils.py#L133

The executable was /usr/local/bin/python at the beginning and became /app/app.py at the end.

I noticed that hypercorn condition was incorrectly set to true, which cause the executable variable to change.

def restart() -> None:                                                               
    # Restart  this process (only safe for dev/debug)                                
    executable = sys.executable                                                      
    script_path = Path(sys.argv[0]).resolve()                                        
    args = sys.argv[1:]                                                              
    main_package = sys.modules["__main__"].__package__                               
                                                                                     
    if main_package is None:                                                         
        ...              
        else:                                                            
            if script_path.is_file() and os.access(script_path, os.X_OK):  # <-- HERE!
                # hypercorn run:app --reload                             
                executable = str(script_path)       
            else:                                        
                # python run.py                           
                args = [str(script_path), *args]          
    else:                                                 
        ...
                                                            
    os.execv(executable, [executable] + args)               

cooolinx avatar Jun 20 '24 12:06 cooolinx

I hit this as well, wonder if it may be related to this open docker issue: https://github.com/docker/for-mac/issues/5029

tomfleming avatar Jun 25 '24 23:06 tomfleming