This instructions are based on these online tutorials.
Create a virtual environment and install Django. Official instructions.
pip install Django==4.x.xGo to the directory you want to locate your Django project and create the Yun2Infinity project.
django-admin startproject yun2inf_projectGo to the directory you want to locate your Django app and create the yun2inf_book.
py manage.py startapp yun2inf_bookIn the yun2inf_book directory create a folder call static.
Build a jupyterbook following these tutorial. This book interface will serve as the webpage for your yun2inf project. Make all necessary changes to the book to describe your app.
Copy and paste all the files in the _build folder into the yun2inf_book/static/ folder
In the yun2inf_book directory create a folder call templates. In the templates folder create a file call ‘index.html’ and paste the following codes.
{% load static %} <meta http-equiv="Refresh" content="0; url={% static 'yun2inf_book/html/index.html' %}" />Go to yun2inf_book/views.py and input these codes.
from django.shortcuts import render def book(request): return render(request, 'index.html')Go to yun2inf_book/urls.py and input these codes.
from django.urls import path from . import views urlpatterns = [ path('', views.book, name='book'), ]Go to yun2inf_project/urls.py and input these codes.
from django.contrib import admin from django.urls import include, path urlpatterns = [ path('', include('yun2inf_book.urls')), path("admin/", admin.site.urls), ]Go to yun2inf_project/settings.py and add the yun2inf_book app.
INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "yun2inf_book" ]Then run this command.
python manage.py migrateConfigure the static file settings in the yun2inf_project/settings.py. Set the static root.
STATIC_ROOT = "/var/www/yun2inf/static/"run this command to collect all the static files into one folder
python manage.py collectstatic
Run the server and see the result.
python manage.py runserverRemove the secret key from Django settings.py.
SECRET_KEY = "django-insecure-o6w@a46mx..." # Remove this linereplace it with these codes.
try: SECRET_KEY = os.environ["SECRET_KEY"] except KeyError as e: raise RuntimeError("Could not find a SECRET_KEY in environment") from e
Set your key to the environment with OpenSSL.
echo "export SECRET_KEY='$(openssl rand -hex 40)'" > .DJANGO_SECRET_KEY source .DJANGO_SECRET_KEY
Serve your Django app with Gunicorn¶
Install gunicorn.
pip install gunicorn==20.1.0Create a config/gunicorn/prod.py file in the project in the following structure
- yun2inf_project - config - gunicorn - prod.py - yun2inf_book - yun2inf_project - db.sqlite3 - manage.pyCut and paste these codes into the dev.py file.
"""Gunicorn *development* config file""" import multiprocessing # Django WSGI application path in pattern MODULE_NAME:VARIABLE_NAME wsgi_app = "yun2inf_project.wsgi:application" # The granularity of Error log outputs loglevel = "info" # The number of worker processes for handling requests workers = multiprocessing.cpu_count() * 2 + 1 # The socket to bind bind = "0.0.0.0:8000" # Restart workers when code changes (development only!) reload = False # Write access and error info to /var/log accesslog = "/var/log/gunicorn/access.log" errorlog = "/var/log/gunicorn/error.log" # Redirect stdout/stderr to log file capture_output = True # PID file so you can easily fetch process ID pidfile = "/var/run/gunicorn/prod.pid" # Daemonize the Gunicorn process (detach & enter background) daemon = FalseCreate the log and run file as specified in your config dev.py file. Change the permission to ensure you have access to the files. You can use ls -l path/to/file to get know the owner and group of the file.
sudo mkdir -pv /var/log/gunicorn/ sudo chown -cR owner:group /var/log/gunicorn/ sudo mkdir -pv /var/run/gunicorn/ sudo chown -cR owner:group /var/run/gunicorn/Run Gunicorn with this command
gunicorn -c config/gunicorn/prod.pyCheck on the status with this command.
tail -f /var/log/gunicorn/access.log tail -f /var/log/gunicorn/error.logTo kill gunicorn
pkill gunicornThere will be an issue with serving static file with gunicorn. This will be resolved when a webserver like nginx is used for serving the Django and Gunicorn application.
Containerize your Django App and Gunicorn¶
These instructions are based on these online tutorials.
Create yun2inf_project/config/gunicorn/yun2inf_init.sh
#!/bin/bash export SECRET_KEY='(openssl rand -hex 40)' > /code/.DJANGO_SET_KEY mkdir -pv /var/log/gunicorn/ mkdir -pv /var/run/gunicorn/ source /code/.DJANGO_SET_KEY exec gunicorn -c /code/config/gunicorn/dev.py #exec gunicorn --log-level=info \ #--workers=2 \ #--bind=0.0.0.0:8000 \ #--access-logfile=/var/log/gunicorn/dev.log \ #--error-logfile=/var/log/gunicorn/dev.log \ #--capture-output \ #--pid=/var/log/gunicorn/dev.pid \ #yun2inf_project.wsgi:applicationCreate a Dockerfile in the yun2inf_project folder.
FROM python:3.11.3-alpine # Set environment varibles ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 RUN apk add --update --no-cache openssl RUN mkdir docker-entrypoint-initdb.d COPY config/gunicorn/yun2inf_gunicorn.sh docker-entrypoint-initdb.d/yun2inf_gunicorn.sh RUN chmod a+x docker-entrypoint-initdb.d/yun2inf_gunicorn.sh # Mounts the application code to the image COPY . yun2inf_project WORKDIR /yun2inf_project COPY requirements.txt requirements.txt RUN pip install --no-cache-dir -r requirements.txt EXPOSE 8000 ENTRYPOINT ["/bin/sh", "/docker-entrypoint-initdb.d/yun2inf_gunicorn.sh"]Run this command to build the image. This command will find the Dockerfile in the directory and build the image according to the file. Refer to this website for a quick understanding of the Dockerfile.
sudo docker build . -t chenkianwee/yun2inf:x.x.xRun the docker image with the -v command to create a volume that can be used by another nginx container.
# to create the network docker network create --driver bridge yun2infsudo docker run -d --name yun2inf_project -h yun2inf_project --network "yun2inf" -p 8000:8000 -v y2i:/yun2inf_project/www/static/ chenkianwee/yun2inf:x.x.xPush the image to your docker hub. Once uploaded, you will be able to pull from the repository.
$ sudo docker login $ sudo docker push yourName/ImageName:tag