Browse Source

Dockerização do SIGI

pull/159/head
Sesostris Vieira 3 years ago
parent
commit
16e6ce5c6d
  1. 15
      .dockerignore
  2. 22
      bin/run_sigi
  3. 100
      docker/Dockerfile
  4. 34
      docker/docker-compose.yml
  5. 6
      etc/nginx/sites-available/sigi.vhost
  6. 2
      requirements/dev-requirements.txt
  7. 7
      requirements/requirements.txt
  8. 0
      sigi/menu_conf.yaml
  9. 103
      sigi/settings.py
  10. 12
      sigi/settings/__init__.py
  11. 57
      sigi/settings/development.py

15
.dockerignore

@ -0,0 +1,15 @@
media
data
env
static
.git
.gitignore
*.log
~*
*.pyc
.cache
.project
.vscode
.travis.yml
.env
.idea

22
bin/run_sigi

@ -1,28 +1,26 @@
#!/bin/bash
# This script expects the following ENV variables:
# $SOCKS : Path to the dir that holds unix socket file
# - Defined as /srv/interlegis/socks in Dockerfile
# $HOME : Path to app home work dir.
# - Defined as /srv/interlegis/sigi in Dockerfile
NAME="sigi"
DJANGODIR=/srv/sigi
VENVDIR=/srv/.virtualenvs/sigi/bin
SOCKFILE=/var/run/sigi/sigi.sock
USER=sigi
GROUP=sigi
SOCKFILE=$SOCKS/sigi.sock
NUM_WORKERS=3 # = 2 * CPUs + 1
DJANGO_SETTINGS_MODULE=sigi.settings
DJANGO_WSGI_MODULE=sigi.wsgi
echo "Starting $NAME as `whoami`"
cd $DJANGODIR
cd ${HOME}
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR
export PYTHONPATH=${HOME}:$PYTHONPATH
exec ${VENVDIR}/gunicorn ${DJANGO_WSGI_MODULE}:application \
exec gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--log-level=debug \
--timeout=180 \
--graceful-timeout=180 \

100
docker/Dockerfile

@ -0,0 +1,100 @@
FROM python:3.8-slim-buster
# Setup env
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV DEBIAN_FRONTEND=noninteractive
# App env
ENV INTERLEGIS=/srv/interlegis
ENV HOME=${INTERLEGIS}/sigi
ENV SOCKS=${INTERLEGIS}/socks
# Settings args - must be provided in the build process
ENV DEBUG=False
ENV ADMINS="(('SIGI Administrator', 'sigi@interlegis.leg.br'),)"
ENV EMAIL_PORT=25
ENV EMAIL_HOST=mail.interlegis.leg.br
ENV EMAIL_HOST_USER=''
ENV EMAIL_HOST_PASSWORD=''
ENV EMAIL_SUBJECT_PREFIX='[SIGI]'
ENV EMAIL_USE_LOCALTIME=True
ENV EMAIL_USE_TLS=False
ENV EMAIL_USE_SSL=False
ENV EMAIL_TIMEOUT=120
ENV DATABASE_URL='sqlite:////:memory:'
ENV AUTH_LDAP_SERVER_URI=''
ENV AUTH_LDAP_BIND_DN=''
ENV AUTH_LDAP_BIND_PASSWORD=''
ENV AUTH_LDAP_USER=''
ENV AUTH_LDAP_USER_SEARCH_STRING=''
ENV AUTH_LDAP_GROUP=''
ENV AUTH_LDAP_GROUP_SEARCH_STRING=''
ENV AUTH_LDAP_GROUP_TYPE_STRING=''
ENV AUTH_LDAP_USER_ATTR_MAP=''
ENV AUTH_LDAP_PROFILE_ATTR_MAP=''
ENV AUTH_LDAP_FIND_GROUP_PERMS=''
ENV AUTH_LDAP_MIRROR_GROUPS=''
ENV AUTH_LDAP_CACHE_GROUPS=''
ENV AUTH_LDAP_GROUP_CACHE_TIMEOUT=''
ENV AUTH_PROFILE_MODULE=''
# Install env
ENV RUN_PACKAGES gcc locales build-essential python3-dev graphviz \
libgraphviz-dev pkg-config libpq-dev postgresql-client \
libsasl2-dev libldap2-dev libssl-dev vim nginx
# Install required packages
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y ${RUN_PACKAGES}
# Set encode language/charset
ENV DESIRED_LANG=pt_BR.UTF-8
RUN sed -i -e "s/# ${DESIRED_LANG}.*/${DESIRED_LANG} UTF-8/" /etc/locale.gen && \
locale-gen pt_BR.UTF-8 && \
dpkg-reconfigure --frontend=noninteractive locales && \
update-locale LANG=${DESIRED_LANG}
ENV LANG=${DESIRED_LANG}
# Create work and unix socket dirs
RUN mkdir -p ${HOME} && \
mkdir ${SOCKS} && \
mkdir ${HOME}/media && \
mkdir ${HOME}/static
# Add sigi to container
WORKDIR ${HOME}
ADD . ${HOME}
# Install python packages
RUN pip install -qq --upgrade pip setuptools && \
if [ $DEBUG = False ]; then \
pip install -qq -r ${HOME}/requirements/requirements.txt; \
else \
pip install -qq -r ${HOME}/requirements/dev-requirements.txt; \
fi
# Generate a new secret key
RUN echo $'\n\n'SECRET_KEY=`python manage.py generate_secret_key` >> ${HOME}/sigi/.env
# Prepare run script to start application server
RUN chmod +x ${HOME}/bin/run_sigi
# Data migration
RUN python manage.py migrate
# Static files
RUN python manage.py collectstatic --noinput --clear
# nginx setup
RUN rm -f /etc/nginx/sites-enabled/*
RUN ln -s ${HOME}/etc/nginx/sites-available/sigi.vhost /etc/nginx/sites-enabled/sigi.vhost
RUN mkdir -p /var/log/sigi
EXPOSE 80/tcp 443/tcp
ENV DEBIAN_FRONTEND=teletype
VOLUME ["/srv/interlegis/sigi/media"]
CMD service nginx start && /srv/interlegis/sigi/bin/run_sigi

34
docker/docker-compose.yml

@ -0,0 +1,34 @@
version: "3.3"
services:
sigidb:
image: postgres:alpine3.15
volumes:
- ../data/db:/var/lib/postgresql/data
environment:
- LANG=pt_BR.UTF-8
- POSTGRES_NAME=sigi
- POSTGRES_USER=sigi
- POSTGRES_PASSWORD=sigi
- PGDATA=/var/lib/postgresql/data
networks:
- sigi-net
sigi:
build:
context: ${PWD}/
dockerfile: docker/Dockerfile
ports:
- "8000:80"
volumes:
- ../data/media:/srv/interlegis/sigi/media
environment:
- LANG=pt_BR.UTF-8
- DATABASE_URL=psql://sigi:sigi@sigidb:5432/sigi
depends_on:
- sigidb
networks:
- sigi-net
networks:
sigi-net:
name: sigi-net
driver: bridge

6
etc/nginx/sites-available/sigi.vhost

@ -1,5 +1,5 @@
upstream sigi_app_server {
server unix:/var/run/sigi/sigi.sock fail_timeout=0;
server unix:/srv/interlegis/socks/sigi.sock fail_timeout=0;
}
server {
@ -12,11 +12,11 @@ server {
error_log /var/log/sigi/sigi-error.log;
location /static/ {
alias /srv/sigi/static/;
alias /srv/interlegis/sigi/static/;
}
location /media/ {
alias /srv/sigi/media/;
alias /srv/interlegis/sigi/media/;
}
location / {

2
requirements/dev-requirements.txt

@ -1,3 +1,3 @@
-r requirements.txt
django-debug-toolbar==3.2.4
pygraphviz==1.7
pygraphviz==1.9

7
requirements/requirements.txt

@ -1,11 +1,14 @@
gunicorn==20.1.0
ipython==8.2.0
Pillow==9.1.0
psycopg2==2.9.3
psycopg2-binary==2.9.3
requests==2.27.1
weasyprint==54.3
Django==4.0.3
django-auth-ldap==4.0.0
django-environ==0.8.1
django-extensions==3.1.5
django-import-export==2.7.1
django-import-export==2.8.0
django-localflavor==3.1
django-material-admin==1.8.6
django-tinymce==3.4.0

0
sigi/settings/menu_conf.yaml → sigi/menu_conf.yaml

103
sigi/settings/base.py → sigi/settings.py

@ -10,12 +10,27 @@ For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.0/ref/settings/
"""
import environ
from pathlib import Path
from django.utils.translation import gettext_lazy as _
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
BASE_DIR = Path(__file__).resolve().parent
env = environ.Env()
env.read_env(BASE_DIR / ".env")
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY', default="Unsafe")
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env('DEBUG', default=False, cast=bool)
ALLOWED_HOSTS = ['*']
INTERNAL_IPS = ["127.0.0.1",]
ADMINS = env('ADMINS', eval)
# Application definition
@ -36,7 +51,6 @@ INSTALLED_APPS = [
'django.forms',
'material',
'material.admin',
# 'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
@ -55,6 +69,28 @@ MIDDLEWARE = [
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
if DEBUG:
INSTALLED_APPS = ['debug_toolbar',] + INSTALLED_APPS
MIDDLEWARE = ['debug_toolbar.middleware.DebugToolbarMiddleware',] + \
MIDDLEWARE
EMAIL_PORT=env("EMAIL_PORT", int, default=25)
EMAIL_HOST=env("EMAIL_HOST", default="")
EMAIL_HOST_USER=env("EMAIL_HOST_USER", default="")
EMAIL_HOST_PASSWORD=env("EMAIL_HOST_PASSWORD", default="")
EMAIL_SUBJECT_PREFIX=env("EMAIL_SUBJECT_PREFIX", default="[SIGI]")
EMAIL_USE_LOCALTIME=env("EMAIL_USE_LOCALTIME", bool, default=False)
EMAIL_USE_TLS=env("EMAIL_USE_TLS", bool, default=False)
EMAIL_USE_SSL=env("EMAIL_USE_SSL", bool, default=False)
EMAIL_TIMEOUT=env("EMAIL_TIMEOUT", int, default=None)
# Database
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
DATABASES = {
'default': env.db(),
}
ROOT_URLCONF = 'sigi.urls'
TEMPLATES = [
@ -94,13 +130,63 @@ USE_TZ = True
USE_THOUSAND_SEPARATOR = True
# Password validation
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
if env('AUTH_LDAP_SERVER_URI', default=None):
AUTHENTICATION_BACKENDS = [
"django_auth_ldap.backend.LDAPBackend",
"django.contrib.auth.backends.ModelBackend",
]
from django_auth_ldap.config import LDAPSearch, GroupOfNamesType
import ldap
AUTH_LDAP_SERVER_URI = env('AUTH_LDAP_SERVER_URI')
AUTH_LDAP_BIND_DN = env('AUTH_LDAP_BIND_DN')
AUTH_LDAP_BIND_PASSWORD = env('AUTH_LDAP_BIND_PASSWORD')
AUTH_LDAP_USER = env('AUTH_LDAP_USER')
AUTH_LDAP_USER_SEARCH = LDAPSearch(
AUTH_LDAP_USER,
ldap.SCOPE_SUBTREE,
env('AUTH_LDAP_USER_SEARCH_STRING')
)
AUTH_LDAP_GROUP = env('AUTH_LDAP_GROUP')
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
AUTH_LDAP_GROUP,
ldap.SCOPE_SUBTREE,
env('AUTH_LDAP_GROUP_SEARCH_STRING')
)
AUTH_LDAP_GROUP_TYPE = GroupOfNamesType(
name_attr=env('AUTH_LDAP_GROUP_TYPE_STRING')
)
AUTH_LDAP_USER_ATTR_MAP = env('AUTH_LDAP_USER_ATTR_MAP', cast=eval)
AUTH_LDAP_PROFILE_ATTR_MAP = env('AUTH_LDAP_PROFILE_ATTR_MAP', eval)
AUTH_LDAP_FIND_GROUP_PERMS = env('AUTH_LDAP_FIND_GROUP_PERMS', bool)
AUTH_LDAP_MIRROR_GROUPS = env('AUTH_LDAP_MIRROR_GROUPS', bool)
AUTH_LDAP_CACHE_GROUPS = env('AUTH_LDAP_CACHE_GROUPS', bool)
AUTH_LDAP_GROUP_CACHE_TIMEOUT = env('AUTH_LDAP_GROUP_CACHE_TIMEOUT', int)
AUTH_PROFILE_MODULE = env('AUTH_PROFILE_MODULE')
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.0/howto/static-files/
STATIC_URL = 'static/'
STATICFILES_DIRS = [BASE_DIR / "static",]
STATIC_ROOT = '/var/www/sigi/static/'
STATIC_ROOT = BASE_DIR / '../static/'
# Media files
# https://docs.djangoproject.com/en/4.0/topics/files/#managing-files
@ -126,8 +212,6 @@ MATERIAL_ADMIN_SITE = {
'HEADER': _('SIGI - Sistema de Informações do Interlegis'),
'TITLE': _('SIGI'),
'FAVICON': 'img/favicon.ico',
# 'MAIN_BG_COLOR': 'color', # Admin site main color, css color should be specified
# 'MAIN_HOVER_COLOR': 'color', # Admin site main hover color, css color should be specified
'PROFILE_PICTURE': 'img/interlegis.jpeg', # Admin site profile picture (path to static should be specified)
'PROFILE_BG': 'img/engitec.jpeg', # Admin site profile background (path to static should be specified)
'LOGIN_LOGO': 'img/interlegis.jpeg', # Admin site logo on login page (path to static should be specified)
@ -135,15 +219,8 @@ MATERIAL_ADMIN_SITE = {
'SHOW_THEMES': False, # Show default admin themes button
'TRAY_REVERSE': False, # Hide object-tools and additional-submit-line by default
'NAVBAR_REVERSE': False, # Hide side navbar by default
# 'SHOW_COUNTS': True, # Show instances counts for each model
# 'APP_ICONS': { # Set icons for applications(lowercase), including 3rd party apps, {'application_name': 'material_icon_name', ...}
# 'sites': 'send',
# },
# 'MODEL_ICONS': { # Set icons for models(lowercase), including 3rd party models, {'model_name': 'material_icon_name', ...}
# 'site': 'contact_mail',
# }
}
# SIGI specific settings
MENU_FILE = BASE_DIR / 'settings/menu_conf.yaml'
MENU_FILE = BASE_DIR / 'menu_conf.yaml'

12
sigi/settings/__init__.py

@ -1,12 +0,0 @@
try:
from sigi.settings.production import *
except ImportError:
from django.core.exceptions import ImproperlyConfigured
msg = """
######################################################################
Arquivo production.py (django settings) nao encontrado.
Se vc esta num ambiente de desenvolvimento pode cria-lo com
ln -s development.py production.py
######################################################################
"""
raise ImproperlyConfigured(msg)

57
sigi/settings/development.py

@ -1,57 +0,0 @@
from sigi.settings.base import *
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-z%cw$-jyh13g2an=8r5ltkyub75bfc$34o(k#%jncdcdgr2$3#'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
INTERNAL_IPS = ["127.0.0.1",]
# Application definition
INSTALLED_APPS = ['debug_toolbar',] + INSTALLED_APPS
MIDDLEWARE = ['debug_toolbar.middleware.DebugToolbarMiddleware',] + MIDDLEWARE
# Database
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'sigi',
'USER': 'sigi',
'PASSWORD': '123456',
'HOST': 'localhost',
}
}
# Password validation
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.0/howto/static-files/
STATIC_ROOT = BASE_DIR / '../static/'
Loading…
Cancel
Save