From 3a96ee1f3986345dc89fdeb5c8f4aedaef78c914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tao=20Bror=20Bojl=C3=A9n?= Date: Wed, 20 Feb 2019 16:18:12 +0000 Subject: [PATCH] docker-ise backend --- .gitignore | 7 +- backend/api/Dockerfile | 12 ++ {apiv1 => backend/api/apiv1}/__init__.py | 0 {apiv1 => backend/api/apiv1}/_util.py | 0 {apiv1 => backend/api/apiv1}/apps.py | 0 {apiv1 => backend/api/apiv1}/serializers.py | 0 {apiv1 => backend/api/apiv1}/views.py | 0 backend/{ => api/backend}/__init__.py | 0 backend/{ => api/backend}/settings/base.py | 40 +--- backend/{ => api/backend}/settings/dev.py | 2 +- .../{ => api/backend}/settings/production.py | 4 +- backend/{ => api/backend}/urls.py | 0 backend/{ => api/backend}/wsgi.py | 3 - manage.py => backend/api/manage.py | 2 +- .../api/requirements.txt | 1 + {scraper => backend/api/scraper}/__init__.py | 0 {scraper => backend/api/scraper}/admin.py | 0 {scraper => backend/api/scraper}/apps.py | 0 .../api/scraper}/management/commands/_util.py | 0 .../management/commands/build_graph.py | 0 .../scraper}/management/commands/scrape.py | 0 .../api/scraper}/migrations/0001_initial.py | 0 .../api/scraper}/migrations/__init__.py | 0 {scraper => backend/api/scraper}/models.py | 0 {scraper => backend/api/scraper}/tests.py | 0 {scraper => backend/api/scraper}/views.py | 0 backend/api/scripts/docker-entrypoint.sh | 26 +++ whitelist.txt => backend/api/whitelist.txt | 0 {gephi => backend/gephi}/.gitignore | 0 {gephi => backend/gephi}/README.md | 0 {gephi => backend/gephi}/build.gradle | 0 .../gephi}/gradle/wrapper/gradle-wrapper.jar | Bin .../gradle/wrapper/gradle-wrapper.properties | 0 {gephi => backend/gephi}/gradlew | 0 {gephi => backend/gephi}/gradlew.bat | 0 {gephi => backend/gephi}/lib/.gitkeep | 0 .../gephi}/lib/gephi-toolkit-0.9.2.jar | Bin {gephi => backend/gephi}/settings.gradle | 0 .../space/fediverse/graph/GraphBuilder.java | 0 config.json.template | 7 - config/gunicorn.conf.py | 196 ++++++++++++++++++ config/nginx/conf.d/local.conf | 20 ++ docker-compose.production.yml | 38 ++++ docker-compose.yml | 31 +++ example.env | 5 + 45 files changed, 347 insertions(+), 47 deletions(-) create mode 100644 backend/api/Dockerfile rename {apiv1 => backend/api/apiv1}/__init__.py (100%) rename {apiv1 => backend/api/apiv1}/_util.py (100%) rename {apiv1 => backend/api/apiv1}/apps.py (100%) rename {apiv1 => backend/api/apiv1}/serializers.py (100%) rename {apiv1 => backend/api/apiv1}/views.py (100%) rename backend/{ => api/backend}/__init__.py (100%) rename backend/{ => api/backend}/settings/base.py (75%) rename backend/{ => api/backend}/settings/dev.py (80%) rename backend/{ => api/backend}/settings/production.py (58%) rename backend/{ => api/backend}/urls.py (100%) rename backend/{ => api/backend}/wsgi.py (79%) rename manage.py => backend/api/manage.py (86%) rename requirements.txt => backend/api/requirements.txt (96%) rename {scraper => backend/api/scraper}/__init__.py (100%) rename {scraper => backend/api/scraper}/admin.py (100%) rename {scraper => backend/api/scraper}/apps.py (100%) rename {scraper => backend/api/scraper}/management/commands/_util.py (100%) rename {scraper => backend/api/scraper}/management/commands/build_graph.py (100%) rename {scraper => backend/api/scraper}/management/commands/scrape.py (100%) rename {scraper => backend/api/scraper}/migrations/0001_initial.py (100%) rename {scraper => backend/api/scraper}/migrations/__init__.py (100%) rename {scraper => backend/api/scraper}/models.py (100%) rename {scraper => backend/api/scraper}/tests.py (100%) rename {scraper => backend/api/scraper}/views.py (100%) create mode 100644 backend/api/scripts/docker-entrypoint.sh rename whitelist.txt => backend/api/whitelist.txt (100%) rename {gephi => backend/gephi}/.gitignore (100%) rename {gephi => backend/gephi}/README.md (100%) rename {gephi => backend/gephi}/build.gradle (100%) rename {gephi => backend/gephi}/gradle/wrapper/gradle-wrapper.jar (100%) rename {gephi => backend/gephi}/gradle/wrapper/gradle-wrapper.properties (100%) rename {gephi => backend/gephi}/gradlew (100%) rename {gephi => backend/gephi}/gradlew.bat (100%) rename {gephi => backend/gephi}/lib/.gitkeep (100%) rename {gephi => backend/gephi}/lib/gephi-toolkit-0.9.2.jar (100%) rename {gephi => backend/gephi}/settings.gradle (100%) rename {gephi => backend/gephi}/src/main/java/space/fediverse/graph/GraphBuilder.java (100%) delete mode 100644 config.json.template create mode 100644 config/gunicorn.conf.py create mode 100644 config/nginx/conf.d/local.conf create mode 100644 docker-compose.production.yml create mode 100644 docker-compose.yml create mode 100644 example.env diff --git a/.gitignore b/.gitignore index 10c5d8e..a16a93d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,9 @@ *.csv .idea/ -config.json -backend/static/ +backend/api/backend/static/ *.gexf -whitelist.txt +backend/api/backend/whitelist.txt +data/ # Byte-compiled / optimized / DLL files __pycache__/ @@ -90,6 +90,7 @@ celerybeat-schedule # Environments .env +.env* .venv env/ venv/ diff --git a/backend/api/Dockerfile b/backend/api/Dockerfile new file mode 100644 index 0000000..b1a0094 --- /dev/null +++ b/backend/api/Dockerfile @@ -0,0 +1,12 @@ +FROM python:3 +ENV PYTHONUNBUFFERED 1 + +RUN apt-get update && \ + apt-get install -qqy --no-install-recommends \ + postgresql-client-9.6=9.6.10-0+deb9u1 + +RUN mkdir /code +WORKDIR /code +COPY requirements.txt /code/ +RUN pip install -r requirements.txt +COPY . /code/ diff --git a/apiv1/__init__.py b/backend/api/apiv1/__init__.py similarity index 100% rename from apiv1/__init__.py rename to backend/api/apiv1/__init__.py diff --git a/apiv1/_util.py b/backend/api/apiv1/_util.py similarity index 100% rename from apiv1/_util.py rename to backend/api/apiv1/_util.py diff --git a/apiv1/apps.py b/backend/api/apiv1/apps.py similarity index 100% rename from apiv1/apps.py rename to backend/api/apiv1/apps.py diff --git a/apiv1/serializers.py b/backend/api/apiv1/serializers.py similarity index 100% rename from apiv1/serializers.py rename to backend/api/apiv1/serializers.py diff --git a/apiv1/views.py b/backend/api/apiv1/views.py similarity index 100% rename from apiv1/views.py rename to backend/api/apiv1/views.py diff --git a/backend/__init__.py b/backend/api/backend/__init__.py similarity index 100% rename from backend/__init__.py rename to backend/api/backend/__init__.py diff --git a/backend/settings/base.py b/backend/api/backend/settings/base.py similarity index 75% rename from backend/settings/base.py rename to backend/api/backend/settings/base.py index 87b1456..e345598 100644 --- a/backend/settings/base.py +++ b/backend/api/backend/settings/base.py @@ -14,35 +14,11 @@ import os import json from django.core.exceptions import ImproperlyConfigured -with open(os.environ.get('FEDIVERSE_CONFIG')) as f: - configs = json.loads(f.read()) - - -def get_config(setting): - try: - val = configs[setting] - if val == 'True': - val = True - elif val == 'False': - val = False - return val - except KeyError: - error_msg = "ImproperlyConfigured: Set {0} environment variable".format(setting) - raise ImproperlyConfigured(error_msg) - - -SECRET_KEY = get_config("SECRET_KEY") +SECRET_KEY = os.getenv("SECRET_KEY") # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ - -ALLOWED_HOSTS = [] - - # Application definition INSTALLED_APPS = [ @@ -76,7 +52,7 @@ ROOT_URLCONF = 'backend.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [os.path.join(BASE_DIR, '../frontend/build')], + 'DIRS': [os.path.join(BASE_DIR, '../../frontend/build')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ @@ -97,10 +73,12 @@ WSGI_APPLICATION = 'backend.wsgi.application' DATABASES = { 'default': { - 'ENGINE': get_config("DATABASE_ENGINE"), - 'NAME': get_config("DATABASE_NAME"), - 'USER': get_config("DATABASE_USER"), - 'PASSWORD': get_config("DATABASE_PASSWORD"), + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': os.getenv("POSTGRES_DB"), + 'USER': os.getenv("POSTGRES_USER"), + 'PASSWORD': os.getenv("POSTGRES_PASSWORD"), + 'HOST': 'db', + 'PORT': 5432, } } @@ -143,7 +121,7 @@ USE_TZ = False STATIC_URL = '/static/' STATICFILES_DIRS = [ - os.path.join(BASE_DIR, '../frontend/build/static') + os.path.join(BASE_DIR, '../../frontend/build/static') ] STATIC_ROOT = os.path.join(BASE_DIR, 'static') diff --git a/backend/settings/dev.py b/backend/api/backend/settings/dev.py similarity index 80% rename from backend/settings/dev.py rename to backend/api/backend/settings/dev.py index e58f186..a160fb7 100644 --- a/backend/settings/dev.py +++ b/backend/api/backend/settings/dev.py @@ -2,7 +2,7 @@ from .base import * DEBUG = True -ALLOWED_HOSTS += ['localhost'] +ALLOWED_HOSTS = ['localhost'] CORS_ORIGIN_WHITELIST = [ 'localhost:3000', diff --git a/backend/settings/production.py b/backend/api/backend/settings/production.py similarity index 58% rename from backend/settings/production.py rename to backend/api/backend/settings/production.py index 62905c7..e5a56c3 100644 --- a/backend/settings/production.py +++ b/backend/api/backend/settings/production.py @@ -1,6 +1,8 @@ from .base import * -ALLOWED_HOSTS += ['fediverse.space'] +DEBUG = False + +ALLOWED_HOSTS = ['fediverse.space'] CORS_ORIGIN_WHITELIST = [ 'fediverse.space', diff --git a/backend/urls.py b/backend/api/backend/urls.py similarity index 100% rename from backend/urls.py rename to backend/api/backend/urls.py diff --git a/backend/wsgi.py b/backend/api/backend/wsgi.py similarity index 79% rename from backend/wsgi.py rename to backend/api/backend/wsgi.py index b3c226b..238f221 100644 --- a/backend/wsgi.py +++ b/backend/api/backend/wsgi.py @@ -8,9 +8,6 @@ https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/ """ import os - from django.core.wsgi import get_wsgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings.production') - application = get_wsgi_application() diff --git a/manage.py b/backend/api/manage.py similarity index 86% rename from manage.py rename to backend/api/manage.py index 968e304..bb33428 100755 --- a/manage.py +++ b/backend/api/manage.py @@ -3,9 +3,9 @@ import os import sys if __name__ == '__main__': - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings') try: from django.core.management import execute_from_command_line + except ImportError as exc: raise ImportError( "Couldn't import Django. Are you sure it's installed and " diff --git a/requirements.txt b/backend/api/requirements.txt similarity index 96% rename from requirements.txt rename to backend/api/requirements.txt index cbf9ba4..3493071 100644 --- a/requirements.txt +++ b/backend/api/requirements.txt @@ -10,6 +10,7 @@ django-silk==3.0.1 djangorestframework==3.8.2 future==0.16.0 gprof2dot==2016.10.13 +gunicorn==19.9.0 idna==2.7 Jinja2==2.10 MarkupSafe==1.0 diff --git a/scraper/__init__.py b/backend/api/scraper/__init__.py similarity index 100% rename from scraper/__init__.py rename to backend/api/scraper/__init__.py diff --git a/scraper/admin.py b/backend/api/scraper/admin.py similarity index 100% rename from scraper/admin.py rename to backend/api/scraper/admin.py diff --git a/scraper/apps.py b/backend/api/scraper/apps.py similarity index 100% rename from scraper/apps.py rename to backend/api/scraper/apps.py diff --git a/scraper/management/commands/_util.py b/backend/api/scraper/management/commands/_util.py similarity index 100% rename from scraper/management/commands/_util.py rename to backend/api/scraper/management/commands/_util.py diff --git a/scraper/management/commands/build_graph.py b/backend/api/scraper/management/commands/build_graph.py similarity index 100% rename from scraper/management/commands/build_graph.py rename to backend/api/scraper/management/commands/build_graph.py diff --git a/scraper/management/commands/scrape.py b/backend/api/scraper/management/commands/scrape.py similarity index 100% rename from scraper/management/commands/scrape.py rename to backend/api/scraper/management/commands/scrape.py diff --git a/scraper/migrations/0001_initial.py b/backend/api/scraper/migrations/0001_initial.py similarity index 100% rename from scraper/migrations/0001_initial.py rename to backend/api/scraper/migrations/0001_initial.py diff --git a/scraper/migrations/__init__.py b/backend/api/scraper/migrations/__init__.py similarity index 100% rename from scraper/migrations/__init__.py rename to backend/api/scraper/migrations/__init__.py diff --git a/scraper/models.py b/backend/api/scraper/models.py similarity index 100% rename from scraper/models.py rename to backend/api/scraper/models.py diff --git a/scraper/tests.py b/backend/api/scraper/tests.py similarity index 100% rename from scraper/tests.py rename to backend/api/scraper/tests.py diff --git a/scraper/views.py b/backend/api/scraper/views.py similarity index 100% rename from scraper/views.py rename to backend/api/scraper/views.py diff --git a/backend/api/scripts/docker-entrypoint.sh b/backend/api/scripts/docker-entrypoint.sh new file mode 100644 index 0000000..b437be6 --- /dev/null +++ b/backend/api/scripts/docker-entrypoint.sh @@ -0,0 +1,26 @@ +#! /bin/bash + +SLEEP_SECONDS=3 + +>&2 echo "Checking Postgres status..." + +# https://docs.docker.com/compose/startup-order/ +export PGPASSWORD=$POSTGRES_PASSWORD +until psql -h db -U "$POSTGRES_USER" -p 5432 -d "$POSTGRES_DB" -c '\q' +do + >&2 echo "Postgres is unavailable - sleeping" + sleep $SLEEP_SECONDS +done +>&2 echo "Postgres is up" + +python manage.py migrate --noinput + + +if [[ $ENVIRONMENT == "development" ]] +then + >&2 echo "Running Django server on port 8000 for development" + python manage.py runserver 0.0.0.0:8000 +else + >&2 echo "Running gunicorn server" + gunicorn backend.wsgi -c /config/gunicorn.conf.py +fi diff --git a/whitelist.txt b/backend/api/whitelist.txt similarity index 100% rename from whitelist.txt rename to backend/api/whitelist.txt diff --git a/gephi/.gitignore b/backend/gephi/.gitignore similarity index 100% rename from gephi/.gitignore rename to backend/gephi/.gitignore diff --git a/gephi/README.md b/backend/gephi/README.md similarity index 100% rename from gephi/README.md rename to backend/gephi/README.md diff --git a/gephi/build.gradle b/backend/gephi/build.gradle similarity index 100% rename from gephi/build.gradle rename to backend/gephi/build.gradle diff --git a/gephi/gradle/wrapper/gradle-wrapper.jar b/backend/gephi/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from gephi/gradle/wrapper/gradle-wrapper.jar rename to backend/gephi/gradle/wrapper/gradle-wrapper.jar diff --git a/gephi/gradle/wrapper/gradle-wrapper.properties b/backend/gephi/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from gephi/gradle/wrapper/gradle-wrapper.properties rename to backend/gephi/gradle/wrapper/gradle-wrapper.properties diff --git a/gephi/gradlew b/backend/gephi/gradlew similarity index 100% rename from gephi/gradlew rename to backend/gephi/gradlew diff --git a/gephi/gradlew.bat b/backend/gephi/gradlew.bat similarity index 100% rename from gephi/gradlew.bat rename to backend/gephi/gradlew.bat diff --git a/gephi/lib/.gitkeep b/backend/gephi/lib/.gitkeep similarity index 100% rename from gephi/lib/.gitkeep rename to backend/gephi/lib/.gitkeep diff --git a/gephi/lib/gephi-toolkit-0.9.2.jar b/backend/gephi/lib/gephi-toolkit-0.9.2.jar similarity index 100% rename from gephi/lib/gephi-toolkit-0.9.2.jar rename to backend/gephi/lib/gephi-toolkit-0.9.2.jar diff --git a/gephi/settings.gradle b/backend/gephi/settings.gradle similarity index 100% rename from gephi/settings.gradle rename to backend/gephi/settings.gradle diff --git a/gephi/src/main/java/space/fediverse/graph/GraphBuilder.java b/backend/gephi/src/main/java/space/fediverse/graph/GraphBuilder.java similarity index 100% rename from gephi/src/main/java/space/fediverse/graph/GraphBuilder.java rename to backend/gephi/src/main/java/space/fediverse/graph/GraphBuilder.java diff --git a/config.json.template b/config.json.template deleted file mode 100644 index 8ca461e..0000000 --- a/config.json.template +++ /dev/null @@ -1,7 +0,0 @@ -{ - "SECRET_KEY": "df4p)6h(#ktn*#ckh2m^^(-)w6_9mn$b%^!+$02vnb&e3sz&!r", - "DATABASE_ENGINE": "django.db.backends.sqlite", - "DATABASE_NAME": "os.path.join(BASE_DIR, 'db.sqlite3')", - "DATABASE_USER": "", - "DATABASE_PASSWORD": "" -} \ No newline at end of file diff --git a/config/gunicorn.conf.py b/config/gunicorn.conf.py new file mode 100644 index 0000000..d752da6 --- /dev/null +++ b/config/gunicorn.conf.py @@ -0,0 +1,196 @@ +# +# Server socket +# +# bind - The socket to bind. +# +# A string of the form: 'HOST', 'HOST:PORT', 'unix:PATH'. +# An IP is a valid HOST. +# +# backlog - The number of pending connections. This refers +# to the number of clients that can be waiting to be +# served. Exceeding this number results in the client +# getting an error when attempting to connect. It should +# only affect servers under significant load. +# +# Must be a positive integer. Generally set in the 64-2048 +# range. +# + +bind = ['unix:/var/gunicorn/.sock', ':8000'] + +# +# Worker processes +# +# workers - The number of worker processes that this server +# should keep alive for handling requests. +# +# A positive integer generally in the 2-4 x $(NUM_CORES) +# range. You'll want to vary this a bit to find the best +# for your particular application's work load. +# +# worker_class - The type of workers to use. The default +# sync class should handle most 'normal' types of work +# loads. You'll want to read +# http://docs.gunicorn.org/en/latest/design.html#choosing-a-worker-type +# for information on when you might want to choose one +# of the other worker classes. +# +# A string referring to a Python path to a subclass of +# gunicorn.workers.base.Worker. The default provided values +# can be seen at +# http://docs.gunicorn.org/en/latest/settings.html#worker-class +# +# worker_connections - For the eventlet and gevent worker classes +# this limits the maximum number of simultaneous clients that +# a single process can handle. +# +# A positive integer generally set to around 1000. +# +# timeout - If a worker does not notify the master process in this +# number of seconds it is killed and a new worker is spawned +# to replace it. +# +# Generally set to thirty seconds. Only set this noticeably +# higher if you're sure of the repercussions for sync workers. +# For the non sync workers it just means that the worker +# process is still communicating and is not tied to the length +# of time required to handle a single request. +# +# keepalive - The number of seconds to wait for the next request +# on a Keep-Alive HTTP connection. +# +# A positive integer. Generally set in the 1-5 seconds range. +# + +# try: +# # fail 'successfully' if either of these modules aren't installed +# from gevent import monkey +# from psycogreen.gevent import patch_psycopg + + +# # setting this inside the 'try' ensures that we only +# # activate the gevent worker pool if we have gevent installed +# worker_class = 'gevent' +# workers = 4 +# # this ensures forked processes are patched with gevent/gevent-psycopg2 +# def do_post_fork(server, worker): +# monkey.patch_all() +# patch_psycopg() + +# # you should see this text in your gunicorn logs if it was successful +# worker.log.info("Made Psycopg2 Green") + +# post_fork = do_post_fork +# except ImportError: +# pass + +workers = 4 +# worker_connections = 1000 +# timeout = 30 +# keepalive = 2 + +# +# spew - Install a trace function that spews every line of Python +# that is executed when running the server. This is the +# nuclear option. +# +# True or False +# + +spew = False + +# +# Server mechanics +# +# daemon - Detach the main Gunicorn process from the controlling +# terminal with a standard fork/fork sequence. +# +# True or False +# +# pidfile - The path to a pid file to write +# +# A path string or None to not write a pid file. +# +# user - Switch worker processes to run as this user. +# +# A valid user id (as an integer) or the name of a user that +# can be retrieved with a call to pwd.getpwnam(value) or None +# to not change the worker process user. +# +# group - Switch worker process to run as this group. +# +# A valid group id (as an integer) or the name of a user that +# can be retrieved with a call to pwd.getgrnam(value) or None +# to change the worker processes group. +# +# umask - A mask for file permissions written by Gunicorn. Note that +# this affects unix socket permissions. +# +# A valid value for the os.umask(mode) call or a string +# compatible with int(value, 0) (0 means Python guesses +# the base, so values like "0", "0xFF", "0022" are valid +# for decimal, hex, and octal representations) +# +# tmp_upload_dir - A directory to store temporary request data when +# requests are read. This will most likely be disappearing soon. +# +# A path to a directory where the process owner can write. Or +# None to signal that Python should choose one on its own. +# + +daemon = False +pidfile = '/var/gunicorn/.pid' +umask = 0 +user = None +group = None +tmp_upload_dir = None + +# +# Logging +# +# logfile - The path to a log file to write to. +# +# A path string. "-" means log to stdout. +# +# loglevel - The granularity of log output +# +# A string of "debug", "info", "warning", "error", "critical" +# + +errorlog = '-' +loglevel = 'warning' +accesslog = '-' +access_log_format = '%(h)s %(t)s %(m)s %(U)s %(q)s %(H)s %(s)s %(B)s %(f)s %(a)s %(L)s' + +# +# Process naming +# +# proc_name - A base to use with setproctitle to change the way +# that Gunicorn processes are reported in the system process +# table. This affects things like 'ps' and 'top'. If you're +# going to be running more than one instance of Gunicorn you'll +# probably want to set a name to tell them apart. This requires +# that you install the setproctitle module. +# +# A string or None to choose a default of something like 'gunicorn'. +# + +proc_name = None + +# +# Server hooks +# +# post_fork - Called just after a worker has been forked. +# +# A callable that takes a server and worker instance +# as arguments. +# +# pre_fork - Called just prior to forking the worker subprocess. +# +# A callable that accepts the same arguments as after_fork +# +# pre_exec - Called just prior to forking off a secondary +# master process during things like config reloading. +# +# A callable that takes a server instance as the sole argument. +# diff --git a/config/nginx/conf.d/local.conf b/config/nginx/conf.d/local.conf new file mode 100644 index 0000000..762dc7c --- /dev/null +++ b/config/nginx/conf.d/local.conf @@ -0,0 +1,20 @@ +upstream app { + server unix:/var/gunicorn/.sock; +} + +server { + listen 80 default_server; + server_name localhost; + + location / { + allow all; + proxy_http_version 1.1; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header X-Cluster-Client-Ip $remote_addr; + proxy_pass http://app; + } + + # Note that nginx doesn't serve any static files. +} + diff --git a/docker-compose.production.yml b/docker-compose.production.yml new file mode 100644 index 0000000..d166321 --- /dev/null +++ b/docker-compose.production.yml @@ -0,0 +1,38 @@ +version: '3' +services: + db: + restart: always + networks: + - database_network + web: + restart: always + volumes: + - gunicorn-socket:/var/gunicorn + - ./config/gunicorn.conf.py:/config/gunicorn.conf.py + networks: + - database_network + - nginx_network + environment: + - ENVIRONMENT=production + - DJANGO_SETTINGS_MODULE=backend.settings.production + nginx: + image: nginx:1.14 + # build: + # context: . + # dockerfile: Dockerfile.nginx + ports: + - "80:80" + volumes: + - gunicorn-socket:/var/gunicorn + - ./config/nginx/conf.d:/etc/nginx/conf.d + networks: + - nginx_network + depends_on: + - web +networks: + database_network: + driver: bridge + nginx_network: + driver: bridge +volumes: + gunicorn-socket: diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..0acaf44 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,31 @@ +version: '3' +services: + db: + image: postgres + environment: + # Set these in .env + - POSTGRES_USER + - POSTGRES_PASSWORD + - POSTGRES_DB + ports: + - "5432:5432" + volumes: + - pgdata:/var/lib/postgresql/data + web: + environment: + # Set these in .env + - SECRET_KEY + - POSTGRES_USER + - POSTGRES_PASSWORD + - POSTGRES_DB + - DJANGO_SETTINGS_MODULE + build: ./backend/api + command: bash scripts/docker-entrypoint.sh + volumes: + - ./backend/api:/code + ports: + - "8000:8000" + depends_on: + - db +volumes: + pgdata: diff --git a/example.env b/example.env new file mode 100644 index 0000000..f3867ba --- /dev/null +++ b/example.env @@ -0,0 +1,5 @@ +SECRET_KEY=a-long-secret-key +POSTGRES_USER=postgres +POSTGRES_PASSWORD=postgres +POSTGRES_DB=fediverse +DJANGO_SETTINGS_MODULE=backend.settings.dev