Search code examples
pythonnginxflaskgoogle-compute-enginegunicorn

Flask Nginx Gunicorn app doesn't deploy on Google compute vm


I've been banging my head on the wall trying to find the error in the code below. I have a Flask/PostgreSQL/SQLAlchemy program hosted on a GCP Compute Engine VM with Nginx and Gunicorn for a server solution.

My work is writing code, not deploying it. (It's better to have more skills, but it is what it is.) And I do not have anybody at this moment to delegate this task to or to get assistance from.

The app deploys locally without any issues. However, putting it on a GCP server is a bit of a problem. I have checked a few dozen Stackoverflow posts and Googled every phrase iteration, but I cannot figure out which part of the code is off.

Nginx server is online because when I check the domain in the browser, I get the 'Welcome to nginx!' page. But the service is failing after gunicorn is started. See the code below. Knowledgeable advice will be greatly appreciated.

my_project folder on the compute vm /home/user/

user@my_project-vm:~/my_project$ ls -la
total 72
drwxr-xr-x  8 user user     4096 Dec 27 21:00 .
drwxr-xr-x  8 user user     4096 Dec 27 21:13 ..
-rw-r--r--  1 user user     2148 Dec 27 05:00 .env
-rw-r--r--  1 user user       34 Dec 27 20:56 .flaskenv
drwxr-xr-x  8 user user     4096 Dec 27 20:56 .git
-rw-r--r--  1 user user     1039 Dec 27 04:41 .gitignore
drwxr-xr-x  2 user user     4096 Dec 27 04:41 .vscode
-rw-r--r--  1 user user     2322 Dec 27 04:41 GCP_email_notification.json
drwxr-xr-x  2 user www-data 4096 Dec 27 20:10 __pycache__
drwxr-xr-x 10 user user     4096 Dec 27 20:56 app
-rw-r--r--  1 user user     7403 Dec 27 20:56 app.py
-rw-r--r--  1 user user      604 Dec 27 04:41 extensions.py
srwxrwx---  1 user www-data    0 Dec 27 21:00 my_project.sock
drwxr-xr-x  3 user user     4096 Dec 27 04:41 migrations
-rw-r--r--  1 user user     1740 Dec 27 05:00 requirements.txt
-rw-r--r--  1 user user      810 Dec 27 04:41 tmp-policy.json
drwxr-xr-x  6 user user     4096 Dec 27 04:48 venv
-rw-r--r--  1 user user       45 Dec 27 20:10 wsgi.py

wsgi.py on /home/user/my_project/

from app import create_app
app = create_app()

app.py on /home/user/my_project/

from app import create_app

if __name__ == "__main__":
    app = create_app()
    app.run(host='0.0.0.0')

__init__.py on /home/user/my_project/app/

import ...

def create_app(): 
    app = Flask(__name__,
                static_url_path='/',
                static_folder='../app/static',
                template_folder='../app/templates')
    ...
    app.config.from_object(config['default'])
    config['default'].init_app(app)

    @app.context_processor
    ...

    @app.template_filter('datetime')
    ...
              
    api.init_app(app)
    db.init_app(app)
    mail.init_app(app)
    moment.init_app(app)

    from app.models import ...

    migrate = Migrate(app, db)
    
    from .templates.about import about_bp
    from .templates.errors import error_bp
    from .templates.main import main_bp
    ...

    app.register_blueprint(main_bp)
    app.register_blueprint(error_bp)
    app.register_blueprint(about_bp, url_prefix='/about')
    ...

    return app

my_project on /etc/nginx/sites/available

    server {
    listen 80;
    server_name my_domain.com www.my_domain.com;

    location / {
        proxy_pass http://unix:/home/user/my_project/my_project.sock
        }
    }

my_project.service on /etc/systemd/system

    [Unit]
    Description= You can change time text
    After=network.target

    [Service]
    User=user
    Group=www-data
    WorkingDirectory=/home/user/my_project
    Environment="PATH=/home/user/my_project/venv/bin"
    ExecStart=/home/user/my_project/venv/bin/gunicorn --workers 3 --bind unix:my_project.sock -m 007 wsgi:app

    [Install]
    WantedBy=multi-user.target

This is what I get after sudo systemctl status my_project. The LAST line is where things go south...

my_project.service - my_project primary web server setup
     Loaded: loaded (/etc/systemd/system/my_project.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2023-12-27 21:00:09 UTC; 1h 22min ago
   Main PID: 131051 (gunicorn)
      Tasks: 7 (limit: 2353)
     Memory: 207.9M
        CPU: 6.629s
     CGroup: /system.slice/my_project.service
             ├─131051 /home/user/my_project/venv/bin/python3 /home/user/my_project/venv/bin/gunicorn --workers 3 --bind unix:my_project.sock -m 007 wsgi:app
             ├─131052 /home/user/my_project/venv/bin/python3 /home/user/my_project/venv/bin/gunicorn --workers 3 --bind unix:my_project.sock -m 007 wsgi:app
             ├─131053 /home/user/my_project/venv/bin/python3 /home/user/my_project/venv/bin/gunicorn --workers 3 --bind unix:my_project.sock -m 007 wsgi:app
             └─131054 /home/user/my_project/venv/bin/python3 /home/user/my_project/venv/bin/gunicorn --workers 3 --bind unix:my_project.sock -m 007 wsgi:app

Dec 27 21:00:09 my_project systemd[1]: Started my_project primary web server setup.
Dec 27 21:00:09 my_project gunicorn[131051]: [2023-12-27 21:00:09 +0000] [131051] [INFO] Starting gunicorn 21.2.0
Dec 27 21:00:09 my_project gunicorn[131051]: [2023-12-27 21:00:09 +0000] [131051] [INFO] Listening at: unix:my_project.sock (131051)
Dec 27 21:00:09 my_project gunicorn[131051]: [2023-12-27 21:00:09 +0000] [131051] [INFO] Using worker: sync
Dec 27 21:00:09 my_project gunicorn[131052]: [2023-12-27 21:00:09 +0000] [131052] [INFO] Booting worker with pid: 131052
Dec 27 21:00:09 my_project gunicorn[131053]: [2023-12-27 21:00:09 +0000] [131053] [INFO] Booting worker with pid: 131053
Dec 27 21:00:09 my_project gunicorn[131054]: [2023-12-27 21:00:09 +0000] [131054] [INFO] Booting worker with pid: 131054
Dec 27 21:52:46 my_project systemd[1]: my_project.service: Current command vanished from the unit file, execution of the command list won't be resumed.

Thanks in advance. Enjoy the holiday season!


Solution

  • This particular problem was solved by changing the my_project.service file on /etc/systemd/system to include the --chdir flag in the ExecStart line as follows:

    ExecStart=/home/user/my_project/venv/bin/gunicorn --workers 3 --bind unix:/home/user/my_project/my_project.sock -m 007 --chdir /home/user/my_project wsgi:app
    

    The solution was adopted from How to run gunicorn from a folder that is not the django project folder