Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
neverabsolute committed Apr 4, 2022
1 parent 29a8476 commit 95b3d3d
Show file tree
Hide file tree
Showing 10 changed files with 353 additions and 0 deletions.
126 changes: 126 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# Folder view configuration files
.DS_Store
Desktop.ini

# Thumbnail cache files
._*
Thumbs.db

# Files that might appear on external disks
.Spotlight-V100
.Trashes
43 changes: 43 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
FROM python:3.8-slim-buster
USER root

# Install system level dependencies
RUN apt-get update &&\
apt-get install\
ffmpeg\
gcc\
libsm6\
libxext6\
musl-dev\
nano\
nginx\
python3-dev\
python3-pip\
systemd\
unzip\
wget\
zip\
-y\
&& apt-get autoremove -y\
&& apt-get clean -y\
&& rm -rf /var/lib/apt/lists/*

# copy nginx configuration file, pip requirements, and entrypoint to be used when starting Docker container
ADD nginx_host /etc/nginx/sites-enabled/default
ADD entrypoint.sh /entrypoint.sh
ADD app/requirements.txt /app/requirements.txt

# install pip and dependencies
RUN wget https://bootstrap.pypa.io/get-pip.py \
&& python3 get-pip.py \
&& python3 -m pip install -U pip \
&& python3 -m pip install -r /app/requirements.txt \
&& rm get-pip.py

# copy app to be used when starting Docker container, and set permissions
COPY ./app /app
RUN chmod +x entrypoint.sh && chmod -R 755 /app

EXPOSE 80
WORKDIR /app
CMD ["/entrypoint.sh"]
86 changes: 86 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Universal Project Scaffold
A scaffold for deploying dockerized flask applications.

### Quickstart Guide for Local Development

cd into the `/app` folder

`python3 -m pip install -r requirements.txt`

edit line 29 the `main.py` file to either the URL of the cocalc server you are on or `localhost` if you are running it on your own PC

run

`python3 -m main`

to start the server on local, most changes while developing will be picked up in realtime by the server

### Quickstart Guide for Local Deployment

Make sure docker is installed on your system. Look that up if you don't know what that means.

cd into the root director of the repo then run

`docker build -t omni .`

once built, run

`docker run -d -p 9000:80 --restart=unless-stopped --name omni omni`

you should then be able to see the `omni` container running when you run

`docker ps -a`

if it seems to be stuck (i.e. constantly listed as `Restarting`), something is wrong with the docker image or code inside causing it to repeatedly fail.

you can start debugging the project by running

`docker logs -f omni`

or

`docker exec -it omni /bin/bash` for an interactive bash terminal (this option only works if the container is running and not stuck in a restart loop)


### File Structure
The files/directories which you will need to edit are **bolded**

**DO NOT TOUCH OTHER FILES. THIS MAY RESULT IN YOUR PROJECT BEING UNABLE TO RUN**

- .gitignore
- Dockerfile
- READMD.md
- entrypoint.sh
- nginx_host
- host_config
- app/
- **main.py**
- **pytorch_model.bin** <- you will need to upload this yourself after cloning the repo when developing the site
- **requirements.txt**
- **utils.py**
- templates/
- **index.html**
### pytorch_model.bin ###
The weights file - must upload if you are running file on coding center or are trying to deploy.
### main.py ###
Contains the main flask app itself.
### requirements.txt ###
Contains list of packages and modules required to run the flask app. Edit only if you are using additional packages that need to be pip installed in order to run the project.

To generate a requirements.txt file you can run

`pip list --format=freeze > app/requirements.txt`

the requirements.txt file will then be updated. Keep in mind: some packages you install on one operating system may not be available on another. You will have to debug and resolve this yourself if this is the case.
### static/ ###
Contains the static images, CSS, & JS files used by the flask app for the webpage. You will need to create this and put files in it. Place all your images used for your website in static/images/ so that you can then reference them in your html files.
### utils.py ###
Contains common functions used by the flask app. Put things here that are used more than once in the flask app.
### templates/ ###
Contains the HTML pages used for the webpage. Edit these to fit your project. index.html is the demo page.
### Files used for deployment ###
`Dockerfile`
`entrypoint.sh`
`nginx_host`
`host_config`
**Only modify `host_config`. Do not touch the other files.**
32 changes: 32 additions & 0 deletions app/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# import requirements needed
from flask import Flask, render_template
from utils import get_base_url

# setup the webserver
# port may need to be changed if there are multiple flask servers running on same server
port = 12345
base_url = get_base_url(port)

# if the base url is not empty, then the server is running in development, and we need to specify the static folder so that the static files are served
if base_url == '/':
app = Flask(__name__)
else:
app = Flask(__name__, static_url_path=base_url+'static')

# set up the routes and logic for the webserver
@app.route(f'{base_url}')
def home():
return render_template('index.html')

# define additional routes here
# for example:
# @app.route(f'{base_url}/team_members')
# def team_members():
# return render_template('team_members.html') # would need to actually make this page

if __name__ == '__main__':
# IMPORTANT: change url to the site where you are editing this file.
website_url = 'url'

print(f'Try to open\n\n https://{website_url}' + base_url + '\n\n')
app.run(host = '0.0.0.0', port=port, debug=True)
4 changes: 4 additions & 0 deletions app/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Flask==1.1.4
gunicorn==20.1.0
uvicorn==0.17.6
markupsafe==2.0.1
3 changes: 3 additions & 0 deletions app/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<h2>
The index works.
</h2>
21 changes: 21 additions & 0 deletions app/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import json
import os

def get_base_url(port:int) -> str:
'''
Returns the base URL to the webserver if available.
i.e. if the webserver is running on coding.ai-camp.org port 12345, then the base url is '/<your project id>/port/12345/'
Inputs: port (int) - the port number of the webserver
Outputs: base_url (str) - the base url to the webserver
'''

try:
info = json.load(open(os.path.join(os.environ['HOME'], '.smc', 'info.json'), 'r'))
project_id = info['project_id']
base_url = f'/{project_id}/port/{port}/'
except Exception as e:
print(f'Server is probably running in production, so a base url does not apply: \n{e}')
base_url = '/'
return base_url
4 changes: 4 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
service nginx start
cd /app
gunicorn -k uvicorn.workers.UvicornWorker --bind unix:/app/gunicorn.sock main:app
19 changes: 19 additions & 0 deletions host_config
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl;
server_name <change this>;

ssl_certificate /etc/letsencrypt/live/<change this>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<change this>/privkey.pem;

client_max_body_size 75M;

location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:9000;
}
}
15 changes: 15 additions & 0 deletions nginx_host
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
upstream app_server {
server unix:/app/gunicorn.sock fail_timeout=0;
}

server {
listen 80;
location / {
proxy_pass http://app_server;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}

0 comments on commit 95b3d3d

Please sign in to comment.