Skip to content
Snippets Groups Projects
Unverified Commit d520dc78 authored by dareqx's avatar dareqx Committed by GitHub
Browse files

Merge pull request #1 from dareqx/user-management

Dockerize the project and load settings from environment variables
parents dea7b8c7 50e42deb
Branches
Tags
No related merge requests found
UWSGI_PROCESS_PER_CONTAINER=4
DEBUG=true
ALLOWED_HOSTS=localhost,127.0.0.1
SECRET_KEY=Ixosoh1iemoh0Heloh1thee5akooboonu5veehae4aikoh2ohg
DATABASE_HOST=shellvalier-postgresql
DATABASE_NAME=shellvalier
DATABASE_USER=shellvalier
DATABASE_PASSWORD=shellvalier
DATABASE_PORT=5432
*.pyc
*/__pycache__/*
*/migrations/*_auto_*.py
/.datastore/
/.idea/
FROM ubuntu:focal
MAINTAINER Dariusz Czerski <dcz@ipipan.waw.pl>
ENV DEBIAN_FRONTEND=noninteractive \
LANG=en_US.UTF-8 \
LC_ALL=en_US.UTF-8 \
LANGUAGE=en_US:en \
TZ=Europe/Warsaw \
PYTHONUNBUFFERED=1 \
PYTHONFAULTHANDLER=1
ENV PACKAGES="\
binutils \
curl \
gdal-bin \
gettext \
git \
libproj-dev \
locales \
nginx \
postgresql-client \
python3-pip \
python3-setuptools \
python3-wheel \
python3.8 \
python3.8-dev \
syslinux \
tar \
tzdata \
unzip \
wget \
"
ENV DEV_PACKAGES="\
gpg-agent \
libcurl4-openssl-dev \
libssl-dev \
software-properties-common \
"
ADD requirements.txt /requirements.txt
RUN echo $TZ > /etc/timezone && \
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
apt update && \
apt install -y -f --no-install-recommends $PACKAGES $DEV_PACKAGES && \
update-alternatives --install /usr/bin/python python /usr/bin/python3.8 1 && \
update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1 && \
sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
echo "LC_ALL=$LC_ALL" >> /etc/environment && \
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen && \
echo "LANG=$LANG" > /etc/locale.conf && \
locale-gen $LANG && \
pip install -r /requirements.txt && \
wget -O - http://download.sgjp.pl/apt/sgjp.gpg.key | apt-key add - && \
apt-add-repository http://download.sgjp.pl/apt/ubuntu && \
apt update && \
apt install -y -f --no-install-recommends morfeusz2 && \
wget http://download.sgjp.pl/morfeusz/20211017/Linux/20.04/64/morfeusz2-1.99.1-20211017-cp35.cp36.cp37.cp38.cp39-abi3-linux_x86_64.whl && \
pip install morfeusz2-1.99.1-20211017-cp35.cp36.cp37.cp38.cp39-abi3-linux_x86_64.whl && \
rm morfeusz2-1.99.1-20211017-cp35.cp36.cp37.cp38.cp39-abi3-linux_x86_64.whl && \
mkdir /run/nginx/ && \
apt purge $DEV_PACKAGES -y && \
apt autoremove --purge -y && \
rm -rf /root/.cache/ && \
rm -rf /usr/src/ && \
rm -rf /var/lib/apt/lists/*
ADD docker/config/uwsgi.ini /uwsgi.ini
ADD . /app
VOLUME /app
WORKDIR /app
ENTRYPOINT ["/app/docker/scripts/docker-entrypoint"]
# ShellValier v2
## Running the development environment
In order to run the development environment locally:
1. Make sure you have [Docker Desktop](https://docs.docker.com/desktop/) and [Docker Compose](https://docs.docker.com/compose/) installed.
2. Build and run the project by executing:
./docker/scripts/run-docker
## Working in the development environment
Whenever you need to establish an interactive bash session in the running applicaiton container, execute:
./docker/scripts/docker-bash
version: "3"
networks:
app-tier:
driver: bridge
services:
postgresql:
container_name: shellvalier-postgresql
image: postgres:14.2
environment:
POSTGRES_USER: "shellvalier"
POSTGRES_DB: "shellvalier"
POSTGRES_PASSWORD: "shellvalier"
POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=en_US.UTF-8 --lc-ctype=en_US.UTF-8"
networks:
- app-tier
volumes:
- ./.datastore/postgresql:/var/lib/postgresql/data
backend:
container_name: shellvalier-backend
image: shellvalier-developer:latest
depends_on:
- postgresql
networks:
- app-tier
env_file: .environment-dev
volumes:
- .:/app
ports:
- "8000:8000"
[uwsgi]
chdir = /app
wsgi-file = /app/shellvalier/wsgi.py
socket = /run/uwsgi.sock
pidfile = /run/uwsgi.pid
chmod-socket = 666
master = true
processes = UWSGI_PROCESS_PER_CONTAINER
enable-threads = true
lazy-apps = true
max-requests = 500
max-requests-delta = 10
buffer-size = 32768
harakiri = 300
disable-write-exception = true
#!/usr/bin/env bash
docker-compose exec backend bash
#!/bin/bash
echo 'Starting docker container'
set -e
function assertPresence() {
VARIABLE_NAME=$1
if [ -z ${!VARIABLE_NAME} ]; then
echo "${VARIABLE_NAME} is unset. Please set this label to run this docker container";
exit 1
fi
}
assertPresence UWSGI_PROCESS_PER_CONTAINER
sed -i.bak "s/UWSGI_PROCESS_PER_CONTAINER/$UWSGI_PROCESS_PER_CONTAINER/" /uwsgi.ini
exec "$@"
python manage.py compilemessages
/app/docker/scripts/postgres-alive
python manage.py migrate --noinput
exec python manage.py runserver 0:8000
#!/usr/bin/env bash
function assertPresence() {
VARIABLE_NAME=$1
if [ -z ${!VARIABLE_NAME} ]; then
echo "${VARIABLE_NAME} is unset. Please set this label to run this docker container";
exit 1
fi
}
assertPresence DATABASE_HOST
assertPresence DATABASE_USER
assertPresence DATABASE_PASSWORD
assertPresence DATABASE_PORT
STATE=NOT_RUN
WAIT=1
is_alive() {
WAIT=$((WAIT+1))
if [[ $WAIT -le 180 ]]; then
DB_CON_OK=$(PGPASSWORD=$DATABASE_PASSWORD psql -h $DATABASE_HOST -U $DATABASE_USER -p $DATABASE_PORT -t -A -c "SELECT datname FROM pg_database WHERE datname='$DATABASE_NAME'" $DATABASE_NAME | grep -i $DATABASE_NAME)
if [[ $DB_CON_OK == "$DATABASE_NAME" ]]; then
STATE=RUN
fi
else
exit
fi
}
while [ $STATE == "NOT_RUN" ]; do
is_alive
sleep 1
done
#!/usr/bin/env bash
set -e
docker build -t shellvalier-developer -f Dockerfile .
docker-compose up
......@@ -6,6 +6,7 @@ certifi==2020.6.20
Django==3.1.5
django-crispy-forms==1.10.0
django-delayed-union==0.1.4
django-extensions==3.1.5
future==0.18.2
infinity==1.4
Jinja2==2.10.3
......
"""Utils for accessing process environment variables"""
import os
from typing import (
Any,
Callable,
List,
Optional,
)
from django.core.exceptions import ImproperlyConfigured
NOT_SET = object()
def get_environment(name: str, mapper: Optional[Callable[[str], Any]] = None, default=NOT_SET) -> Any:
"""Return a value with the given name from the process environment variables"""
possible_environ_names = [name]
for environ_name in possible_environ_names:
try:
value = os.environ[environ_name]
except KeyError:
continue
else:
break
else:
if default is NOT_SET:
raise ImproperlyConfigured('The {} environment variable is not present under names: {}'.format(name, ', '.join(possible_environ_names)))
else:
return default
mapper = mapper or str
return mapper(value)
def boolean_mapper(value: str) -> bool:
"""Map a string representation on a boolean value to Python bool"""
if value.lower() in {'true', '1', 'yes'}:
return True
if value.lower() in {'false', '0', 'no'}:
return False
raise ImproperlyConfigured('Boolean mapper cannot map the {} value to bool'.format(value))
def list_mapper_factory(delimiter: Optional[str] = None, item_mapper: Optional[Callable[[str], Any]] = None) -> Callable[[str], List[Any]]:
"""Return a function that maps lists serialized to a string with a specified delimiter to a Python list
:param delimiter: the item delimiter in the serialized list
:param item_mapper: the mapper for list elements
:return: the mapper function
"""
delimiter = delimiter or ','
item_mapper = item_mapper or str
def list_mapper(value: str) -> List[Any]:
"""Map a list serialized to a string to a Python list
Assumes an empty string represents an empty list, not a list containing an empty string.
:param value: the list serialized to string
:return: the parsed list
"""
if value == '':
return []
return [item_mapper(item) for item in value.split(delimiter)]
return list_mapper
......@@ -12,6 +12,9 @@ https://docs.djangoproject.com/en/2.1/ref/settings/
import os
from .environment import get_environment, boolean_mapper, list_mapper_factory
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
......@@ -20,10 +23,10 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'xxx'
SECRET_KEY = get_environment('SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
DEBUG = get_environment('DEBUG', mapper=boolean_mapper)
# for production
'''
......@@ -34,7 +37,7 @@ CSRF_COOKIE_SECURE = True
X_FRAME_OPTIONS = 'DENY'
'''
ALLOWED_HOSTS = ['127.0.0.1']
ALLOWED_HOSTS = get_environment('ALLOWED_HOSTS', mapper=list_mapper_factory())
# Application definition
......@@ -56,6 +59,7 @@ INSTALLED_APPS = [
'dictionary_statistics.apps.DictionaryStatisticsConfig',
'download.apps.DownloadConfig',
'crispy_forms',
'django_extensions',
]
CRISPY_TEMPLATE_PACK = 'bootstrap4'
......@@ -99,11 +103,11 @@ WSGI_APPLICATION = 'shellvalier.wsgi.application'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'shellvalier',
'USER': 'shellvalier',
'PASSWORD': 'shellvalier',
'HOST': 'localhost',
'PORT': '',
'NAME': get_environment('DATABASE_NAME'),
'USER': get_environment('DATABASE_USER'),
'PASSWORD': get_environment('DATABASE_PASSWORD'),
'HOST': get_environment('DATABASE_HOST'),
'PORT': get_environment('DATABASE_PORT', mapper=int),
}}
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment