diff --git a/README.md b/README.md index 524d007..db22f01 100644 --- a/README.md +++ b/README.md @@ -18,14 +18,14 @@ To test the build locally on your laptop: `docker run -it --name datasketch_cms -e DB_HOST="host.docker.internal" -p 8888:8000 androiddrew/datasketch:latest` -If using the postgres.app on Mac OS you will need to update both the postgresql.conf and pg_hba.conf files +If using the postgres.app on Mac OS you will need to update both the `postgresql.conf` and `pg_hba.conf` files -/Users//Library/Application Support/Postgres/var-10/postgresql.conf +/Users/user_name/Library/Application Support/Postgres/var-10/postgresql.conf ``` listen_addresses = '*' ``` -/Users//Library/Application Support/Postgres/var-10/pg_hba.conf +/Users/user_name/Library/Application Support/Postgres/var-10/pg_hba.conf ``` # TYPE DATABASE USER ADDRESS METHOD @@ -46,8 +46,14 @@ host datasketch datasketch host.docker.internal trust ## Trouble shooting -You can run the following command to get the logs for a task, running or not. +You can run the following commands to get the logs for a task, running or not. ``` -docker logs $(docker inspect --format "{{.Status.ContainerStatus.ContainerID}}" ) +docker logs -f $(docker inspect --format "{{.Status.ContainerStatus.ContainerID}}" ) +``` + +or + +``` +docker service logs -f ``` \ No newline at end of file diff --git a/docker-compose-swarm.yml b/docker-compose-swarm.yml index 03da986..0bd5bb6 100644 --- a/docker-compose-swarm.yml +++ b/docker-compose-swarm.yml @@ -3,27 +3,45 @@ version: '3.6' services: cms: - image: androiddrew/datasketch:latest + image: androiddrew/datasketch:0.1.3 + command: gunicorn cms.wsgi:application --bind 0.0.0.0:5000 --workers 3 deploy: replicas: 1 restart_policy: condition: on-failure - ports: - - 8000:8000 secrets: - datasketch_key - pg_passwd_datasketch environment: - DJANGO_SETTINGS_MODULE=cms.settings.production - DB_HOST=db + - DB_PORT=5432 - DB_USER=datasketch volumes: - datasketch-media-vol:/code/media + - datasketch-static-vol:/code/staticout depends_on: - db networks: - datasketch_net + nginx: + image: androiddrew/datasketch_nginx:0.1.0 + deploy: + replicas: 1 + restart_policy: + condition: on-failure + ports: + - 8000:80 + depends_on: + - cms + networks: + - datasketch_net + volumes: + - datasketch-media-vol:/var/www/datasketch/media + - datasketch-static-vol:/var/www/datasketch/static + + db: image: postgres:10.5-alpine deploy: @@ -62,6 +80,13 @@ volumes: type: nfs o: addr=nas1.androiddrew.com,rw device: ":/volume1/expanse/datasketch_media" + datasketch-static-vol: + driver: local + driver_opts: + type: nfs + o: addr=nas1.androiddrew.com,rw + device: ":/volume1/expanse/datasketch_static" + secrets: pg_passwd_datasketch: diff --git a/services/cms/Dockerfile b/services/cms/Dockerfile index 79d9701..6c3c55c 100644 --- a/services/cms/Dockerfile +++ b/services/cms/Dockerfile @@ -1,21 +1,38 @@ +#FROM python:3.7-alpine FROM python:3.7 LABEL maintainer="drew@androiddrew.comw" +# Set environmental variables ENV PYTHONUNBUFFERED 1 -ENV DJANGO_ENV production +ENV PYTHONDONTWRITEBYTECODE 1 +# Set Working Directory +WORKDIR /code + +# install psycopg2 +#RUN apk update \ +# && apk add --virtual build-deps gcc python3-dev musl-dev \ +# && apk add postgresql-dev \ +# && pip install psycopg2 \ +# && apk del build-deps + +# Install dependencies +RUN pip install --upgrade pip COPY ./requirements.txt /code/requirements.txt RUN pip install -r /code/requirements.txt -RUN pip install gunicorn +# Copy entrypoint.sh +COPY ./entrypoint.sh /code/entrypoint.sh + +# Copy code to image COPY . /code/ -WORKDIR /code/ -RUN python manage.py collectstatic +RUN useradd wagtail && chown -R wagtail /code + +RUN apt update && apt -y install netcat -RUN useradd wagtail -RUN chown -R wagtail /code USER wagtail -EXPOSE 8000 -CMD exec gunicorn cms.wsgi:application --bind 0.0.0.0:8000 --workers 3 +# run entrypoint.sh +ENTRYPOINT ["/code/entrypoint.sh"] + diff --git a/services/cms/README.md b/services/cms/README.md index 11ca287..e4eda9d 100644 --- a/services/cms/README.md +++ b/services/cms/README.md @@ -2,17 +2,13 @@ This service is built using the [Wagtail](http://docs.wagtail.io/en/v2.3/) framework. -## Middleware - -Since this application is being deployed to a Docker swarm it utilizes [Whitenoise](http://whitenoise.evans.io/en/stable/) and the Django specific whitenoise middleware to deliver static content. This solution is suitable for serving low traffic static content. To improve performance an Nginx reverse proxy could leverage HTTP caching or could be configured to serve all static content directly. - ## Environmental Variables The follow environment variables must be set for development. Note that the DB_PASSWD for production must be a docker secret. ``` DB_HOST= -DB_PASSWD=ec +DB_PASSWD= ``` In production you must set the `DJANGO_SETTINGS_MODULE` to the appropriate module: @@ -21,6 +17,5 @@ In production you must set the `DJANGO_SETTINGS_MODULE` to the appropriate modul DJANGO_SETTINGS_MODULE=cms.settings.production ``` -## Migrations - -The `manage.py` file is used to upgrade the backend database. You will need to log into the container on the appropriate host and execute the command `python manage.py migrate` manually. +## Migrations and collectstatic +Migrations and the collection of static content is managed through the `entrypoint.sh` script. On start up the cms container will check for the availability of the Postgres server, then run the migration and static file collection processes. The static files in production will be written to a persistent location on a NAS device. An Nginx service will mount that same static location and serve content. diff --git a/services/cms/cms/settings/base.py b/services/cms/cms/settings/base.py index a5d3f98..07a787f 100644 --- a/services/cms/cms/settings/base.py +++ b/services/cms/cms/settings/base.py @@ -48,7 +48,6 @@ INSTALLED_APPS = [ ] MIDDLEWARE = [ - "whitenoise.middleware.WhiteNoiseMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", @@ -134,7 +133,7 @@ STATICFILES_DIRS = [os.path.join(PROJECT_DIR, "static")] # See https://docs.djangoproject.com/en/2.1/ref/contrib/staticfiles/#manifeststaticfilesstorage STATICFILES_STORAGE = "django.contrib.staticfiles.storage.ManifestStaticFilesStorage" -STATIC_ROOT = os.path.join(BASE_DIR, "static") +STATIC_ROOT = os.path.join(BASE_DIR, "staticout") STATIC_URL = "/static/" MEDIA_ROOT = os.path.join(BASE_DIR, "media") diff --git a/services/cms/cms/settings/production.py b/services/cms/cms/settings/production.py index e1e9797..3436e0d 100644 --- a/services/cms/cms/settings/production.py +++ b/services/cms/cms/settings/production.py @@ -18,12 +18,15 @@ DATABASES = { "USER": "datasketch", "PASSWORD": PG_PASSWD, "HOST": os.environ.get("DB_HOST") if os.environ.get("DB_HOST") else "127.0.0.1", - "PORT": "5432", + "PORT": os.environ.get("DB_PORT") if os.environ.get("DB_PORT") else "5432", } } -# Set as the volume map for media on the nas -MEDIA_URL = "/code/media/" +STATIC_ROOT = os.path.join(BASE_DIR, "staticout") +STATIC_URL = "/static/" + +MEDIA_ROOT = os.path.join(BASE_DIR, "media") +MEDIA_URL = "/media/" LOGGING = { "version": 1, diff --git a/services/cms/entrypoint.sh b/services/cms/entrypoint.sh new file mode 100755 index 0000000..c07dd82 --- /dev/null +++ b/services/cms/entrypoint.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +echo "Waiting for PostgreSQL" + +while ! nc -z $DB_HOST $DB_PORT; do + sleep 0.1 +done + +echo "PostgreSQL started" + +python manage.py flush --no-input +python manage.py migrate +python manage.py collectstatic --no-input + +echo "Migratation and static file collection Successful" + +exec "$@" \ No newline at end of file diff --git a/services/cms/requirements.txt b/services/cms/requirements.txt index 80fe774..2c6ae09 100644 --- a/services/cms/requirements.txt +++ b/services/cms/requirements.txt @@ -1,4 +1,4 @@ Django>=2.1,<2.2 wagtail>=2.3,<2.4 -psycopg2>=2.7.5 -whitenoise>=4.1 \ No newline at end of file +psycopg2==2.7.5 +gunicorn==19.9.0 \ No newline at end of file diff --git a/services/nginx/Dockerfile b/services/nginx/Dockerfile new file mode 100644 index 0000000..365335a --- /dev/null +++ b/services/nginx/Dockerfile @@ -0,0 +1,4 @@ +FROM nginx:1.15.0-alpine + +RUN rm /etc/nginx/conf.d/default.conf +COPY prod.conf /etc/nginx/conf.d \ No newline at end of file diff --git a/services/nginx/prod.conf b/services/nginx/prod.conf new file mode 100644 index 0000000..55b30d5 --- /dev/null +++ b/services/nginx/prod.conf @@ -0,0 +1,26 @@ +upstream wagtail_app { + server cms:5000; +} + +server { + + listen 80; + + location / { + proxy_pass http://wagtail_app; + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host $server_name; + } + + location /media/ { + alias /var/www/datasketch/media/; + } + + location /static/ { + alias /var/www/datasketch/static/; + } + +} \ No newline at end of file