Skip to content

add docker and kubernetes configs #151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 29, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
FROM docker.io/debian:buster-slim

# install imagetagger system dependencies
RUN apt-get update && \
apt-get install --no-install-recommends -y g++ wget uwsgi-plugin-python3 python3 python3-pip node-uglify make git \
python3-psycopg2 python3-ldap3 gettext gcc python3-dev python3-setuptools libldap2-dev libsasl2-dev nginx

# add requirements file
WORKDIR /app/src
COPY requirements.txt /app/src/requirements.txt

# install python dependencies
RUN pip3 install -r /app/src/requirements.txt
RUN pip3 install sentry-sdk uwsgi django-ldapdb django-auth-ldap

# clean container
RUN apt-get purge -y --auto-remove node-uglify git python3-pip make gcc python3-dev libldap2-dev libsasl2-dev \
python3-setuptools
RUN apt-get clean

# add remaining sources
COPY imagetagger /app/src/imagetagger

# confiure runtime environment
RUN mkdir /app/data /app/static /app/config
RUN cp /app/src/imagetagger/imagetagger/settings.py.example /app/config/settings.py
RUN ln -sf /app/config/settings.py /app/src/imagetagger/imagetagger/settings.py
RUN sed -i 's/env python/env python3/g' /app/src/imagetagger/manage.py

ARG UID_WWW_DATA=5008
ARG GID_WWW_DATA=33
RUN usermod -u $UID_WWW_DATA -g $GID_WWW_DATA -d /app/data/ www-data
RUN chown -R www-data /app

RUN /app/src/imagetagger/manage.py collectstatic --no-input

COPY docker/uwsgi_imagetagger.ini /etc/uwsgi/imagetagger.ini
COPY docker/nginx.conf /etc/nginx/sites-enabled/default
COPY docker/update_points docker/zip_daemon docker/run /app/bin/
RUN ln -sf /app/bin/* /usr/local/bin
ENTRYPOINT ["/usr/local/bin/run"]

# add image metadata
EXPOSE 3008
EXPOSE 80
VOLUME /app/config
VOLUME /app/data

34 changes: 34 additions & 0 deletions docker/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# vim: set filetype=conf:

server {
listen 80;
server_name default_server;
root /var/www/imagetagger;

client_max_body_size 4G;

location / {
include uwsgi_params;
uwsgi_pass localhost:3008;
uwsgi_read_timeout 120;
}

location /static {
expires 1h;
alias /var/www/imagetagger;
}

location /ngx_static_dn/ {
internal;
alias /app/data/images/;
}


location /_internal_auth/ {
rewrite ^/_internal_auth/ngx_std_direct/(\d*)/(.*)$ /images/image_nginx/$1 last;
}

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
}

8 changes: 8 additions & 0 deletions docker/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash
set -e

/app/src/imagetagger/manage.py migrate

nginx
exec uwsgi /etc/uwsgi/imagetagger.ini

4 changes: 4 additions & 0 deletions docker/update_points
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

/app/src/imagetagger/manage.py updatepoints

31 changes: 31 additions & 0 deletions docker/uwsgi_imagetagger.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[uwsgi]
procname-master = uwsgi %n
master = true
socket = :3008

chdir = /app/src/imagetagger

module = imagetagger.wsgi:application
env = DJANGO_SETTINGS_MODULE=imagetagger.settings

; drop privileges
uid = www-data
gid = www-data
umask = 027

; run with at least 1 process but increase up to 4 when needed
processes = 8
cheaper = 2

; reload whenever this config file changes
; %p is the full path of the current config file
touch-reload = %p

; disable uWSGI request logging
disable-logging = true

enable-threads = true

; update points every hour
cron2 = day=-1,unique=1 /usr/local/bin/update_points
smart-attach-daemon2 = /tmp/zipdaemon.pid /usr/local/bin/zip_daemon
4 changes: 4 additions & 0 deletions docker/zip_daemon
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

/app/src/imagetagger/manage.py runzipdaemon

15 changes: 9 additions & 6 deletions imagetagger/imagetagger/settings.py.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ SECRET_KEY = 'DEV KEY PLEASE CHANGE IN PRODUCTION INTO SOMETHING RANDOM'
DEBUG = True

# Allowed Host headers this site can server
ALLOWED_HOSTS = ['imagetagger.example.com']
ALLOWED_HOSTS = ['localhost', '127.0.0.1']

# Additional installed apps
INSTALLED_APPS += [
Expand All @@ -25,7 +25,7 @@ DATABASES = {
'default': {
# Imagetagger relies on some Postgres features so other Databses will _not_ work
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'HOST': '127.0.0.1',
'HOST': 'imagetagger-postgres',
'NAME': 'imagetagger',
'PASSWORD': 'imagetagger',
'USER': 'imagetagger',
Expand All @@ -39,7 +39,7 @@ LANGUAGE_CODE = 'en-us'

# TIME_ZONE = 'Europe/Berlin' #Timezone of your server

# STATIC_URL = '/static/'
STATIC_ROOT = '/var/www/imagetagger'

# EXPORT_SEPARATOR = '|'
# DATA_PATH = os.path.join(BASE_DIR, 'data')
Expand All @@ -52,7 +52,7 @@ LANGUAGE_CODE = 'en-us'
# 'jpg',
# }

USE_NGINX_IMAGE_PROVISION = False # defines if images get provided directly via nginx what generally improves imageset download performance
USE_NGINX_IMAGE_PROVISION = True # defines if images get provided directly via nginx what generally improves imageset download performance

# The 'report a problem' page on an internal server error can either be a custom url or a text that can be defined here.
# PROBLEMS_URL = 'https://problems.example.com'
Expand All @@ -69,14 +69,17 @@ ACCOUNT_ACTIVATION_DAYS = 7

UPLOAD_FS_GROUP = 33 # www-data on debian

ENABLE_ZIP_DOWNLOAD = False # If enabled, run manage.py runzipdaemon to create the zip files and keep them up to date
ENABLE_ZIP_DOWNLOAD = True # If enabled, run manage.py runzipdaemon to create the zip files and keep them up to date

# Test mail functionality by printing mails to console:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
TOOLS_ENABLED = True
TOOLS_PATH = os.path.join(BASE_DIR, 'tools')
TOOL_UPLOAD_NOTICE = ''

DATA_PATH = '/app/data'
IMAGE_PATH = DATA_PATH + '/images'
TOOLS_PATH = DATA_PATH + '/tools'

# Use ldap login
#
# import ldap
Expand Down
5 changes: 5 additions & 0 deletions k8s/namespace.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
kind: Namespace
apiVersion: v1
metadata:
name: imagetagger
71 changes: 71 additions & 0 deletions k8s/postgres.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
kind: Service
apiVersion: v1
metadata:
name: imagetagger-postgres
labels:
tier: database
spec:
selector:
tier: database
ports:
- name: postgres
port: 5432
targetPort: postgres

---
kind: Deployment
apiVersion: apps/v1
metadata:
name: imagetagger-postgres
labels:
tier: database
spec:
selector:
matchLabels:
tier: database
template:
metadata:
labels:
tier: database
spec:
automountServiceAccountToken: false
volumes:
- name: data
persistentVolumeClaim:
claimName: imagetagger-database
containers:
- name: main
image: docker.io/postgres:12
imagePullPolicy: Always
envFrom:
- configMapRef:
name: imagetagger-postgres
env:
# postgres recommends putting the actual data in a sub-folder if it is mounted from external sources
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
ports:
- name: postgres
containerPort: 5432
livenessProbe:
tcpSocket:
port: postgres

---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: imagetagger-database
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi # should be enough even for large instances
selector:
matchLabels:
tier: database
73 changes: 73 additions & 0 deletions k8s/web_app.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
kind: Service
apiVersion: v1
metadata:
name: imagetagger-web
labels:
tier: web
spec:
selector:
tier: web
ports:
- name: http
port: 80
targetPort: http

---
apiVersion: apps/v1
kind: Deployment
metadata:
name: imagetagger-web
labels:
tier: web
spec:
selector:
matchLabels:
tier: web
template:
metadata:
labels:
tier: web
spec:
volumes:
- name: config
configMap:
name: imagetagger-web
- name: data
persistentVolumeClaim:
claimName: imagetagger-image-data
containers:
- name: main
image: imagetagger:local
ports:
- name: uwsgi
containerPort: 3008
- name: http
containerPort: 80
volumeMounts:
- name: config
mountPath: /app/config
readOnly: true
- name: data
mountPath: /app/data
livenessProbe:
tcpSocket:
port: uwsgi
startupProbe:
tcpSocket:
port: uwsgi

---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: imagetagger-image-data
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi # in production we need a lot more but this should be enough for a test or dev instance
selector:
matchLabels:
tier: web
21 changes: 21 additions & 0 deletions kustomization.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
kind: Kustomization
apiVersion: kustomize.config.k8s.io/v1beta1
namespace: imagetagger
commonLabels:
app: imagetagger

resources:
- k8s/namespace.yml
- k8s/postgres.yml
- k8s/web_app.yml

configMapGenerator:
- name: imagetagger-web
files:
- "settings.py=./imagetagger/imagetagger/settings.py.example"
- name: imagetagger-postgres
literals:
- "POSTGRES_PASSWORD=imagetagger"
- "POSTGRES_USER=imagetagger"
- "POSTGRES_DB=imagetagger"