Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docker support [WIP] #32

Open
wants to merge 54 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
f3f4c52
Start Docker support [WIP]
stefankoegl Nov 19, 2014
f180435
Merge branch 'master' into docker
stefankoegl Jul 2, 2017
3a719f0
Move dependency installation from Dockerfile to makefile
stefankoegl Jul 2, 2017
9ce0fa2
Simplify settings
stefankoegl Jul 2, 2017
c3268bc
Merge branch 'master' into docker
stefankoegl Jul 23, 2017
247b23e
Start Docker support [WIP]
stefankoegl Nov 19, 2014
89d689f
Docker-compose setup
JeanFred Aug 9, 2016
cdcb34f
Serve static assets using Whitenoise
JeanFred Jul 1, 2017
44e40e4
Avoid crash during initial migration
JeanFred Jul 1, 2017
6f74bbd
Update Dockerfile, makefile to fix build
stefankoegl Jul 23, 2017
d3580b3
Comment out django-nose from INSTALLED_APPS
JeanFred Jul 23, 2017
20ff6fa
Import django-nose only when it is available
stefankoegl Jul 24, 2017
b7aadf5
Run collectstatic, compilemessages in Docker build
stefankoegl Jul 24, 2017
2c03404
Merge branch 'master' into docker
stefankoegl Jul 24, 2017
ba29198
Merge branch 'docker' of https://github.com/JeanFred/mygpo into docker
stefankoegl Jul 24, 2017
95bf714
Revert some changes from 89d689ff35e4160821021ac3f
stefankoegl Jul 25, 2017
ea99b1f
Add container for Celery worker
stefankoegl Jul 25, 2017
558179b
Add dependencies between containers
stefankoegl Jul 25, 2017
bcf227e
Run gunicorn webserver
stefankoegl Jul 25, 2017
91f3312
Merge branch 'master' into docker
stefankoegl Aug 6, 2017
b4cd336
Merge branch 'master' into docker
stefankoegl Aug 6, 2017
1ea4a8a
Merge branch 'master' into docker
stefankoegl Aug 22, 2017
f316715
Merge branch 'master' into docker
stefankoegl Sep 9, 2017
0aed0da
Merge branch 'master' into docker
stefankoegl Sep 25, 2017
1491582
Add missing setting SEARCH_CUTOFF
stefankoegl Sep 25, 2017
a5f9fa1
Merge branch 'master' into docker
stefankoegl Oct 26, 2017
0763228
Remove references to (unused) Elasticsearch
stefankoegl Oct 28, 2017
a6c9430
Update PostgreSQL container to version 10
stefankoegl Oct 28, 2017
e0558bc
Merge branch 'master' into docker
stefankoegl Dec 2, 2017
193d19c
Merge branch 'master' into docker
stefankoegl Jan 16, 2018
7a46e2d
Update commands in celery containers
stefankoegl Jan 16, 2018
57a4d07
wait-for-postgres.sh wrapper
elelay Jan 14, 2018
aef345a
docker-compose: wait for postgres + init; don't run base
elelay Jan 26, 2018
4cc2ee0
Merge branch 'master' into docker
stefankoegl Jan 30, 2018
437eb37
Merge branch 'master' into docker
stefankoegl Feb 1, 2018
2ecfc89
Merge branch 'master' into docker
stefankoegl Feb 18, 2018
e40bf7d
Merge pull request #84 from elelay/docker-wait-for-postgres
stefankoegl Mar 24, 2018
f305196
Merge branch 'master' into docker
stefankoegl May 6, 2018
86836ed
Merge branch 'master' into docker
stefankoegl Jun 28, 2018
7611dbc
Specify Python 3.6 in Dockerfile
stefankoegl Aug 15, 2018
85343ec
Merge branch 'master' into docker
stefankoegl Aug 15, 2018
2567edc
Merge branch 'master' into docker
stefankoegl Sep 2, 2018
15c1204
Merge branch 'master' into docker
stefankoegl Oct 15, 2019
a15262e
Fix code formatting
stefankoegl Oct 18, 2019
44b0499
Merge branch 'master' into docker
stefankoegl Oct 22, 2019
560f3eb
Merge branch 'master' into docker
SiqingYu Feb 24, 2020
31365aa
Fix makefile tab indentation.
SiqingYu Feb 24, 2020
406f1d5
Upgrade whitenoise to fix django.utils.six ModuleNotFoundError
SiqingYu Feb 24, 2020
8484c3e
Allow to run Makefile command without sudo
JeanFred Apr 14, 2020
4efb585
Set POSTGRES_HOST_AUTH_METHOD in Postgres Docker
JeanFred Apr 14, 2020
93131ae
Add gettext to makefile dependencies
JeanFred Apr 14, 2020
9f4ac38
Fix variable in French locale
JeanFred Apr 14, 2020
a7045b9
Set STATIC_ROOT for serving static assets using Whitenoise
JeanFred Apr 14, 2020
06a1b80
Merge pull request #397 from JeanFred/docker
Sep 24, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.git
htdocs/media/logo
mygpo/settings_prod.py
doc/
res/
tools/
locale/
venv*
*.pyc
*/*.pyc
*/*/*.pyc
*/*/*/*.pyc
39 changes: 39 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
FROM python:3.6
MAINTAINER Stefan Kögl <stefan@skoegl.net>

RUN apt-get update && apt-get install -y git make

# copy source
WORKDIR /srv/mygpo

COPY makefile .

# install all packaged runtime dependencies
RUN yes | make install-deps APT=apt-get

# create log directories
RUN mkdir -p /var/log/gunicorn

COPY requirements.txt .
COPY requirements-setup.txt .

# install all runtime dependencies
RUN pip install \
-r requirements.txt \
-r requirements-setup.txt

# copy source
COPY . .

# Post-deployment actions
ENV SECRET_KEY temp
RUN python manage.py collectstatic --no-input
RUN python manage.py compilemessages

# set up missing environment variables
ENTRYPOINT ["/srv/mygpo/bin/docker-env.sh"]

# default launch command
CMD ["/srv/mygpo/contrib/wait-for-postgres.py", "gunicorn", "mygpo.wsgi:application", "--access-logfile", "-", "--bind=0.0.0.0:8000"]

EXPOSE 8000
18 changes: 18 additions & 0 deletions bin/docker-env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

# Docker doesn't have a great way to set environment variables at startup.
# This scripts will set up some defaults.

# if a DATABSE_URL is provided from outside, use it
if [[ -z "$DATABASE_URL" ]]; then
# otherwise construct one using a linked "db" container
export DATABASE_URL="postgres://mygpo:mygpo@${DB_PORT_5432_TCP_ADDR}:5432/mygpo"
fi

# if not SECRET_KEY is provided from outside, create a random one
if [[ -z "$SECRET_KEY" ]]; then
export SECRET_KEY=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
fi

# Execute the commands passed to this script
exec "$@"
3 changes: 3 additions & 0 deletions contrib/Dockerfile.postgres
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM postgres:10

COPY init-db.sql /docker-entrypoint-initdb.d/
2 changes: 2 additions & 0 deletions contrib/docker.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BROKER_URL=redis://root@redis:6379/0
DATABASE_URL=postgresql://mygpo:mygpo@postgres:5432/mygpo
9 changes: 9 additions & 0 deletions contrib/init-db.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CREATE USER mygpo WITH PASSWORD 'mygpo';
ALTER USER mygpo CREATEDB; -- required for creating test database
CREATE DATABASE mygpo;
CREATE DATABASE test_mygpo;
GRANT ALL PRIVILEGES ON DATABASE mygpo to mygpo;
GRANT ALL PRIVILEGES ON DATABASE test_mygpo to mygpo;
ALTER DATABASE mygpo OWNER TO mygpo;
ALTER DATABASE test_mygpo OWNER TO mygpo;
ALTER ROLE mygpo SET statement_timeout = 5000;
51 changes: 51 additions & 0 deletions contrib/wait-for-postgres.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env python
import os
import sys
import time

import psycopg2cffi as psycopg2


if __name__ == "__main__":
dburl = os.environ["DATABASE_URL"]
print("Trying to connect to {}".format(dburl))
conn = None
while not conn:
try:
conn = psycopg2.connect(dburl)
except:
print("Postgres is unavailable - sleeping")
time.sleep(1)

cur = conn.cursor()
cur.execute("""SELECT EXISTS (
SELECT 1
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name = 'votes_vote'
)""")
has_table = cur.fetchone()[0]
cur.close()
conn.close()

if 'migrate' in sys.argv:
if has_table:
print("Database already initialized, exiting")
sys.exit(0)
else:
print("Postgres is available => will initialize")
else:
if not has_table:
print("ERROR: Postgres is available but not initialized.\n"
"Please run:\n"
"\tdocker-compose run web /srv/mygpo/contrib/wait-for-postgres.py python manage.py migrate\n"
"and restart.")
sys.exit(-1)

if sys.argv[1]:
cmd = sys.argv[1:]
print("Postgres is up - executing command {}".format(" ".join(cmd)))
sys.stdout.flush()
os.execvp(cmd[0], cmd)
else:
print("Postgres is up - no command given, exiting")
14 changes: 3 additions & 11 deletions doc/dev/postgres-setup.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,6 @@ PostgreSQL Setup

Use the following to set up a local PostgreSQL.

.. code-block:: sql

CREATE USER mygpo WITH PASSWORD 'mygpo';
ALTER USER mygpo CREATEDB; -- required for creating test database
CREATE DATABASE mygpo;
CREATE DATABASE test_mygpo;
GRANT ALL PRIVILEGES ON DATABASE mygpo to mygpo;
GRANT ALL PRIVILEGES ON DATABASE test_mygpo to mygpo;
ALTER DATABASE mygpo OWNER TO mygpo;
ALTER DATABASE test_mygpo OWNER TO mygpo;
ALTER ROLE mygpo SET statement_timeout = 5000;
.. literalinclude:: ../../contrib/init-db.sql
:language: sql
:linenos:
1 change: 1 addition & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Contents
publisher/index
api/index
dev/index
ops/index
Translator Documentation <http://wiki.gpodder.org/wiki/Translations>


Expand Down
106 changes: 106 additions & 0 deletions doc/ops/configuration.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
Configuration
=============

Configuration can be done through the following environment variables.

``DEBUG``
---------
Debug mode shows error pages, enables debug output, etc.


``DATABASE_URL``
----------------
DB connection string in the form of ``postgres://USER:PASSWORD@HOST:PORT/NAME``


``ACCOUNT_ACTIVATION_DAYS``
---------------------------
Number of days that newly registered users have time to activate their account.


``DEFAULT_FROM_EMAIL``
----------------------
Default sender address for outgoing emails. See `Django documentation
<https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-DEFAULT_FROM_EMAIL>`__.


``SECRET_KEY``
--------------
See `Django documentation
<https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SECRET_KEY>`__.


``GOOGLE_ANALYTICS_PROPERTY_ID``
--------------------------------
Setting a Google Analytics Property ID activates GA integration.


``DIRECTORY_EXCLUDED_TAGS``
---------------------------
A comma-separated list of tags that are excluded from the directory.


``FLICKR_API_KEY``
------------------
Setting a Flickr API key activates Flickr integration.


``MAINTENANCE``
---------------
Switches the site into a maintenance mode.


* ``PODCAST_SLUG_SUBSCRIBER_LIMIT``

* ``MIN_SUBSCRIBERS_CATEGORY``: minimum number of subscribers that a podcast
needs to "push" one of its categories to the top

* ``API_ACTIONS_MAX_NONBG``: maximum number of episode actions that the API
processes immediatelly before returning the response. Larger requests will
be handled in background.

* ``ADSENSE_CLIENT``

* ``ADSENSE_SLOT_BOTTOM``

* ``STAFF_TOKEN``: enabled access to staff-only areas with ?staff=<STAFF_TOKEN>

* ``FLATTR_KEY``

* ``FLATTR_SECRET``

* ``FLATTR_MYGPO_THING``: Flattr thing of the webservice. Will be flattr'd
when a user sets the "Auto-Flattr gpodder.net" option

* ``USER_AGENT``: The User-Agent string used for outgoing HTTP requests

* ``DEFAULT_BASE_URL``: Base URL of the website that is used if the actually
used parameters is not available. Request handlers, for example, can access
the requested domain. Code that runs in background can not do this, and
therefore requires a default value. This should be set to something like
``http://example.com``

* ``BROKER_URL`` Celery Broker URL

* ``CELERY_RESULT_BACKEND``

* ``CELERY_SEND_TASK_ERROR_EMAILS``

* ``SERVER_EMAIL``

* ``GOOGLE_CLIENT_ID``

* ``GOOGLE_CLIENT_SECRET``

* ``SUPPORT_URL``: URL where users of the site can get support

* ``ELASTICSEARCH_SERVER``

* ``ELASTICSEARCH_INDEX``

* ``ELASTICSEARCH_TIMEOUT``

* ``ACTIVATION_VALID_DAYS`` time for how long an activation is valid; after
that, an unactivated user will be deleted

* ``INTERNAL_IPS``
57 changes: 57 additions & 0 deletions doc/ops/docker.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
Using Docker
============

mygpo can be run using `Docker <https://docker.com/>`_.


Database
--------

The image requires a PostgreSQL server, specified either via

* a `linked container <https://docs.docker.com/userguide/dockerlinks/>`_
called ``db`` containing a server with a database called ``mygpo``, a user
called ``mygpo`` with a password ``mygpo``.
* A ``DATABASE_URL`` environment variable (eg
``postgres://USER:PASSWORD@HOST:PORT/NAME``)

Using a PostgreSQL Docker container
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Start a container using the `official PostgreSQL image <https://registry.hub.docker.com/_/postgres/>`_. ::

docker run --name db -d postgres

Create the schema and a corresponding user ::

docker exec -it db psql -U postgres

And enter the following commands (change passwords as required)

.. literalinclude:: ../../contrib/init-db.sql
:language: sql
:linenos:

Initialize the tables. This needs needs to be run for every update. ::

sudo docker run --rm --link db:db -e SECRET_KEY=asdf mygpo/web python manage.py migrate


Redis
-----


Web Frontend
------------

The image exposes the web interface on port 8000.


Celery Worker
-------------


Celery Heartbeat
----------------


9 changes: 9 additions & 0 deletions doc/ops/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Operation Documentation
=======================


.. toctree::
:maxdepth: 1

configuration
docker
14 changes: 14 additions & 0 deletions docker-compose-common.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

version: '2'

services:

base:
build:
context: .
dockerfile: Dockerfile
env_file: contrib/docker.env
volumes:
- .:/srv/mygpo
- ./contrib/docker.env:/docker.env

Loading