Create docker image

This commit is contained in:
Sascha Ißbrücker 2019-07-03 17:18:29 +02:00
parent fdcd9cb42c
commit d57ea27ba3
17 changed files with 137 additions and 12 deletions

7
.gitignore vendored
View File

@ -222,5 +222,8 @@ typings/
.next .next
### Custom ### Custom
polls
tmp # Collected static files for deployment
/static
# Build output, etc.
/tmp

26
Dockerfile Normal file
View File

@ -0,0 +1,26 @@
FROM python:3.7-slim-stretch
# Install packages required for uswgi
RUN apt-get update
RUN apt-get -y install build-essential
# Install requirements and uwsgi server for running python web apps
WORKDIR /etc/linkdings
COPY requirements.prod.txt ./requirements.txt
RUN pip install -U pip
RUN pip install -Ur requirements.txt
RUN pip install uwsgi
# Copy application
COPY bookmarks ./bookmarks
COPY siteroot ./siteroot
COPY static ./static
COPY manage.py .
COPY uwsgi.ini .
COPY bootstrap.sh .
RUN ["chmod", "+x", "./bootstrap.sh"]
EXPOSE 9090
# Start uwsgi server
CMD ["./bootstrap.sh"]

View File

@ -1,6 +1,6 @@
from django.contrib import admin from django.contrib import admin
# Register your models here. # Register your models here.
from .models import Bookmark from bookmarks.models import Bookmark
admin.site.register(Bookmark) admin.site.register(Bookmark)

View File

@ -0,0 +1,18 @@
from django.core.management.base import BaseCommand
from django.contrib.auth import get_user_model
class Command(BaseCommand):
help = "Creates an admin user non-interactively if it doesn't exist"
def add_arguments(self, parser):
parser.add_argument('--username', help="Admin's username")
parser.add_argument('--email', help="Admin's email")
parser.add_argument('--password', help="Admin's password")
def handle(self, *args, **options):
User = get_user_model()
if not User.objects.filter(username=options['username']).exists():
User.objects.create_superuser(username=options['username'],
email=options['email'],
password=options['password'])

View File

@ -2,8 +2,8 @@ from django.contrib.auth.models import User
from django.utils import timezone from django.utils import timezone
from bookmarks.models import Bookmark, BookmarkForm, parse_tag_string from bookmarks.models import Bookmark, BookmarkForm, parse_tag_string
from services.tags import get_or_create_tags from bookmarks.services.tags import get_or_create_tags
from services.website_loader import load_website_metadata from bookmarks.services.website_loader import load_website_metadata
def create_bookmark(form: BookmarkForm, current_user: User): def create_bookmark(form: BookmarkForm, current_user: User):

View File

@ -5,7 +5,7 @@ from bs4 import BeautifulSoup
from django.contrib.auth.models import User from django.contrib.auth.models import User
from bookmarks.models import Bookmark, parse_tag_string from bookmarks.models import Bookmark, parse_tag_string
from services.tags import get_or_create_tags from bookmarks.services.tags import get_or_create_tags
def import_netscape_html(html: str, user: User): def import_netscape_html(html: str, user: User):

View File

@ -2,8 +2,7 @@ from django.conf.urls import url
from django.urls import path from django.urls import path
from django.views.generic import RedirectView from django.views.generic import RedirectView
from . import views from bookmarks import views
from .views import api
app_name = 'bookmarks' app_name = 'bookmarks'
urlpatterns = [ urlpatterns = [
@ -15,5 +14,5 @@ urlpatterns = [
path('bookmarks/<int:bookmark_id>/edit', views.edit, name='edit'), path('bookmarks/<int:bookmark_id>/edit', views.edit, name='edit'),
path('bookmarks/<int:bookmark_id>/remove', views.remove, name='remove'), path('bookmarks/<int:bookmark_id>/remove', views.remove, name='remove'),
# API # API
path('api/website_metadata', api.website_metadata, name='api.website_metadata'), path('api/website_metadata', views.api.website_metadata, name='api.website_metadata'),
] ]

View File

@ -1 +1,2 @@
from .bookmarks import * from .bookmarks import *
from .api import *

View File

@ -1,7 +1,7 @@
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.http import JsonResponse from django.http import JsonResponse
from services.website_loader import load_website_metadata from bookmarks.services.website_loader import load_website_metadata
@login_required @login_required

14
bootstrap.sh Executable file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env bash
# Bootstrap script that gets executed in new Docker containers
# Set host name in settings if it was passed as environment variable
if [[ -v HOST_NAME ]]
then
printf "ALLOWED_HOSTS=['%s']" $HOST_NAME > ./siteroot/settings_custom.py
fi
# Run database migration
python manage.py migrate
# Start uwsgi server
uwsgi uwsgi.ini

5
build-docker.sh Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
./build-static.sh
#docker build -t sissbruecker/linkding .
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t sissbruecker/linkding:latest --push .

6
build-static.sh Executable file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
rm -rf static
python manage.py compilescss
python manage.py collectstatic --ignore=*.scss
python manage.py compilescss --delete-files

18
requirements.prod.txt Normal file
View File

@ -0,0 +1,18 @@
beautifulsoup4==4.7.1
certifi==2019.6.16
chardet==3.0.4
Django==2.2.2
django-appconf==1.0.3
django-compressor==2.3
django-picklefield==2.0
django-sass-processor==0.7.3
django-widget-tweaks==1.4.5
idna==2.8
pytz==2019.1
rcssmin==1.0.6
requests==2.22.0
rjsmin==1.1.0
six==1.12.0
soupsieve==1.9.2
sqlparse==0.3.0
urllib3==1.25.3

View File

@ -1,5 +1,5 @@
""" """
Django settings for siteroot project. Django settings for linkding webapp.
Generated by 'django-admin startproject' using Django 2.2.2. Generated by 'django-admin startproject' using Django 2.2.2.
@ -120,8 +120,12 @@ USE_TZ = True
STATIC_URL = '/static/' STATIC_URL = '/static/'
# Collect static files in static folder
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
# Location where generated CSS files are saved # Location where generated CSS files are saved
SASS_PROCESSOR_ROOT = os.path.join(BASE_DIR, 'bookmarks', 'static', 'build') SASS_PROCESSOR_ENABLED = True
SASS_PROCESSOR_ROOT = os.path.join(BASE_DIR, 'tmp', 'build', 'styles')
# Add SASS preprocessor finder to resolve generated CSS # Add SASS preprocessor finder to resolve generated CSS
STATICFILES_FINDERS = [ STATICFILES_FINDERS = [

View File

@ -0,0 +1 @@
# Placeholder, can be overridden in Docker container with a custom settings like ALLOWED_HOSTS

18
siteroot/settings_prod.py Normal file
View File

@ -0,0 +1,18 @@
"""
Production settings for linkding webapp
"""
# Start from development settings
# noinspection PyUnresolvedReferences
from .settings import *
# Turn of debug mode
DEBUG = False
# Turn off SASS compilation
SASS_PROCESSOR_ENABLED = False
ALLOWED_HOSTS = ['*']
# Import custom settings
# noinspection PyUnresolvedReferences
from .settings_custom import *

12
uwsgi.ini Normal file
View File

@ -0,0 +1,12 @@
[uwsgi]
#socket = 127.0.0.1:3031
http = :9090
chdir = /etc/linkdings
module = siteroot.wsgi:application
env = DJANGO_SETTINGS_MODULE=siteroot.settings_prod
static-map = /static=static
processes = 4
threads = 2
pidfile = /tmp/project-master.pid
vacuum=True
stats = 127.0.0.1:9191