diff --git a/Dockerfile b/Dockerfile index e7d9e9d43f4..11d254014cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,14 @@ -FROM python:2.7.9 +FROM python:2.7 + +ENV POSTGRES_VERSION 9.5 # This section is borrowed from the official Django image but adds GDAL and others -RUN apt-get update && apt-get install -y \ +RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main" > /etc/apt/sources.list.d/postgres.list \ + && wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ + && apt-get update && apt-get install -y \ gcc \ gettext \ - postgresql-client libpq-dev \ + postgresql-client-${POSTGRES_VERSION} libpq-dev \ sqlite3 \ python-gdal python-psycopg2 \ python-imaging python-lxml \ @@ -12,49 +16,45 @@ RUN apt-get update && apt-get install -y \ python-ldap \ libmemcached-dev libsasl2-dev zlib1g-dev \ python-pylibmc \ - --no-install-recommends && rm -rf /var/lib/apt/lists/* - -# Install pg client -ENV POSTGRES_VERSION 9.5 -RUN apt-get update \ - && apt-get install -y wget \ - && echo "deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main" > /etc/apt/sources.list.d/postgres.list \ - && wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ - && apt-get update \ - && apt-get install -y postgresql-client-${POSTGRES_VERSION} + wget \ + --no-install-recommends \ + && rm -rf /var/lib/apt/lists/* -COPY package/docker/wait-for-postgres.sh /usr/bin/wait-for-postgres -RUN chmod +x /usr/bin/wait-for-postgres +#COPY package/docker/wait-for-postgres.sh /usr/bin/wait-for-postgres -RUN mkdir /docker-entrypoint.d -COPY package/docker/docker-entrypoint.sh /docker-entrypoint.sh -COPY package/docker/00-bootstrap-dbs.sh /docker-entrypoint.d/ +#RUN mkdir /docker-entrypoint.d +#COPY package/docker/docker-entrypoint.sh /docker-entrypoint.sh +COPY package/docker/ / # To understand the next section (the need for requirements.txt and setup.py) # Please read: https://packaging.python.org/requirements/ # Update pip -RUN pip install --upgrade pip - +RUN pip install --upgrade pip \ # python-gdal does not seem to work, let's install manually the version that is # compatible with the provided libgdal-dev -RUN pip install GDAL==1.10 --global-option=build_ext --global-option="-I/usr/include/gdal" + && pip install GDAL==1.10 --global-option=build_ext --global-option="-I/usr/include/gdal" \ +# install gunicorn for production setup + && pip install gunicorn + +EXPOSE 8000 +ENTRYPOINT ["/docker-entrypoint.sh"] +CMD ["django-admin.py", "runserver", "0.0.0.0:8000", "--settings=geonode.settings"] # Install geonode code and dependencies RUN mkdir -p /usr/src/app WORKDIR /usr/src/app -COPY . /usr/src/app/ +COPY requirements.txt /usr/src/app/ RUN pip install --no-cache-dir -r requirements.txt +COPY . /usr/src/app/ RUN pip install --no-cache-dir --no-deps -e /usr/src/app/ # Install geonode configuration -VOLUME ["/mnt/geonode_config", "/mnt/geonode_data"] RUN mkdir -p /mnt/geonode_data/uploaded /mnt/geonode_data/static /mnt/geonode_config \ && cd /usr/src/app/geonode/ \ - && mv local_settings.py /mnt/geonode_config/ \ + && cp local_settings.py.docker /mnt/geonode_config/local_settings.py \ + && mv local_settings.py local_settings.py.old \ && ln -s /mnt/geonode_config/local_settings.py +VOLUME ["/mnt/geonode_config", "/mnt/geonode_data"] -EXPOSE 8000 -ENTRYPOINT ["/docker-entrypoint.sh"] -CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] diff --git a/docker-compose.yml b/docker-compose.yml index b59ce6da908..2aea26d333a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -27,7 +27,9 @@ services: - database - elasticsearch - rabbitmq - command: django-admin.py runserver 0.0.0.0:8000 --settings=geonode.settings + - geoserver +# uncomment following line for production setup +# command: gunicorn geonode.wsgi --forwarded-allow-ips=* --workers=3 --bind=0.0.0.0 --worker-tmp-dir=/tmp --access-logfile=- --error-logfile=- ports: - "8000:8000" environment: @@ -45,6 +47,9 @@ services: - DB_GEOSERVER_NAME=geoserver - DB_GEOSERVER_USER=geoserver - DB_GEOSERVER_PASSWORD=secret + volumes: + - geonode_config:/mnt/geonode_config + - geonode_data:/mnt/geonode_data celery: image: camptocamp/geonode_django @@ -68,7 +73,6 @@ services: image: camptocamp/geonode_geoserver links: - database - - django ports: - "8080:8080" volumes: @@ -80,3 +84,5 @@ volumes: geoserver_datadir: geoserver_data: postgresql_data: + geonode_data: + geonode_config: diff --git a/geonode/local_settings.py.docker b/geonode/local_settings.py.docker new file mode 100644 index 00000000000..6e1662303e3 --- /dev/null +++ b/geonode/local_settings.py.docker @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# wb-django:/etc/geonode/local_settings.py +import os +import geonode + +# Setting debug to true makes Django serve static media and +# present pretty error pages. +DEBUG = True + +# Set to True to load non-minified versions of (static) client dependencies +# Requires to set-up Node and tools that are required for static development +# otherwise it will raise errors for the missing non-minified dependencies +DEBUG_STATIC = False + +SITENAME = 'GeoNode' +SITEURL = 'http://localhost:8000/' +PROXY_URL = None +GEONODE_ROOT = os.path.dirname(geonode.__file__) + +DATABASE_HOST = os.getenv('DB_HOST', 'database') +DATABASE_PORT = os.getenv('DB_PORT', '5432') + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': os.getenv('DB_GEONODE_NAME', 'geonode'), + 'USER': os.getenv('DB_GEONODE_USER', 'geonode'), + 'PASSWORD': os.getenv('DB_GEONODE_PASSWORD', 'secret'), + 'HOST': DATABASE_HOST, + 'PORT': DATABASE_PORT, + }, + 'datastore': { + 'ENGINE': 'django.contrib.gis.db.backends.postgis', + 'NAME': os.getenv('DB_GEOSERVER_NAME', 'geoserver'), + 'USER': os.getenv('DB_GEOSERVER_USER', 'geoserver'), + 'PASSWORD': os.getenv('DB_GEOSERVER_PASSWORD', 'secret'), + 'HOST': DATABASE_HOST, + 'PORT': DATABASE_PORT, + } +} + +GEOSERVER_PUBLIC_LOCATION = 'http://localhost:8080/geoserver/' +GEOSERVER_INTERNAL_LOCATION = 'http://geoserver:8080/geoserver/' +GEOSERVER_URL = GEOSERVER_PUBLIC_LOCATION + +# OGC (WMS/WFS/WCS) Server Settings +OGC_SERVER = { + 'default': { + 'BACKEND': 'geonode.geoserver', + 'LOCATION': GEOSERVER_INTERNAL_LOCATION, + 'LOGIN_ENDPOINT': '', #'j_spring_oauth2_geonode_login', + 'LOGOUT_ENDPOINT': '', #'j_spring_oauth2_geonode_logout', + 'PUBLIC_LOCATION': GEOSERVER_URL, + 'USER': 'admin', + 'PASSWORD': os.getenv('GEOSERVER_ADMIN_PASSWORD', 'secret'), + 'MAPFISH_PRINT_ENABLED': True, + 'PRINT_NG_ENABLED': True, + 'GEONODE_SECURITY_ENABLED': True, + 'GEOGIG_ENABLED': False, + 'WMST_ENABLED': False, + 'BACKEND_WRITE_ENABLED': True, + 'WPS_ENABLED': True, + #'LOG_FILE': '/usr/share/geoserver/data/logs/geoserver.log', + # Set to name of database in DATABASES dictionary to enable + 'DATASTORE': 'datastore', + 'PG_GEOGIG': False, + 'TIMEOUT': 10, + } +} + +LANGUAGE_CODE = 'en' + +MEDIA_ROOT = '/mnt/geonode_data/uploaded/' +STATIC_ROOT = '/mnt/geonode_data/static/' + +# secret key used in hashing, should be a long, unique string for each +# site. See http://docs.djangoproject.com/en/1.2/ref/settings/#secret-key +SECRET_KEY = 'SVp7KiF6FKaymGw1en' + + +CATALOGUE = { + 'default': { + # The underlying CSW backend + # ("pycsw_http", "pycsw_local", "geonetwork", "deegree") + 'ENGINE': 'geonode.catalogue.backends.pycsw_local', + # The FULLY QUALIFIED base url to the CSW instance for this GeoNode + 'URL': '%scatalogue/csw' % SITEURL, + } +} + +# A Google Maps API key is needed for the 3D Google Earth view of maps +# See http://code.google.com/apis/maps/signup.html +GOOGLE_API_KEY = '' + +# Django automatically includes the "templates" dir in all the INSTALLED_APPS. +TEMPLATES = [ + { + 'NAME': 'GeoNode Project Templates', + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': ['/mnt/geonode_config/templates', os.path.join(GEONODE_ROOT, "templates")], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.contrib.auth.context_processors.auth', + 'django.core.context_processors.debug', + 'django.core.context_processors.i18n', + 'django.core.context_processors.tz', + 'django.core.context_processors.media', + 'django.core.context_processors.static', + 'django.core.context_processors.request', + 'django.contrib.messages.context_processors.messages', + 'account.context_processors.account', + 'geonode.context_processors.resource_urls', + 'geonode.geoserver.context_processors.geoserver_urls', + ], + 'debug': DEBUG, + }, + }, +] +# Additional directories which hold static files +STATICFILES_DIRS = [ + '/mnt/geonode_config/media', + os.path.join(GEONODE_ROOT, 'static'), +] + +MAP_BASELAYERS = [{ + "source": { + "ptype": "gxp_wmscsource", + "url": GEOSERVER_URL + "wms", + "restUrl": "/gs/rest" + } + },{ + "source": {"ptype": "gxp_olsource"}, + "type":"OpenLayers.Layer", + "args":["No background"], + "visibility": False, + "fixed": True, + "group":"background" + }, { + "source": {"ptype": "gxp_olsource"}, + "type":"OpenLayers.Layer.OSM", + "args":["OpenStreetMap"], + "visibility": False, + "fixed": True, + "group":"background" + }, { + "source": {"ptype": "gxp_mapquestsource"}, + "name":"osm", + "group":"background", + "visibility": False + }, { + "source": {"ptype": "gxp_mapquestsource"}, + "name":"naip", + "group":"background", + "visibility": False + }, { + "source": {"ptype": "gxp_olsource"}, + "type":"OpenLayers.Layer.XYZ", + "group":"background", + "visibility": True, + "fixed": True, + "args":[ "mapbox", + ["https://a.tiles.mapbox.com/v4/ingenieroariel.m9a2h374/${z}/${x}/${y}.png?access_token=pk.eyJ1IjoiaW5nZW5pZXJvYXJpZWwiLCJhIjoibXhDZ3pIMCJ9.qTmPYCbnUKtaNFkvKKysAQ", + "https://b.tiles.mapbox.com/v4/ingenieroariel.m9a2h374/${z}/${x}/${y}.png?access_token=pk.eyJ1IjoiaW5nZW5pZXJvYXJpZWwiLCJhIjoibXhDZ3pIMCJ9.qTmPYCbnUKtaNFkvKKysAQ", + "https://c.tiles.mapbox.com/v4/ingenieroariel.m9a2h374/${z}/${x}/${y}.png?access_token=pk.eyJ1IjoiaW5nZW5pZXJvYXJpZWwiLCJhIjoibXhDZ3pIMCJ9.qTmPYCbnUKtaNFkvKKysAQ"], + {"transitionEffect": "resize","attribution": "osm_attribution"} + ] +}] + +#REGISTRATION_OPEN = False +#ACCOUNT_APPROVAL_REQUIRED = False + +#ACCOUNT_EMAIL_CONFIRMATION_EMAIL = False +#ACCOUNT_EMAIL_CONFIRMATION_REQUIRED = False + +# Allowed values for the preview library are 'geoext' and 'leaflet'. +#LAYER_PREVIEW_LIBRARY = 'geoext' + +# Uncomment the following to receive emails whenever there are errors in GeoNode +# or to be notified of new user requests when ACCOUNT_APPROVAL_REQUIRED has been set. +#ADMINS = ( +# ('John', 'john@example.com'), +# ) + +# Uncomment the following to use a Gmail account as the email backend +#EMAIL_USE_TLS = True +#EMAIL_HOST = 'smtp.gmail.com' +#EMAIL_HOST_USER = 'youremail@gmail.com' +#EMAIL_HOST_PASSWORD = 'yourpassword' +#EMAIL_PORT = 587 + +# For more information on available settings please consult the Django docs at +# https://docs.djangoproject.com/en/dev/ref/settings +# Handle by env vars +#ALLOWED_HOSTS= [ 'localhost', ] diff --git a/package/docker/00-bootstrap-dbs.sh b/package/docker/docker-entrypoint.d/00-bootstrap-dbs.sh similarity index 96% rename from package/docker/00-bootstrap-dbs.sh rename to package/docker/docker-entrypoint.d/00-bootstrap-dbs.sh index 446716ecf98..d85ff323893 100755 --- a/package/docker/00-bootstrap-dbs.sh +++ b/package/docker/docker-entrypoint.d/00-bootstrap-dbs.sh @@ -40,6 +40,9 @@ else python manage.py migrate account --noinput python manage.py migrate --noinput + echo " Populate db with admin:admin account and some categories" + paver sync + fi # Check if geoserver database exists diff --git a/package/docker/wait-for-postgres.sh b/package/docker/wait-for-postgres.sh deleted file mode 100644 index a3cd815dd2c..00000000000 --- a/package/docker/wait-for-postgres.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -set -e - -host="$1" -shift -cmd="$@" - -until psql -h "$host" -U "postgres" -c '\l'; do - >&2 echo "Postgres is unavailable - sleeping" - sleep 1 -done - ->&2 echo "Postgres is up - executing command" -exec $cmd