init
This commit is contained in:
commit
b2eca58f38
13 changed files with 477 additions and 0 deletions
71
Dockerfile
Normal file
71
Dockerfile
Normal file
|
@ -0,0 +1,71 @@
|
|||
FROM node:12 AS vendors
|
||||
|
||||
COPY . /srv/umap
|
||||
|
||||
WORKDIR /srv/umap
|
||||
|
||||
RUN make installjs
|
||||
|
||||
RUN make vendors
|
||||
|
||||
FROM python:3.8-slim
|
||||
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
UMAP_SETTINGS=/srv/umap/umap/settings/docker.py \
|
||||
PORT=8000
|
||||
|
||||
RUN mkdir -p /srv/umap/data && \
|
||||
mkdir -p /srv/umap/uploads
|
||||
|
||||
COPY . /srv/umap
|
||||
|
||||
COPY --from=vendors /srv/umap/umap/static/umap/vendors /srv/umap/umap/static/umap/vendors
|
||||
|
||||
WORKDIR /srv/umap
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
uwsgi \
|
||||
libpq-dev \
|
||||
build-essential \
|
||||
binutils \
|
||||
gdal-bin \
|
||||
libproj-dev \
|
||||
curl \
|
||||
git \
|
||||
gettext \
|
||||
sqlite3 \
|
||||
libffi-dev \
|
||||
libtiff5-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
zlib1g-dev \
|
||||
libfreetype6-dev \
|
||||
liblcms2-dev \
|
||||
libwebp-dev \
|
||||
&& \
|
||||
pip install --no-cache -r requirements-docker.txt && pip install . && \
|
||||
apt-get remove -y \
|
||||
binutils \
|
||||
libproj-dev \
|
||||
libffi-dev \
|
||||
libtiff5-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
zlib1g-dev \
|
||||
libfreetype6-dev \
|
||||
liblcms2-dev \
|
||||
libwebp-dev \
|
||||
&& \
|
||||
apt-get autoremove -y && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Add Tini
|
||||
ENV TINI_VERSION v0.14.0
|
||||
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
|
||||
RUN chmod +x /tini
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
ENTRYPOINT ["/tini", "--", "/srv/umap/docker-entrypoint.sh"]
|
||||
|
||||
CMD ["/srv/umap/docker-entrypoint.sh"]
|
51
README.md
Normal file
51
README.md
Normal file
|
@ -0,0 +1,51 @@
|
|||
uMap
|
||||
===
|
||||
|
||||
### About
|
||||
|
||||
uMap lets you create maps with OpenStreetMap layers in a minute and embed them in your site.
|
||||
*Because we think that the more OSM will be used, the more OSM will be improved.*
|
||||
It uses [django-leaflet-storage](https://github.com/umap-project/django-leaflet-storage) and [Leaflet.Storage](https://github.com/umap-project/Leaflet.Storage), built on top of Django and Leaflet.
|
||||
|
||||
![Umap](scripts/umap.png)
|
||||
|
||||
docker support from https://github.com/Duvel/umap
|
||||
umap documentation at https://umap-project.readthedocs.io/en/latest/install/
|
||||
|
||||
|
||||
#### Install
|
||||
```
|
||||
cd /opt/
|
||||
git clone https://git.lattuga.net/blat/umap
|
||||
chmod -x ./scripts/install.sh
|
||||
./scripts/install.sh
|
||||
```
|
||||
##### Create admin
|
||||
```
|
||||
docker exec -ti umap_app_1 umap createsuperuser
|
||||
```
|
||||
|
||||
#### Backup
|
||||
There are two important places where your data are located, in your database and in your media folder.
|
||||
```
|
||||
chmod -x ./scripts/backup.sh
|
||||
./scripts/backup.sh
|
||||
```
|
||||
|
||||
read more about backups: https://github.com/umap-project/umap/blob/update-docs-backup-commands/docs/backup.md
|
||||
|
||||
#### Restore
|
||||
edit db_$(date +"%Y-%B-%d").zip with your backup date
|
||||
* require root privilegies to fix permission on db folder
|
||||
```
|
||||
chmod -x ./scripts/restore.sh
|
||||
./scripts/restore.sh
|
||||
```
|
||||
|
||||
#### Upgrade
|
||||
select a version and build a new image
|
||||
* require root privilegies to fix permission on db folder
|
||||
```
|
||||
chmod -x ./scripts/upgrade.sh
|
||||
./scripts/upgrade.sh
|
||||
```
|
29
docker-compose.yml
Normal file
29
docker-compose.yml
Normal file
|
@ -0,0 +1,29 @@
|
|||
version: '3'
|
||||
services:
|
||||
db:
|
||||
image: mdillon/postgis:9.6-alpine
|
||||
volumes:
|
||||
- ./db:/var/lib/postgresql/data
|
||||
|
||||
redis:
|
||||
image: redis:latest
|
||||
|
||||
app:
|
||||
image: umap:latest
|
||||
environment:
|
||||
- DATABASE_URL=postgis://postgres@db/postgres
|
||||
- REDIS_URL=redis://redis:6379/0
|
||||
- ADMIN_EMAIL=umap
|
||||
- ENABLE_ACCOUNT_LOGIN=True
|
||||
- SECRET_KEY=some-long-and-weirdly-unrandom-secret-key
|
||||
- ALLOWED_HOSTS=*
|
||||
- SITE_URL=http://localhost/
|
||||
- LEAFLET_STORAGE_ALLOW_ANONYMOUS=True
|
||||
volumes:
|
||||
- ./uploads:/srv/umap/uploads
|
||||
- ./static:/srv/umap/static
|
||||
ports:
|
||||
- 8000:8000
|
||||
depends_on:
|
||||
- db
|
||||
restart: always
|
31
docker-entrypoint.sh
Executable file
31
docker-entrypoint.sh
Executable file
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
|
||||
# default variables
|
||||
: "${SLEEP:=1}"
|
||||
: "${TRIES:=60}"
|
||||
|
||||
function wait_for_database {(
|
||||
echo "Waiting for database to respond..."
|
||||
tries=0
|
||||
while true; do
|
||||
[[ $tries -lt $TRIES ]] || return
|
||||
(echo "from django.db import connection; connection.connect()" | umap shell) >/dev/null 2>&1
|
||||
[[ $? -eq 0 ]] && return
|
||||
sleep $SLEEP
|
||||
tries=$((tries + 1))
|
||||
done
|
||||
)}
|
||||
|
||||
# first wait for the database
|
||||
wait_for_database
|
||||
# then migrate the database
|
||||
umap migrate
|
||||
# then collect static files
|
||||
umap collectstatic --noinput
|
||||
# create languagae files
|
||||
#umap storagei18n
|
||||
# compress static files
|
||||
umap compress
|
||||
# run uWSGI
|
||||
exec uwsgi --ini uwsgi.ini
|
4
requirements-docker.txt
Normal file
4
requirements-docker.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
-r requirements.txt
|
||||
django-environ==0.4.1
|
||||
django-redis==4.7.0
|
||||
uwsgi==2.0.14
|
20
scripts/auth-su.sh
Executable file
20
scripts/auth-su.sh
Executable file
|
@ -0,0 +1,20 @@
|
|||
#!/bin/su root
|
||||
ARG=$1
|
||||
|
||||
function auth_su {
|
||||
if [[ -z $ARG ]]; then
|
||||
# ok postgres
|
||||
chown -R 70:$USER db ; \
|
||||
chmod g=rwx,o-rwx -R db ;
|
||||
elif [[ $ARG == "user" ]]; then
|
||||
# ok build
|
||||
chown -R $USER:$USER db ; \
|
||||
chmod g=rwx,o-rwx -R db ;
|
||||
elif [[ $ARG == "delete" ]]; then
|
||||
# delete old volumes
|
||||
rm -rf db ; \
|
||||
rm -rf uploads ;
|
||||
fi
|
||||
}
|
||||
|
||||
auth_su $ARG
|
13
scripts/backup.sh
Executable file
13
scripts/backup.sh
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
|
||||
docker-compose down
|
||||
|
||||
[[ -f $HOME/backup ]] && mkdir $HOME/backup ; mkdir $HOME/backup/umap
|
||||
|
||||
# db
|
||||
zip -r $HOME/backup/umap/db_$(date +"%Y-%B-%d").zip db
|
||||
|
||||
# media and geojson
|
||||
zip -r $HOME/backup/umap/uploads_$(date +"%Y-%B-%d").zip uploads
|
||||
|
||||
docker-compose up -d
|
32
scripts/install.sh
Executable file
32
scripts/install.sh
Executable file
|
@ -0,0 +1,32 @@
|
|||
#!/bin/bash
|
||||
|
||||
# backup README
|
||||
cp README.md DOC.md
|
||||
|
||||
# delete this git repo and sync the offical one
|
||||
rm -rf .git
|
||||
git clone https://github.com/umap-project/umap.git tmp
|
||||
rsync -r -L tmp/ .
|
||||
rm -rf tmp/
|
||||
|
||||
# checkout to latest tag
|
||||
TAG=$(git tag -l | tail -1)
|
||||
git checkout $TAG
|
||||
|
||||
# create two default branch
|
||||
git switch -c current
|
||||
git switch -c upstream
|
||||
|
||||
# build docker image
|
||||
chmod +x docker-entrypoint.sh
|
||||
docker build --tag umap:$TAG .
|
||||
|
||||
# initialize directories and
|
||||
# fix db volume permission to enable backup without root needed
|
||||
mkdir static uploads db
|
||||
chown -R 70:$USER db
|
||||
chmod g=rwx,o-rwx -R db
|
||||
|
||||
# setup umap container tagname
|
||||
sed -i 's/umap:latest/umap:'${TAG}'/g' docker-compose.yml;
|
||||
docker-compose up -d;
|
16
scripts/restore.sh
Executable file
16
scripts/restore.sh
Executable file
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
|
||||
docker-compose down
|
||||
|
||||
# delete db and media volumes
|
||||
chmod +x ./scripts/auth-su.sh
|
||||
./scripts/auth-su.sh delete
|
||||
|
||||
# db
|
||||
unzip $HOME/backup/umap/db_$(date +"%Y-%B-%d").zip
|
||||
./scripts/auth-su.sh
|
||||
|
||||
# media and geojson
|
||||
unzip $HOME/backup/umap/uploads_$(date +"%Y-%B-%d").zip
|
||||
|
||||
docker-compose up -d
|
BIN
scripts/umap.png
Normal file
BIN
scripts/umap.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 606 KiB |
46
scripts/upgrade.sh
Executable file
46
scripts/upgrade.sh
Executable file
|
@ -0,0 +1,46 @@
|
|||
#!/bin/bash
|
||||
|
||||
docker-compose down
|
||||
|
||||
git checkout current
|
||||
TAG=$(git describe --tags)
|
||||
git fetch --tags
|
||||
|
||||
# select from last 5 tags
|
||||
if [ latestTag="" ] ; then
|
||||
PS3="Enter number of version: "
|
||||
select version in $(git tag -l | tail -5)
|
||||
do
|
||||
latestTag=$version;
|
||||
echo "Upgrading to $version ..."
|
||||
break;
|
||||
done
|
||||
fi
|
||||
|
||||
# or use latest
|
||||
# latestTag=$(git tag -l | tail -1`)
|
||||
|
||||
# update upstream
|
||||
git branch -D upstream
|
||||
git pull
|
||||
git checkout $latestTag
|
||||
git switch -c upstream
|
||||
|
||||
# fix permission and rebuild
|
||||
chmod +x docker-entrypoint.sh
|
||||
chmod +x ./scripts/auth-su.sh
|
||||
./scripts/auth-su.sh user
|
||||
|
||||
docker build --tag umap:$latestTag .
|
||||
|
||||
# fix permission
|
||||
chmod +x ./scripts/auth-su.sh
|
||||
./scripts/auth-su.sh
|
||||
|
||||
# restart
|
||||
sed -i 's/umap:'${TAG}'/umap:'${latestTag}'/g' docker-compose.yml;
|
||||
docker-compose up -d;
|
||||
|
||||
# resync current
|
||||
git branch -D current
|
||||
git branch current
|
154
umap/settings/docker.py
Normal file
154
umap/settings/docker.py
Normal file
|
@ -0,0 +1,154 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Settings for Docker development
|
||||
Use this file as a base for your local development settings and copy
|
||||
it to umap/settings/local.py. It should not be checked into
|
||||
your code repository.
|
||||
"""
|
||||
import environ
|
||||
from umap.settings.base import * # pylint: disable=W0614,W0401
|
||||
|
||||
env = environ.Env()
|
||||
|
||||
SECRET_KEY = env('SECRET_KEY')
|
||||
INTERNAL_IPS = env.list('INTERNAL_IPS', default='127.0.0.1')
|
||||
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default='*')
|
||||
|
||||
DEBUG = env.bool('DEBUG', default=False)
|
||||
|
||||
ADMIN_EMAILS = env.list('ADMIN_EMAIL', default='')
|
||||
ADMINS = [(email, email) for email in ADMIN_EMAILS]
|
||||
MANAGERS = ADMINS
|
||||
|
||||
DATABASES = {
|
||||
'default': env.db(default='postgis://localhost:5432/umap')
|
||||
}
|
||||
|
||||
COMPRESS_ENABLED = True
|
||||
COMPRESS_OFFLINE = True
|
||||
|
||||
LANGUAGE_CODE = 'en'
|
||||
|
||||
# Set to False if login into django account should not be possible. You can
|
||||
# administer accounts in the admin interface.
|
||||
ENABLE_ACCOUNT_LOGIN = env.bool('ENABLE_ACCOUNT_LOGIN', default=True)
|
||||
|
||||
AUTHENTICATION_BACKENDS = ()
|
||||
|
||||
# We need email to associate with other Oauth providers
|
||||
SOCIAL_AUTH_GITHUB_SCOPE = ['user:email']
|
||||
SOCIAL_AUTH_GITHUB_KEY = env('GITHUB_KEY', default='')
|
||||
SOCIAL_AUTH_GITHUB_SECRET = env('GITHUB_SECRET', default='')
|
||||
if SOCIAL_AUTH_GITHUB_KEY and SOCIAL_AUTH_GITHUB_SECRET:
|
||||
AUTHENTICATION_BACKENDS += (
|
||||
'social_core.backends.github.GithubOAuth2',
|
||||
)
|
||||
SOCIAL_AUTH_BITBUCKET_KEY = env('BITBUCKET_KEY', default='')
|
||||
SOCIAL_AUTH_BITBUCKET_SECRET = env('BITBUCKET_SECRET', default='')
|
||||
if SOCIAL_AUTH_BITBUCKET_KEY and SOCIAL_AUTH_BITBUCKET_SECRET:
|
||||
AUTHENTICATION_BACKENDS += (
|
||||
'social_core.backends.bitbucket.BitbucketOAuth',
|
||||
)
|
||||
|
||||
SOCIAL_AUTH_TWITTER_KEY = env('TWITTER_KEY', default='')
|
||||
SOCIAL_AUTH_TWITTER_SECRET = env('TWITTER_SECRET', default='')
|
||||
if SOCIAL_AUTH_TWITTER_KEY and SOCIAL_AUTH_TWITTER_SECRET:
|
||||
AUTHENTICATION_BACKENDS += (
|
||||
'social_core.backends.twitter.TwitterOAuth',
|
||||
)
|
||||
SOCIAL_AUTH_OPENSTREETMAP_KEY = env('OPENSTREETMAP_KEY', default='')
|
||||
SOCIAL_AUTH_OPENSTREETMAP_SECRET = env('OPENSTREETMAP_SECRET', default='')
|
||||
if SOCIAL_AUTH_OPENSTREETMAP_KEY and SOCIAL_AUTH_OPENSTREETMAP_SECRET:
|
||||
AUTHENTICATION_BACKENDS += (
|
||||
'social_core.backends.openstreetmap.OpenStreetMapOAuth',
|
||||
)
|
||||
|
||||
AUTHENTICATION_BACKENDS += (
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
)
|
||||
|
||||
# MIDDLEWARE_CLASSES += (
|
||||
# 'social_django.middleware.SocialAuthExceptionMiddleware',
|
||||
# )
|
||||
|
||||
SOCIAL_AUTH_RAISE_EXCEPTIONS = False
|
||||
SOCIAL_AUTH_BACKEND_ERROR_URL = "/"
|
||||
|
||||
# If you want to add a playgroud map, add its primary key
|
||||
# UMAP_DEMO_PK = 204
|
||||
# If you want to add a showcase map on the home page, add its primary key
|
||||
# UMAP_SHOWCASE_PK = 1156
|
||||
# Add a baner to warn people this instance is not production ready.
|
||||
UMAP_DEMO_SITE = False
|
||||
|
||||
# Whether to allow non authenticated people to create maps.
|
||||
LEAFLET_STORAGE_ALLOW_ANONYMOUS = env.bool(
|
||||
'LEAFLET_STORAGE_ALLOW_ANONYMOUS',
|
||||
default=False,
|
||||
)
|
||||
|
||||
# This setting will exclude empty maps (in fact, it will exclude all maps where
|
||||
# the default center has not been updated)
|
||||
UMAP_EXCLUDE_DEFAULT_MAPS = False
|
||||
|
||||
# How many maps should be showcased on the main page resp. on the user page
|
||||
UMAP_MAPS_PER_PAGE = 0
|
||||
# How many maps should be showcased on the user page, if owner
|
||||
UMAP_MAPS_PER_PAGE_OWNER = 10
|
||||
|
||||
SITE_URL = env('SITE_URL')
|
||||
SHORT_SITE_URL = env('SHORT_SITE_URL', default=None)
|
||||
|
||||
CACHES = {'default': env.cache('REDIS_URL', default='locmem://')}
|
||||
|
||||
# POSTGIS_VERSION = (2, 1, 0)
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||
|
||||
# You need to unable accent extension before using UMAP_USE_UNACCENT
|
||||
# python manage.py dbshell
|
||||
# CREATE EXTENSION unaccent;
|
||||
UMAP_USE_UNACCENT = False
|
||||
|
||||
# For static deployment
|
||||
STATIC_ROOT = '/srv/umap/static'
|
||||
|
||||
# For users' statics (geojson mainly)
|
||||
MEDIA_ROOT = '/srv/umap/uploads'
|
||||
|
||||
# Default map location for new maps
|
||||
LEAFLET_LONGITUDE = env.int('LEAFLET_LONGITUDE', default=2)
|
||||
LEAFLET_LATITUDE = env.int('LEAFLET_LATITUDE', default=51)
|
||||
LEAFLET_ZOOM = env.int('LEAFLET_ZOOM', default=6)
|
||||
|
||||
# Number of old version to keep per datalayer.
|
||||
LEAFLET_STORAGE_KEEP_VERSIONS = env.int(
|
||||
'LEAFLET_STORAGE_KEEP_VERSIONS',
|
||||
default=10,
|
||||
)
|
||||
|
||||
import sys
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'formatters': {
|
||||
'verbose': {
|
||||
'format': '[django] %(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
|
||||
}
|
||||
},
|
||||
'handlers': {
|
||||
'console': {
|
||||
'level': 'DEBUG',
|
||||
'class': 'logging.StreamHandler',
|
||||
'stream': sys.stdout,
|
||||
'formatter': 'verbose'
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'django': {
|
||||
'handlers': ['console'],
|
||||
'level': 'DEBUG',
|
||||
'propagate': True,
|
||||
},
|
||||
},
|
||||
}
|
10
uwsgi.ini
Normal file
10
uwsgi.ini
Normal file
|
@ -0,0 +1,10 @@
|
|||
[uwsgi]
|
||||
http = :$(PORT)
|
||||
module = umap.wsgi:application
|
||||
master = True
|
||||
vacuum = True
|
||||
max-requests = 5000
|
||||
processes = 4
|
||||
enable-threads = true
|
||||
static-map = /static=/srv/umap/static
|
||||
static-map = /uploads=/srv/umap/uploads
|
Loading…
Reference in a new issue