miguelgrinberg/flasky

17d -- docker container doesn't run locally -- import main error

NoLandMen496 opened this issue · 4 comments

1 - Problem

Miguel your book and github support are awesome and unique. Thanks.
I cloned and used your code from 17d locally, built an image successfully, but I can't run the docker container because it shuts down due to an ImportError: cannot import name name 'main'.

My docker is Docker version 20.10.12, build e91ed57. I have used your exact code & dependencies so you can replicate the problem. You Dockerfile (maybe) has a error on env variable

ENV FLASK_CONFIG production 

I tried with production and docker, the error was always the same.

The steps 2, 3 & 4 show the traces.

Step 2 - Image is built without errors

$ docker build -t flasky:latest .
Sending build context to Docker daemon  189.4kB
Step 1/14 : FROM python:3.6-alpine
3.6-alpine: Pulling from library/python
59bf1c3509f3: Pull complete 
8786870f2876: Pull complete 
acb0e804800e: Pull complete 
52bedcb3e853: Pull complete 
b064415ed3d7: Pull complete 
Digest: sha256:579978dec4602646fe1262f02b96371779bfb0294e92c91392707fa999c0c989
Status: Downloaded newer image for python:3.6-alpine
...
  Running setup.py install for SQLAlchemy: started
    Running setup.py install for SQLAlchemy: finished with status 'done'
  Running setup.py install for MarkupSafe: started
    Running setup.py install for MarkupSafe: finished with status 'done'
  Running setup.py install for Mako: started
    Running setup.py install for Mako: finished with status 'done'
  Running setup.py install for python-editor: started
    Running setup.py install for python-editor: finished with status 'done'
  Running setup.py install for alembic: started
    Running setup.py install for alembic: finished with status 'done'
  Running setup.py install for blinker: started
    Running setup.py install for blinker: finished with status 'done'
  Running setup.py install for dominate: started
    Running setup.py install for dominate: finished with status 'done'
  Running setup.py install for itsdangerous: started
    Running setup.py install for itsdangerous: finished with status 'done'
  Running setup.py install for visitor: started
    Running setup.py install for visitor: finished with status 'done'
  Running setup.py install for Flask-Bootstrap: started
    Running setup.py install for Flask-Bootstrap: finished with status 'done'
  Running setup.py install for Flask-Mail: started
    Running setup.py install for Flask-Mail: finished with status 'done'
  Running setup.py install for Flask-Script: started
    Running setup.py install for Flask-Script: finished with status 'done'
  Running setup.py install for Flask-Migrate: started
    Running setup.py install for Flask-Migrate: finished with status 'done'
  Running setup.py install for Flask-Moment: started
    Running setup.py install for Flask-Moment: finished with status 'done'
  Running setup.py install for WTForms: started
    Running setup.py install for WTForms: finished with status 'done'
  Running setup.py install for Markdown: started
    Running setup.py install for Markdown: finished with status 'done'
...
Successfully built 252b41828261
Successfully tagged flasky:latest

Step 3 - Container runs with no apparent error, but stops immediately

docker run --name flasky -d -p 8000:5000 -e SECRET_KEY=hidekey -e MAIL_USERNAME=example@example.com -e MAIL_PASSWORD=hidepassword flasky:latest

Step 4 - Docker logs say -- ImportError: cannot import name 'main'

$ docker logs flasky
Traceback (most recent call last):
  File "/home/flasky/venv/bin/flask", line 11, in <module>
    sys.exit(main())
  File "/home/flasky/venv/lib/python3.6/site-packages/flask/cli.py", line 513, in main
    cli.main(args=args, prog_name=name)
  File "/home/flasky/venv/lib/python3.6/site-packages/flask/cli.py", line 380, in main
    return AppGroup.main(self, *args, **kwargs)
  File "/home/flasky/venv/lib/python3.6/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/home/flasky/venv/lib/python3.6/site-packages/click/core.py", line 1061, in invoke
    cmd_name, cmd, args = self.resolve_command(ctx, args)
  File "/home/flasky/venv/lib/python3.6/site-packages/click/core.py", line 1100, in resolve_command
    cmd = self.get_command(ctx, cmd_name)
  File "/home/flasky/venv/lib/python3.6/site-packages/flask/cli.py", line 351, in get_command
    rv = info.load_app().cli.get_command(ctx, name)
  File "/home/flasky/venv/lib/python3.6/site-packages/flask/cli.py", line 237, in load_app
    rv = locate_app(self.app_import_path)
  File "/home/flasky/venv/lib/python3.6/site-packages/flask/cli.py", line 90, in locate_app
    __import__(module)
  File "/home/flasky/flasky.py", line 15, in <module>
    app = create_app(os.getenv('FLASK_CONFIG') or 'default')
  File "/home/flasky/app/__init__.py", line 36, in create_app
    from .main import main as main_blueprint
ImportError: cannot import name 'main'
[2021-12-29 14:34:51 +0000] [1] [INFO] Starting gunicorn 19.7.1
[2021-12-29 14:34:51 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)
[2021-12-29 14:34:51 +0000] [1] [INFO] Using worker: sync
[2021-12-29 14:34:51 +0000] [14] [INFO] Booting worker with pid: 14
[2021-12-29 14:34:51 +0000] [14] [ERROR] Exception in worker process
Traceback (most recent call last):
  File "/home/flasky/venv/lib/python3.6/site-packages/gunicorn/arbiter.py", line 578, in spawn_worker
    worker.init_process()
  File "/home/flasky/venv/lib/python3.6/site-packages/gunicorn/workers/base.py", line 126, in init_process
    self.load_wsgi()
  File "/home/flasky/venv/lib/python3.6/site-packages/gunicorn/workers/base.py", line 135, in load_wsgi
    self.wsgi = self.app.wsgi()
  File "/home/flasky/venv/lib/python3.6/site-packages/gunicorn/app/base.py", line 67, in wsgi
    self.callable = self.load()
  File "/home/flasky/venv/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 65, in load
    return self.load_wsgiapp()
  File "/home/flasky/venv/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 52, in load_wsgiapp
    return util.import_app(self.app_uri)
  File "/home/flasky/venv/lib/python3.6/site-packages/gunicorn/util.py", line 352, in import_app
    __import__(module)
  File "/home/flasky/flasky.py", line 15, in <module>
    app = create_app(os.getenv('FLASK_CONFIG') or 'default')
  File "/home/flasky/app/__init__.py", line 36, in create_app
    from .main import main as main_blueprint
ImportError: cannot import name 'main'
[2021-12-29 14:34:51 +0000] [14] [INFO] Worker exiting (pid: 14)
[2021-12-29 14:34:51 +0000] [1] [INFO] Shutting down: Master
[2021-12-29 14:34:51 +0000] [1] [INFO] Reason: Worker failed to boot.

Any ideas?

Do you have a main directory in /home/flasky/app? Is there a __init__.py inside this directory? Does this file have a main variable in it? Since the import is failing, one of these questions must have a "no" answer. You can log in to your container to check these things using the docker exec command.

Created an image of the stopped Flasky docker container to check inside

Thanks for "wasting" time on this. Good questions. I have a main directory in /home/flasky/app. But can't check for __init__.py or main variable because can't cd to main/: Permission denied.
The odd thing about this is: I cloned your entire code (Dockerfile & all) and followed the commands in your book to the letter. No changes. Do you have another tip? If you run the 17d code on your side, in 2021, can you replicate the issue?

Terminal code to look inside the container:

$ docker commit 716bd1c028a3 debug/flasky
sha256:4107650b9e649674ec2cd2189e68fb9195adb2696323d12274d993e14702bd67
~/being-awesome/4_books_courses/courses/flask/2018-flask-web-dev/flasky-17d
$ docker run -it --rm --entrypoint sh debug/flasky
~ $ pwd
/home/flasky
~ $ ls
__pycache__   boot.sh       flasky.py     requirements
app           config.py     migrations    venv
~ $ cd app/
~/app $ ls
__init__.py    decorators.py  fake.py        static
api            email.py       main           templates
auth           exceptions.py  models.py
~/app $ cd main/
sh: cd: can't cd to main/: Permission denied
~/app $ ls main/
ls: can't open 'main/': Permission denied
~/app $ ls -l
total 56
-rw-rw-r--    1 root     root          1124 Dec 29 16:44 __init__.py
drwx------    2 root     root          4096 Jul 20 09:41 api
drwx------    2 root     root          4096 Jul 20 09:41 auth
-rw-rw-r--    1 root     root           494 Jul 20 09:41 decorators.py
-rw-rw-r--    1 root     root           669 Jul 20 09:41 email.py
-rw-rw-r--    1 root     root            44 Jul 20 09:41 exceptions.py
-rw-rw-r--    1 root     root          1012 Jul 20 09:41 fake.py
drwx------    2 root     root          4096 Jul 20 09:41 main
-rw-rw-r--    1 root     root         12892 Jul 20 09:41 models.py
drwx------    2 root     root          4096 Jul 20 09:41 static
drwx------    4 root     root          4096 Jul 20 09:41 templates
~/app $ 

Have you done anything to change the default umask setting on your system? This is what I get:

-rw-r--r--    1 root     root          1156 Jul 20 09:38 __init__.py
drwxr-xr-x    2 root     root          4096 May 16  2021 __pycache__
drwxr-xr-x    3 root     root          4096 Feb  1  2021 api
drwxr-xr-x    3 root     root          4096 Jul 20 09:38 auth
-rw-r--r--    1 root     root           494 Dec 19  2020 decorators.py
-rw-r--r--    1 root     root           669 Dec 19  2020 email.py
-rw-r--r--    1 root     root            44 Feb  1  2021 exceptions.py
-rw-r--r--    1 root     root          1012 Dec 19  2020 fake.py
drwxr-xr-x    3 root     root          4096 Jul 20 09:38 main
-rw-r--r--    1 root     root         12892 Feb  1  2021 models.py
drwxr-xr-x    2 root     root          4096 Feb  1  2021 static
drwxr-xr-x    4 root     root          4096 Feb  1  2021 templates

Note how all the files are readable by everybody. Your directories are only accessible to the root user.

Miguel you should receive an international award for best teacher 2021. The directory where I kept my files had the permissions completely out of wack. Nobody could read the files besides root. Created a new directory with the correct umask value and everything is hunky dory.

If folders can't be read of course imports will not work. Very obvious and simple, but only after you point it out.