Skip to content
Snippets Groups Projects
Commit 93f0d649 authored by florimondmanca's avatar florimondmanca
Browse files

simplify docker-compose

parent cac16471
No related branches found
No related tags found
No related merge requests found
Showing with 76 additions and 126 deletions
......@@ -10,6 +10,9 @@ __pycache__/
*.db
*.sqlite3
# private
.env
# media and collected static files
oser-backend/media/
static/
......
......@@ -9,8 +9,7 @@ install:
script:
# Check that docker images are running
- docker ps | grep nginx_01
- docker ps | grep django_01
- docker ps | grep ps_01
- docker ps | grep django_container
- docker ps | grep postgres_container
# Run the tests inside the Django container
- docker exec django_01 python manage.py test
- docker exec django_container python manage.py test
......@@ -2,43 +2,24 @@ version: '3'
# Create data volumes to be shared between Django and Nginx
volumes:
static:
media:
pgdata:
data:
services:
# NOTE: having volumes static and media both defined in nginx and
# gunicorn allows them to share the same data, i.e. it allows
# Nginx to access static and media files in the Django project's folder.
# Nginx server
nginx:
restart: always
image: nginx:latest
container_name: nginx_01
ports:
- 8000:8000
volumes:
- ./nginx/:/etc/nginx/conf.d
- static:/static/ # access static files
- media:/media/ # access media files
depends_on:
# start Django container before this one
- gunicorn
# Django web app on Gunicorn WSGI server
# Serves static files directly thanks to WhiteNoise
gunicorn:
restart: always
build: ./oser-backend
container_name: django_01
container_name: django_container
environment:
- DATABASE_URL=postgres://postgres:postgres@db:5432/postgres
ports:
- "8000:8000"
volumes:
# Sync local project folder to container's, allowing
# to see effects of code changes without need to rebuild image.
- ./oser-backend/:/oser-backend/
# Mount static and media file volumes
- static:/oser-backend/static # expose static files
- media:/oser-backend/media # expose media files
depends_on:
# start db container before this one
- db
......@@ -48,8 +29,8 @@ services:
# default username/password is postgres/postgres
restart: always
image: postgres:9.6
container_name: ps_01
container_name: postgres_container
expose:
- "5432"
volumes:
- pgdata:/var/lib/postgresql/data/
- data:/var/lib/postgresql/data/
upstream web {
ip_hash;
server gunicorn:8000; # match the Django service in docker-compose.yml
}
server {
server_name oser-cs.fr;
listen 8000;
location /static/ {
# Serve static files
autoindex on;
alias /static/;
}
location /media/ {
# Serve user uploaded media
autoindex on;
alias /media/;
}
location / {
# Pass requests to the Gunicorn server running the Django app
# (upstream web is defined at top of file)
proxy_pass http://web;
# Send full host in header (default is service name, i.e. gunicorn).
# Ensures that absolute URLs on Django app are accessible (e.g. in
# discoverable API).
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
......@@ -4,14 +4,11 @@
.idea
.travis.yml
.build
.env
media/
README.md
LICENSE
# Databases
**/*.sqlite
**/*.sqlite3
# Static files (will be collected inside container)
static/
......
from python:3.6
from python:3.6-alpine
# postgresql dependencies on Linux Alpine
RUN apk update && apk add build-base postgresql-dev libffi-dev
# pillow dependencies on Linux Alpine
RUN apk add --no-cache jpeg-dev zlib-dev
EXPOSE 8000
ENV PYTHONUNBUFFERED=1
# set port to 8000 if not defined (e.g. in development)
ENV PORT=${PORT:-8000}
ADD . /oser-backend
WORKDIR /oser-backend/oser_backend
# Install dependencies
RUN echo "Installing dependencies..." && pip3 install -r ../requirements.txt && pip3 install gunicorn
WORKDIR oser-backend/oser_backend
# Migrations are not run here
# They should be run once the container have started
RUN ls
RUN echo "Collecting static files..." && python manage.py collectstatic --noinput
# Install dependencies
RUN pip3 install -r ../requirements.txt
RUN pip3 install gunicorn
# Run app as non-root user
RUN adduser -D user
USER user
CMD sh ../start.sh
'''
"""
Django settings for oser_backend project.
Base settings common to all environments.
'''
"""
import os
import dj_database_url
from django.contrib.messages import constants as messages
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
......@@ -33,6 +34,7 @@ DJANGO_APPS = [
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'whitenoise.runserver_nostatic',
'django.contrib.staticfiles',
'django.forms',
]
......@@ -70,6 +72,7 @@ MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
......@@ -144,22 +147,9 @@ MARKDOWNX_MARKDOWN_EXTENSION_CONFIGS = {
}
# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# }
# }
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'postgres',
'USER': 'postgres',
'HOST': 'db',
'PORT': 5432,
}
'default': dj_database_url.config(conn_max_age=600),
}
# Authentication
......@@ -172,7 +162,6 @@ AUTHENTICATION_BACKENDS = [
# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
......@@ -202,9 +191,9 @@ USE_TZ = True
# https://docs.djangoproject.com/en/2.0/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(dn(BASE_DIR), 'static')
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
# User-uploaded media files
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(dn(BASE_DIR), 'media')
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
import os
import django_heroku
from .default import *
DEBUG = False
ALLOWED_HOSTS = ['florimondmanca.pythonanywhere.com', 'localhost']
DEBUG = True
ALLOWED_HOSTS = ['florimondmanca.pythonanywhere.com', 'localhost',
'lit-dusk-75348.herokuapp.com']
django_heroku.settings(locals())
......@@ -11,7 +11,11 @@ import os
from django.core.wsgi import get_wsgi_application
from whitenoise import WhiteNoise
os.environ.setdefault("DJANGO_SETTINGS_MODULE",
"oser_backend.settings.production")
application = get_wsgi_application()
application = WhiteNoise(application,
root='/oser-backend/oser_backend/static/')
"""Test the authentication mechanism used by the API."""
from rest_framework import status
from rest_framework.test import APITestCase, RequestsClient
from rest_framework.test import APITestCase
from users.factory import UserFactory
from users.serializers import UserSerializer
......@@ -17,9 +17,6 @@ class TestTokenAuth(APITestCase):
def setUp(self):
super().setUp()
# Use the raw Requests client (named after the Python library)
# to make requests as an external client
self.client = RequestsClient()
# create a fake user
self.fake_password = 'pass'
self.user = UserFactory.create(password=self.fake_password)
......@@ -29,15 +26,14 @@ class TestTokenAuth(APITestCase):
'username': self.user.email,
'password': self.fake_password
}
response = self.client.post(
'http://testserver/api/auth/get-token/',
data=post_data)
response = self.client.post('/api/auth/get-token/', data=post_data)
return response
def test_get_token(self):
"""Test retrieving the auth token from email/password."""
response = self.perform_get_token()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.status_code, status.HTTP_200_OK,
response.data)
self.assertIn('token', response.json())
token = response.json().get('token')
self.assertIsNotNone(token)
......@@ -56,9 +52,8 @@ class TestTokenAuth(APITestCase):
"""Test once authenticated, the token can be used in the API."""
token_response = self.perform_get_token()
token = token_response.json().get('token')
self.client.credentials(HTTP_AUTHORIZATION='Token ' + token)
# get some data using the token
response = self.client.get(
'http://testserver/api/users/',
headers={'Authorization': 'Token ' + token},
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
response = self.client.get('/api/users/')
self.assertEqual(response.status_code, status.HTTP_200_OK,
response.data)
"""Users tests."""
from django.contrib.auth import get_user_model
from django.db import IntegrityError
from django.test import TestCase
from tests.utils import ModelTestCase
......@@ -90,9 +89,9 @@ class UserModelTest(ModelTestCase):
def test_two_users_with_same_email_not_allowed(self):
same_email = 'same.email@example.net'
with self.assertRaises(IntegrityError):
UserFactory.create(email=same_email)
UserFactory.create(email=same_email)
_, created = User.objects.get_or_create(email=same_email)
self.assertFalse(created)
def test_visits_relationship(self):
self.assertEqual(self.obj.visit_set.all().count(), 0)
......@@ -4,6 +4,7 @@ from django.db import models
from django.shortcuts import reverse
from django.utils.timezone import now
from dry_rest_permissions.generics import authenticated_users
from markdownx.models import MarkdownxField
utc = pytz.UTC
......@@ -66,7 +67,8 @@ class VisitParticipant(models.Model):
unique_together = (('user', 'visit'),)
def get_absolute_url(self):
return reverse('api:visit-participants-detail', args=[str(self.pk)])
return reverse('api:visit-participants-detail',
args=[str(self.visit.pk)])
# Permissions
......@@ -181,7 +183,9 @@ class Visit(models.Model):
@property
def organizers_group_name(self):
return 'Organisateurs - {} : {}'.format(self.id, self.title)
group_name = 'Organisateurs - {} : {}'.format(self.id, self.title)
# limit group name to 80 characters (i.e. Group.name.max_length)
return group_name[:80]
class Meta: # noqa
ordering = ('date',)
......
......@@ -10,3 +10,6 @@ django-guardian>~1.4.9
django-admin-sortable2>=0.6.19
pymdown-extensions>=4.8
psycopg2
dj-database-url
whitenoise
django-heroku
#!/usr/bin/env bash
echo "Migrating database"
python manage.py makemigrations
python manage.py migrate
echo "Initializing admin"
python manage.py initadmin
echo "Collecting static files"
python manage.py collectstatic --noinput
# Run server
exec gunicorn oser_backend.wsgi:application \
--bind 0.0.0.0:8000 \
--bind 0.0.0.0:$PORT \
--workers 3 \
--access-logfile=- \
--reload
--reload \
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment