diff --git a/Dockerfile.base b/Dockerfile.base new file mode 100644 index 00000000000..79a3cc89995 --- /dev/null +++ b/Dockerfile.base @@ -0,0 +1,54 @@ +# Read the Docs - Environment base +# docker build -f Dockerfile.base -t readthedocs/build:docker-compose --build-arg UID=1000 --build-arg GID=100 --build-arg GROUPNAME=users --build-arg DOCKER_GID=991 . + +FROM ubuntu:16.04 +MAINTAINER Read the Docs + +ARG UID=1000 +ARG GID=100 +ARG GROUPNAME=users +ARG DOCKER_GID=991 + +ENV LANG C.UTF-8 + +# System dependencies +RUN apt-get -y update + +# Install requirements +RUN apt-get -y install \ + git-core \ + postgresql-client + +# Install Python tools/libs +RUN apt-get -y install python-pip + +RUN apt-get -y install wget + +RUN apt-get -y install python3 python3-venv +RUN apt-get -y install libxml2-dev libxslt-dev zlib1g-dev + + +# https://github.com/rtfd/readthedocs.org/pull/3152#issuecomment-339573168 +# RUN groupadd --gid ${GID} ${GROUPNAME} +RUN useradd --uid ${UID} --gid ${GID} docs + +# Create the `docker` group with our specific GID +RUN groupadd --gid ${DOCKER_GID} docker + +# Add `docs` user to the `docker` group so it run containers +RUN gpasswd -a docs docker +RUN apt-get -y install docker.io + +# Download latest pip requirements for the project +RUN pip install -U pip +RUN wget https://raw.githubusercontent.com/rtfd/readthedocs.org/master/requirements/pip.txt -O requirements.txt +RUN pip install -r requirements.txt + +# Install some python utilities +RUN pip install ipdb dj-cmd + +USER docs +WORKDIR /home/docs/readthedocs.org + + +CMD ["/bin/bash"] diff --git a/Dockerfile.devbuild b/Dockerfile.devbuild new file mode 100644 index 00000000000..a38c78113d7 --- /dev/null +++ b/Dockerfile.devbuild @@ -0,0 +1,16 @@ +# Read the Docs - Environment base +# docker build -f Dockerfile.devbuild -t readthedocs/build:dev --build-arg UID=1000 --build-arg GID=100 --build-arg GROUPNAME=users . + +FROM readthedocs/build:2.0 + +ARG UID=1000 +ARG GID=100 +ARG GROUPNAME=users + +# https://github.com/rtfd/readthedocs.org/pull/3152#issuecomment-339573168 +USER root +# RUN groupadd --gid ${GID} ${GROUPNAME} +RUN usermod --uid ${UID} --gid ${GID} docs +USER docs + +CMD ["/bin/bash"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000000..12e286b5d16 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,27 @@ +version: '3.3' + +services: + + readthedocs: + image: readthedocs/build:docker-compose + command: "./docker/run.sh" + ports: + - "8000:8000" + - "8088:8088" + links: + - redis + volumes: + # mount docker unix socket to be able to run containers in the host from inside this container + - /var/run/docker.sock:/var/run/docker.sock + - .:/home/docs/readthedocs.org + environment: + DJANGO_SETTINGS_MODULE: readthedocs.settings.docker + DJANGO_SETTINGS_SKIP_LOCAL: 1 + + + # DEPENDENCIES + + redis: + image: redis + + # TODO: run celery workers diff --git a/docker/create_superuser.py b/docker/create_superuser.py new file mode 100644 index 00000000000..c13325eb18f --- /dev/null +++ b/docker/create_superuser.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- + +from django.contrib.auth.models import User +from allauth.account.models import EmailAddress + +query = User.objects.filter(username='admin') +if not query.exists(): + admin = User.objects.create_superuser('admin', 'admin@example.com', 'admin') + EmailAddress.objects.create(user=admin, email='admin@example.com', primary=True, verified=True) + print('`admin` user created') +else: + print('`admin` user already exists') + +print('Exit.') diff --git a/docker/run.sh b/docker/run.sh new file mode 100755 index 00000000000..82b2b78a08f --- /dev/null +++ b/docker/run.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +pip install -r requirements.txt + +python manage.py migrate + +python manage.py shell < docker/create_superuser.py + +python manage.py collectstatic --noinput +python manage.py loaddata test_data + +python manage.py runserver 0.0.0.0:8000 diff --git a/readthedocs/settings/docker.py b/readthedocs/settings/docker.py new file mode 100644 index 00000000000..1fcdf16382c --- /dev/null +++ b/readthedocs/settings/docker.py @@ -0,0 +1,86 @@ +"""Local development settings, including local_settings, if present.""" +from __future__ import absolute_import +import os + +from .base import CommunityBaseSettings + + +class CommunityDevSettings(CommunityBaseSettings): + + """Settings for local development""" + + PRODUCTION_DOMAIN = '0.0.0.0:8000' + WEBSOCKET_HOST = '0.0.0.0:8088' + + @property + def DATABASES(self): # noqa + return { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(self.SITE_ROOT, 'docker.db'), + } + } + + DONT_HIT_DB = False + + SESSION_COOKIE_DOMAIN = None + CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', + 'PREFIX': 'docs', + } + } + + SLUMBER_USERNAME = 'test' + SLUMBER_PASSWORD = 'test' # noqa: ignore dodgy check + SLUMBER_API_HOST = 'http://0.0.0.0:8000' + PUBLIC_API_URL = 'http://0.0.0.0:8000' + + BROKER_URL = 'redis://redis:6379/0' + CELERY_RESULT_BACKEND = 'redis://redis:6379/0' + CELERY_RESULT_SERIALIZER = 'json' + CELERY_ALWAYS_EAGER = True + + HAYSTACK_CONNECTIONS = { + 'default': { + 'ENGINE': 'haystack.backends.simple_backend.SimpleEngine', + }, + } + + EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' + FILE_SYNCER = 'readthedocs.builds.syncers.LocalSyncer' + + # For testing locally. Put this in your /etc/hosts: + # 127.0.0.1 test + # and navigate to http://test:8000 + CORS_ORIGIN_WHITELIST = ( + 'test:8000', + ) + + # Build documentation using docker image + DOCKER_ENABLE = True + + # https://github.com/rtfd/readthedocs.org/pull/3152#issuecomment-339573168 + DOCKER_IMAGE = 'readthedocs/build:dev' + + # https://github.com/rtfd/readthedocs.org/pull/3243#issuecomment-343551486 + DOCKER_VERSION = '1.17' + + + @property + def LOGGING(self): # noqa - avoid pep8 N802 + logging = super(CommunityDevSettings, self).LOGGING + logging['formatters']['default']['format'] = '[%(asctime)s] ' + self.LOG_FORMAT + # Remove double logging + logging['loggers']['']['handlers'] = [] + return logging + + +CommunityDevSettings.load_settings(__name__) + +if not os.environ.get('DJANGO_SETTINGS_SKIP_LOCAL', False): + try: + # pylint: disable=unused-wildcard-import + from .local_settings import * # noqa + except ImportError: + pass