pretix / pretix-docker-compose

Docker Compose setup for pretix. Not officially maintained!
3 stars 4 forks source link

docker-compose #1

Open Speedy1991 opened 7 years ago

Speedy1991 commented 7 years ago

Hi! I try to run Pretix via docker-compose and if i get it running i will open a PR if you are interested. The current state is:

I hope you can help me figure out the problems. The isn't any error to see except pretix_1 | 2017-09-13 19:14:04,988 INFO exited: pretixtask (exit status 1; not expected)

Here are my files + config + docker output

docker-compose.yml:

version: '2'
services:
  db:
    image: mariadb:latest
    environment:
      - MYSQL_DATABASE=pretix
      - MYSQL_USER=pretix
      - MYSQL_PASSWORD=pretix
      - MYSQL_RANDOM_ROOT_PASSWORD=1

  redis:
    image: redis:latest

  pretix:
    image: pretix/standalone
    volumes:
      - pretix-data:/data
      - ./etc:/etc/pretix/
    ports:
      - "0.0.0.0:8345:8345"
    depends_on:
      - db
      - redis

volumes:
  pretix-data:

pretix.cfg:


[pretix]
instance_name=My pretix installation
url=localhost
currency=EUR
; DO NOT change the following value, it has to be set to the location of the
; directory *inside* the docker container
datadir=/data

[database]
; Replace mysql with postgresql_psycopg2 for PostgreSQL
backend=mysql
name=pretix
user=pretix
password=pretix
; Replace with host IP address for PostgreSQL
host=db

[mail]
; See config file documentation for more options
from=tickets@yourdomain.com
; This is the default IP address of your docker host in docker's virtual
; network. Make sure postfix listens on this address.
host=172.17.0.1

[redis]
location=redis?db=0
; Remove the following line if you are unsure about your redis' security
; to reduce impact if redis gets compromised.
sessions=true

[celery]
backend=redis+socket://redis?virtual_host=1
broker=redis+socket://redis?virtual_host=2

Full output of docker:

$ docker-compose up  --force-recreate --build
Recreating pretix_db_1 ...
Recreating pretix_db_1
Recreating pretix_redis_1 ...
Recreating pretix_redis_1 ... done
Recreating pretix_pretix_1 ...
Recreating pretix_pretix_1 ... done
Attaching to pretix_db_1, pretix_redis_1, pretix_pretix_1
redis_1   | 1:C 13 Sep 19:13:48.931 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1   | 1:C 13 Sep 19:13:48.931 # Redis version=4.0.1, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1   | 1:C 13 Sep 19:13:48.931 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] mysqld (mysqld 10.2.7-MariaDB-10.2.7+maria~jessie) starting as process 1 ...
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] InnoDB: Uses event mutexes
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] InnoDB: Compressed tables use zlib 1.2.8
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] InnoDB: Using Linux native AIO
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] InnoDB: Number of pools: 1
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] InnoDB: Using SSE2 crc32 instructions
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] InnoDB: Initializing buffer pool, total size = 256M, instances = 1, chunk size = 128M
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] InnoDB: Completed initialization of buffer pool
db_1      | 2017-09-13 19:13:49 139725240645376 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] InnoDB: Highest supported file format is Barracuda.
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] InnoDB: 128 out of 128 rollback segments are active.
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] InnoDB: Creating shared tablespace for temporary tables
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] InnoDB: Waiting for purge to start
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] InnoDB: 5.7.18 started; log sequence number 10897290
db_1      | 2017-09-13 19:13:49 139725000136448 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] Plugin 'FEEDBACK' is disabled.
db_1      | 2017-09-13 19:13:49 139725978556288 [Note] Server socket created on IP: '::'.
db_1      | 2017-09-13 19:13:49 139725978556288 [Warning] 'proxies_priv' entry '@% root@9fc6669132a6' ignored in --skip-name-resolve mode.
db_1      | 2017-09-13 19:13:49 139725000136448 [Note] InnoDB: Buffer pool(s) load completed at 170913 19:13:49
pretix_1  | Operations to perform:
pretix_1  |   Apply all migrations: auth, banktransfer, contenttypes, easy_thumbnails, otp_static, otp_totp, paypal, pretixbase, pretixdroid, pretixmultidomain, sessions, stripe
pretix_1  | Running migrations:
pretix_1  |   No migrations to apply.
pretix_1  |   Your models have changes that are not yet reflected in a migration, and so won't be applied.
pretix_1  |   Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.
pretix_1  | 2017-09-13 19:13:51,529 CRIT Supervisor running as root (no user in config file)
pretix_1  | 2017-09-13 19:13:51,536 INFO RPC interface 'supervisor' initialized
pretix_1  | 2017-09-13 19:13:51,536 CRIT Server 'unix_http_server' running without any HTTP authentication checking
pretix_1  | 2017-09-13 19:13:51,536 INFO supervisord started with pid 11
pretix_1  | 2017-09-13 19:13:52,539 INFO spawned: 'pretixweb' with pid 14
pretix_1  | 2017-09-13 19:13:52,543 INFO spawned: 'pretixtask' with pid 15
pretix_1  | 2017-09-13 19:13:52,552 INFO spawned: 'nginx' with pid 16
pretix_1  | 2017-09-13 19:13:53,663 INFO success: pretixweb entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
pretix_1  | 2017-09-13 19:13:53,664 INFO success: pretixtask entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
pretix_1  | 2017-09-13 19:13:53,664 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
pretix_1  | 2017-09-13 19:14:04,988 INFO exited: pretixtask (exit status 1; not expected)
pretix_1  | 2017-09-13 19:14:05,996 INFO spawned: 'pretixtask' with pid 67
pretix_1  | 2017-09-13 19:14:06,999 INFO success: pretixtask entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
pretix_1  | 2017-09-13 19:14:09,399 INFO exited: pretixtask (exit status 1; not expected)
pretix_1  | 2017-09-13 19:14:10,405 INFO spawned: 'pretixtask' with pid 79
pretix_1  | 2017-09-13 19:14:11,408 INFO success: pretixtask entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
pretix_1  | 2017-09-13 19:14:13,244 INFO exited: pretixtask (exit status 1; not expected)
Gracefully stopping... (press Ctrl+C again to force)
Stopping pretix_pretix_1 ...
Stopping pretix_redis_1 ...
Stopping pretix_db_1 ...
Killing pretix_pretix_1 ... done
Killing pretix_redis_1 ... done
Killing pretix_db_1 ... done
raphaelm commented 7 years ago

Hi! :)

The isn't any error to see except pretix_1 | 2017-09-13 19:14:04,988 INFO exited: pretixtask (exit status 1; not expected)

You might need to look into the pretix.log in the data volume, it should tell you more! :)

Speedy1991 commented 7 years ago

Thanks. My Database ist not found by pretix, here is the log:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/celery/utils/dispatch/signal.py", line 227, in send
    response = receiver(signal=self, sender=sender, **named)
  File "/usr/local/lib/python3.6/site-packages/celery/fixups/django.py", line 84, in on_import_modules
    self.worker_fixup.validate_models()
  File "/usr/local/lib/python3.6/site-packages/celery/fixups/django.py", line 123, in validate_models
    run_checks()
  File "/usr/local/lib/python3.6/site-packages/django/core/checks/registry.py", line 81, in run_checks
    new_errors = check(app_configs=app_configs)
  File "/usr/local/lib/python3.6/site-packages/django/core/checks/model_checks.py", line 30, in check_all_models
    errors.extend(model.check(**kwargs))
  File "/usr/local/lib/python3.6/site-packages/django/db/models/base.py", line 1283, in check
    errors.extend(cls._check_fields(**kwargs))
  File "/usr/local/lib/python3.6/site-packages/django/db/models/base.py", line 1358, in _check_fields
    errors.extend(field.check(**kwargs))
  File "/usr/local/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 913, in check
    errors = super(AutoField, self).check(**kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 219, in check
    errors.extend(self._check_backend_specific_checks(**kwargs))
  File "/usr/local/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 322, in _check_backend_specific_checks
    return connections[db].validation.check_field(self, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/db/backends/mysql/validation.py", line 49, in check_field
    field_type = field.db_type(self.connection)
  File "/usr/local/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 644, in db_type
    return connection.data_types[self.get_internal_type()] % data
  File "/usr/local/lib/python3.6/site-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/usr/local/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 174, in data_types
    if self.features.supports_microsecond_precision:
  File "/usr/local/lib/python3.6/site-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/usr/local/lib/python3.6/site-packages/django/db/backends/mysql/features.py", line 53, in supports_microsecond_precision
    return self.connection.mysql_version >= (5, 6, 4) and Database.version_info >= (1, 2, 5)
  File "/usr/local/lib/python3.6/site-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/usr/local/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 385, in mysql_version
    with self.temporary_connection() as cursor:
  File "/usr/local/lib/python3.6/contextlib.py", line 81, in __enter__
    return next(self.gen)
  File "/usr/local/lib/python3.6/site-packages/django/db/backends/base/base.py", line 591, in temporary_connection
    cursor = self.cursor()
  File "/usr/local/lib/python3.6/site-packages/django/db/backends/base/base.py", line 254, in cursor
    return self._cursor()
  File "/usr/local/lib/python3.6/site-packages/django/db/backends/base/base.py", line 229, in _cursor
    self.ensure_connection()
  File "/usr/local/lib/python3.6/site-packages/django/db/backends/base/base.py", line 213, in ensure_connection
    self.connect()
  File "/usr/local/lib/python3.6/site-packages/django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/usr/local/lib/python3.6/site-packages/django/utils/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "/usr/local/lib/python3.6/site-packages/django/db/backends/base/base.py", line 213, in ensure_connection
    self.connect()
  File "/usr/local/lib/python3.6/site-packages/django/db/backends/base/base.py", line 189, in connect
    self.connection = self.get_new_connection(conn_params)
  File "/usr/local/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 274, in get_new_connection
    conn = Database.connect(**conn_params)
  File "/usr/local/lib/python3.6/site-packages/MySQLdb/__init__.py", line 86, in Connect
    return Connection(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/MySQLdb/connections.py", line 204, in __init__
    super(Connection, self).__init__(*args, **kwargs2)
django.db.utils.OperationalError: (2005, "Unknown MySQL server host 'db' (0)")

But db is reachable (inside container):

pretixuser@33609491c9a1:/$ ping db
PING db (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: icmp_seq=0 ttl=64 time=0.041 ms
64 bytes from 172.20.0.2: icmp_seq=1 ttl=64 time=0.124 ms
^C--- db ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.041/0.083/0.124/0.042 ms

Guess i have to dig deeper into the source of pretix :)

€: Update: Found one error, i mounted /etc/ instead of /etc/pretix/ containing the pretix.cfg

raphaelm commented 7 years ago

Hmm, I'm pretty sure that is not a pretix-specific bug. Could you try installing mysql-client into the pretix docker container and manually connect to the database from the container?

Speedy1991 commented 7 years ago

Thank you for your feedback, i mounted the pretix.cfg in the wrong place. Website is up now with all migrations, but visiting localhost/control leads to: Internal Server Error Checking the logs i found:

ERROR 2017-09-14 09:17:20,283 django.request exception Internal Server Error: /control/
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/django_redis/cache.py", line 33, in _decorator
    return method(self, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/django_redis/cache.py", line 82, in get
    client=client)
  File "/usr/local/lib/python3.6/site-packages/django_redis/client/default.py", line 203, in get
    raise ConnectionInterrupted(connection=client, parent=e)
django_redis.exceptions.ConnectionInterrupted: Redis ConnectionError: Error 99 connecting to None:6379. Cannot assign requested address.

Now i am realy confused: The pretixtask doesn't show any error in the logs (conntected to redis). Redis is reachable (checked with ping). The error only occures in pretixweb. I updated my compose + cfg:

docker-compose.yml

version: '3'
services:
  db:
    image: mariadb:latest
    environment:
      - MYSQL_DATABASE=pretix
      - MYSQL_USER=pretix
      - MYSQL_PASSWORD=pretix
      - MYSQL_RANDOM_ROOT_PASSWORD=1
    volumes:
      - db-data:/var/lib/mysql

  redis:
    image: redis:latest

  pretix:
    image: pretix/standalone
    container_name: pretix
    ports:
      - "0.0.0.0:80:80"

    volumes:
      - pretix-data:/data
      - ${PWD}/etc/pretix:/etc/pretix
      - ${PWD}/etc/pretix/pretix.cfg:/etc/pretix/pretix.cfg
    depends_on:
      - db
      - redis

volumes:
  pretix-data:
  db-data:

pretix.cfg

[pretix]
instance_name=My pretix installation
url=localhost
currency=EUR
; DO NOT change the following value, it has to be set to the location of the
; directory *inside* the docker container
datadir=/data

[database]
; Replace mysql with postgresql_psycopg2 for PostgreSQL
backend=mysql
name=pretix
user=pretix
password=pretix
; Replace with host IP address for PostgreSQL
host=db

[mail]
; See config file documentation for more options
from=tickets@yourdomain.com
; This is the default IP address of your docker host in docker's virtual
; network. Make sure postfix listens on this address.
host=172.17.0.1

[redis]
location=redis
; Remove the following line if you are unsure about your redis' security
; to reduce impact if redis gets compromised.
sessions=true

[celery]
backend=redis://redis/10
broker=redis://redis/11
Speedy1991 commented 7 years ago

Ok got i running now - the crontab was kinda hard to put into the container. Why isn't it a celery-beat btw? Is it ok if i put it under deployment/docker-compose in a PR?

raphaelm commented 7 years ago

Ok got i running now - the crontab was kinda hard to put into the container. Why isn't it a celery-beat btw?

No special reason, really. It's another process to run and the problem with celery beat is that it doesn't cluster, it is supposed to be run on one machine only and is therefore not redundant. In my pretix.eu production setup, I just execute the cronjob with different intervals alternating between different machines, so if a machine goes down, the cronjob still executes -- half the time. Sure, I could build something similar with beat somehow, I just didn't so far ;)

Is it ok if i put it under deployment/docker-compose in a PR?

Yep sure! I think that the MariaDB container should have a volume for /var/lib/mysql (or whatever it is in the container) so that nobody accidentally loses all their data when upgrading MariaDB :)

Speedy1991 commented 7 years ago

should have a volume for /var/lib/mysql

The compose in my PR has a docker-volume mounted for the db.

It's not meant as drop-in-replacement. Just an example setup with one cmd for users who just want to try pretix without any configuration or setup

almereyda commented 6 years ago

The PR has been used as a starting point for a separate, opinionated docker compose example in https://github.com/ecobytes/docker-pretix

DottoreTozzi commented 5 years ago

Ok my problems were due to utter stupidity on my part.

Here's my working configuration for the current pretix container, running behind Træfik as reverse proxy:

docker-compose.yml:

version: "3.7"
services:
  dbpretix:
    container_name: dbpretix
    image: postgres:10
    environment:
      POSTGRES_DB: pretix
      POSTGRES_USER: pretix
      POSTGRES_PASSWORD: pretix
    ports:
      - target: 5432
        published: 5432
        protocol: tcp
        mode: host
    volumes:
      - pretix-dbdata:/var/lib/postgresql/data

  redis:
    image: redis:latest
    container_name: redis
    ports:
      - target: 6379
        published: 6379
        protocol: tcp
        mode: host

  pretix:
    image: pretix/standalone:stable
    container_name: pretix
    hostname: tickets
    domainname: mydomain.de
    depends_on:
      - redis
      - dbpretix
    volumes:
      - ${DOCKERDIR}/pretix/config/pretix.cfg:/etc/pretix/pretix.cfg
      - pretix-data:/data
    networks:
      - default
      - traefik_proxy
    labels:
      - "traefik.domain=mydomain.de"
      - "traefik.frontend.rule=Host:tickets.mydomain.de"
      - "traefik.enable=true"
      - "traefik.backend=pretix"
      - "traefik.docker.network=traefik_proxy"
      - "traefik.frontend.headers.SSLRedirect=true"
      - "traefik.frontend.headers.STSSeconds=315360000"
      - "traefik.frontend.headers.browserXSSFilter=true"
      - "traefik.frontend.headers.contentTypeNosniff=true"
      - "traefik.frontend.headers.forceSTSHeader=true"
      - "traefik.frontend.headers.SSLHost=mydomain.de"
      - "traefik.frontend.headers.STSIncludeSubdomains=true"
      - "traefik.frontend.headers.STSPreload=true"
      - "traefik.frontend.headers.frameDeny=false"

networks:
  traefik_proxy:
    external:
      name: traefik_proxy
  default:
    driver: bridge

volumes:
  pretix-data:
    driver: local
  pretix-dbdata:
    driver: local

pretix.cfg:

[pretix]
instance_name=My Ticketshop
url=https://tickets.mydomain.de
currency=EUR
; DO NOT change the following value, it has to be set to the location of the
; directory *inside* the docker container
datadir=/data

[database]
; Replace postgresql with mysql for MySQL
backend=postgresql
name=pretix
user=pretix
; Replace with the password you chose above
password=xxxxxxx
; In most docker setups, 172.17.0.1 is the address of the docker host. Adjuts
; this to wherever your database is running, e.g. the name of a linked container
; or of a mounted MySQL socket.
host=172.17.0.1
port=5432

[mail]
; See config file documentation for more options
from=tickets@heimbrauconvention.de
; This is the default IP address of your docker host in docker's virtual
; network. Make sure postfix listens on this address.
host=172.17.0.1

[redis]
location=redis://172.17.0.1:6379/0
sessions=true

[celery]
backend=redis://172.17.0.1:6379/1
broker=redis://172.17.0.1:6379/2
DottoreTozzi commented 5 years ago

Updated it once more, CRON job and connection to redis are working now, too, me thinks. At least I'm not getting any errors anymore.

Perhaps someone will find this useful as a starting point. I didn't get UNIX Socket connection to redis running, but I don't really care since my event won't attract a huge crowd and it will all be fine the way it is now, I hope.

Træfik as a reverse proxy can't be recommended enough, it takes care of Let's Encrypt certificate and helps setting up a server like a breeze. I've got Wordpress, Typo3, OpenProject, tvial's complete email server solution, Rainloop, and now also pretix, all running perfectly behind it...