From bbf85c79b895f87c4a8135279d15db721f23d3f8 Mon Sep 17 00:00:00 2001
From: Tom Downes <tpdownes@gmail.com>
Date: Tue, 4 Dec 2018 21:17:38 -0600
Subject: [PATCH] Initial commit to containerize GraceDb

---
 .dockerignore               |  1 +
 .gitlab-ci.yml              | 29 +++++++++++++++++++++++++
 Dockerfile                  | 43 +++++++++++++++++++++++++++++++++++++
 config/settings/__init__.py |  6 +++---
 config/settings/base.py     | 27 ++++++++++++-----------
 config/wsgi.py              |  7 +++---
 6 files changed, 95 insertions(+), 18 deletions(-)
 create mode 100644 .dockerignore
 create mode 100644 .gitlab-ci.yml
 create mode 100644 Dockerfile

diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 000000000..6b8710a71
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1 @@
+.git
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 000000000..fbb993ad8
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,29 @@
+---
+image: docker:latest
+
+variables:
+  DOCKER_DRIVER: overlay
+  DOCKER_BRANCH: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
+  DOCKER_LATEST: $CI_REGISTRY_IMAGE:latest
+
+stages:
+  - branch
+  - latest
+
+branch_image:
+  stage: branch
+  script:
+    - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
+    - docker build --pull -t $DOCKER_BRANCH .
+    - docker push $DOCKER_BRANCH
+
+latest_image:
+  stage: latest
+  dependencies:
+    - branch_image
+  only:
+    refs:
+      - master
+  script:
+    - docker tag $DOCKER_BRANCH $DOCKER_LATEST
+    - docker push $DOCKER_LATEST
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 000000000..9f026d560
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,43 @@
+FROM ligo/base:stretch
+LABEL name="LIGO GraceDB Django application" \
+      maintainer="tanner.prestegard@ligo.org" \
+      date="20180215"
+WORKDIR /app
+ADD . /app/gracedb_project
+
+# Volumes
+VOLUME /app/logs /app/project_data
+
+RUN apt-get update
+RUN apt-get install --assume-yes gcc \
+        python2.7 \
+        python-pip \
+        mariadb-client \
+        libmariadbclient-dev \
+        libldap2-dev \
+        libsasl2-dev \
+        libxml2-dev \
+        libsqlite3-dev \
+        python-glue \
+        python-pylal \
+        python-voeventlib
+
+# Install npm, bower, bower_components
+RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
+RUN apt-get update && \
+  apt-get install nodejs && \
+  apt-get clean && \
+  npm install -g bower
+
+# Install Python packages
+RUN pip install -r ./gracedb_project/requirements.txt
+EXPOSE 8000
+
+# Give pip-installed packages priority over distribution packages
+ENV PYTHONPATH /usr/local/lib/python2.7/dist-packages:$PYTHONPATH
+ENV VIRTUAL_ENV dummy
+
+# Set WORKDIR and run Gunicorn
+WORKDIR /app/gracedb_project
+#RUN python manage.py collectstatic --noinput
+CMD ["gunicorn", "--reload", "--bind", "0.0.0.0:8000", "config.wsgi:application"]
diff --git a/config/settings/__init__.py b/config/settings/__init__.py
index 1f665b4db..e1b6ddcda 100644
--- a/config/settings/__init__.py
+++ b/config/settings/__init__.py
@@ -24,10 +24,10 @@ try:
     if IS_PRODUCTION_SERVER:
         settings_file = 'production'
     else:
-        # If ./local.py is not found or IS_PRODUCTION_SERVER
-        # is not defined, use development/test settings
+        # If IS_PRODUCTION_SERVER is not defined, use development/test settings
         settings_file = 'dev'
-except NameError:
+except ImportError:
+    # If local.py does not exist, use development/test settings
     settings_file = 'dev'
 settings_module = __import__(settings_file, globals(), locals())
 
diff --git a/config/settings/base.py b/config/settings/base.py
index 07bcf5543..ad7b35bbf 100644
--- a/config/settings/base.py
+++ b/config/settings/base.py
@@ -16,6 +16,9 @@ BASE_DIR = abspath(join(dirname(__file__), "..", ".."))
 CONFIG_ROOT = join(BASE_DIR, "config")
 PROJECT_ROOT = join(BASE_DIR, "gracedb")
 
+# Other useful paths
+PROJECT_DATA_DIR = join(BASE_DIR, "..", "project_data")
+
 # Unauthenticated access ------------------------------------------------------
 # This variable controls whether unauthenticated access is allowed *ANYWHERE*
 # on this service, except the home page, which is always public.
@@ -196,16 +199,15 @@ SKYALERT_SUBMITTERS = ['Patrick Brady', 'Brian Moe']
 # Stuff related to report/plot generation -------------------------------------
 
 # Latency histograms.  Where they go and max latency to bin.
-LATENCY_REPORT_DEST_DIR = GRACEDB_PATHS["latency"]
+LATENCY_REPORT_DEST_DIR = PROJECT_DATA_DIR
 LATENCY_MAXIMUM_CHARTED = 1800
-LATENCY_REPORT_WEB_PAGE_FILE_PATH = join(LATENCY_REPORT_DEST_DIR,
-    "latency.inc")
+LATENCY_REPORT_WEB_PAGE_FILE_PATH = join(PROJECT_DATA_DIR, "latency.inc")
 
 # Uptime reporting
-UPTIME_REPORT_DIR = GRACEDB_PATHS["uptime"]
+UPTIME_REPORT_DIR = PROJECT_DATA_DIR
 
 # Rate file location
-RATE_INFO_FILE = join(GRACEDB_PATHS["data"], "rate_info.json")
+RATE_INFO_FILE = join(PROJECT_DATA_DIR, "rate_info.json")
 
 # URL prefix for serving report information (usually plots and tables)
 # This is aliased to GRACEDB_PATHS["latency"] in the Apache virtualhost
@@ -213,11 +215,11 @@ RATE_INFO_FILE = join(GRACEDB_PATHS["data"], "rate_info.json")
 REPORT_INFO_URL_PREFIX = "/report_info/"
 
 # Directory for CBC IFAR Reports
-REPORT_IFAR_IMAGE_DIR = GRACEDB_PATHS["latency"]
+REPORT_IFAR_IMAGE_DIR = PROJECT_DATA_DIR
 
 # Stuff for the new rates plot
 BINNED_COUNT_PIPELINES = ['gstlal', 'MBTAOnline', 'CWB', 'oLIB', 'spiir']
-BINNED_COUNT_FILE = join(GRACEDB_PATHS["data"], "binned_counts.json")
+BINNED_COUNT_FILE = join(PROJECT_DATA_DIR, "binned_counts.json")
 
 # Defaults for RSS feed
 FEED_MAX_RESULTS = 50
@@ -238,7 +240,7 @@ DATABASES = {
 }
 
 # Location of database
-GRACEDB_DATA_DIR = GRACEDB_PATHS["database_data"]
+GRACEDB_DATA_DIR = join(BASE_DIR, "..", "db_data")
 # First level subdirs with 2 chars, second level with 1 char
 # These DIR_DIGITS had better add up to a number less than 40 (which is
 # the length of a SHA-1 hexdigest. Actually, it should be way less than
@@ -465,7 +467,7 @@ PASSWORD_EXPIRATION_TIME = timedelta(days=365)
 
 # IP addresses of IFO control rooms
 # Used to display signoff pages for operators
-# TP (10 Apr 2017): Virgo IP received from Florent Robinet, Franco Carbognani, 
+# TP (10 Apr 2017): Virgo IP received from Florent Robinet, Franco Carbognani,
 # and Sarah Antier. Corresponds to ctrl1.virgo.infn.it.
 CONTROL_ROOM_IPS = {
     'H1': '198.129.208.178',
@@ -481,6 +483,7 @@ LOG_FILE_BAK_CT = 10
 LOG_FORMAT = 'extra_verbose'
 LOG_LEVEL = 'DEBUG'
 LOG_DATEFMT = '%Y-%m-%d %H:%M:%S'
+LOG_DIR = abspath(join(BASE_DIR, "..", "logs"))
 
 # Note that mode for log files is 'a' (append) by default
 # The 'level' specifier on the handle is optional, and we
@@ -511,7 +514,7 @@ LOGGING = {
         'debug_file': {
             'class': 'logging.handlers.ConcurrentRotatingFileHandler',
             'formatter': LOG_FORMAT,
-            'filename': join(GRACEDB_PATHS["logs"], "gracedb_debug.log"),
+            'filename': join(LOG_DIR, "gracedb_debug.log"),
             'maxBytes': (20*1024*1024),
             'backupCount': LOG_FILE_BAK_CT,
             'level': 'DEBUG',
@@ -519,7 +522,7 @@ LOGGING = {
         'error_file': {
             'class': 'logging.handlers.ConcurrentRotatingFileHandler',
             'formatter': LOG_FORMAT,
-            'filename': join(GRACEDB_PATHS["logs"], "gracedb_error.log"),
+            'filename': join(LOG_DIR, "gracedb_error.log"),
             'maxBytes': LOG_FILE_SIZE,
             'backupCount': LOG_FILE_BAK_CT,
             'level': 'ERROR',
@@ -529,7 +532,7 @@ LOGGING = {
             'maxBytes': 1024*1024,
             'backupCount': 1,
             'formatter': 'simple',
-            'filename': join(GRACEDB_PATHS["logs"], "gracedb_performance.log"),
+            'filename': join(LOG_DIR, "gracedb_performance.log"),
         },
         'mail_admins': {
             'level': 'ERROR',
diff --git a/config/wsgi.py b/config/wsgi.py
index 1700c59cf..38eb90c54 100644
--- a/config/wsgi.py
+++ b/config/wsgi.py
@@ -18,9 +18,10 @@ sys.path.append(BASE_DIR)
 sys.path.append(join(BASE_DIR, PROJECT_ROOT_NAME))
 
 # Activate the virtual environment
-VIRTUALENV_ACTIVATOR = abspath(join(BASE_DIR, '..', VENV_NAME, 'bin',
-    'activate_this.py'))
-execfile(VIRTUALENV_ACTIVATOR, dict(__file__=VIRTUALENV_ACTIVATOR))
+if ('VIRTUAL_ENV' not in os.environ):
+    VIRTUALENV_ACTIVATOR = abspath(join(BASE_DIR, '..', VENV_NAME, 'bin',
+        'activate_this.py'))
+    execfile(VIRTUALENV_ACTIVATOR, dict(__file__=VIRTUALENV_ACTIVATOR))
 
 # Matplotlib config directory
 os.environ['MPLCONFIGDIR'] = '/tmp/'
-- 
GitLab