From dc13a973cdc277744584c04e98c5f41d3cac0450 Mon Sep 17 00:00:00 2001 From: Luca Date: Sat, 16 Dec 2023 16:26:31 +0100 Subject: [PATCH] Update Dockerfile and entrypoint for multi-container setup (#54) --- .github/workflows/docker.yml | 18 +++++-- Dockerfile | 10 ++-- README.md | 4 +- ansible-role/pretalx/tasks/main.yml | 12 +++++ ansible-role/pretalx/templates/pretalx.cfg.j2 | 4 +- conf/pretalx.cfg | 4 +- deployment/docker/pretalx.bash | 54 ++++++++++++++----- docker-compose.yml | 5 ++ 8 files changed, 81 insertions(+), 30 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index ba4e011..bea4136 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -7,12 +7,14 @@ on: - '*' pull_request: branches: - - 'master' + - 'main' jobs: build_and_push: - name: Build and push Docker image to Docker Hub + name: Build and push Docker image to Docker Hub or GHCR runs-on: ubuntu-latest + env: + push_to_docker_hub: ${{ secrets.DOCKER_USERNAME != null && secrets.DOCKER_PASSWORD != null }} steps: - name: Checkout uses: actions/checkout@v4 @@ -23,7 +25,7 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - images: pretalx/standalone + images: ${{ env.push_to_docker_hub == 'true' && 'pretalx/standalone' || format('ghcr.io/{0}', github.repository) }} - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -32,12 +34,20 @@ jobs: uses: docker/setup-buildx-action@v3 - name: Login to DockerHub - if: github.event_name != 'pull_request' + if: github.event_name != 'pull_request' && env.push_to_docker_hub == 'true' uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} + - name: Login to GHCR + if: github.event_name != 'pull_request' && env.push_to_docker_hub == 'false' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build and push uses: docker/build-push-action@v5 with: diff --git a/Dockerfile b/Dockerfile index c492b2a..a55b563 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,7 @@ RUN apt-get update && \ /usr/sbin/update-locale LANG=C.UTF-8 && \ mkdir /etc/pretalx && \ mkdir /data && \ + mkdir /public && \ groupadd -g 999 pretalxuser && \ useradd -r -u 999 -g pretalxuser -d /pretalx -ms /bin/bash pretalxuser && \ echo 'pretalxuser ALL=(ALL) NOPASSWD: /usr/bin/supervisord' >> /etc/sudoers @@ -36,19 +37,18 @@ RUN python3 -m pretalx migrate RUN apt-get update && \ apt-get install -y nodejs npm && \ - python3 -m pretalx rebuild && \ - apt-get remove -y nodejs npm && \ apt-get clean && \ - rm -rf /var/lib/apt/lists/* + rm -rf /var/lib/apt/lists/* && \ + python3 -m pretalx rebuild RUN chmod +x /usr/local/bin/pretalx && \ cd /pretalx/src && \ rm -f pretalx.cfg && \ - chown -R pretalxuser:pretalxuser /pretalx /data && \ + chown -R pretalxuser:pretalxuser /pretalx /data /public && \ rm -f /pretalx/src/data/.secret USER pretalxuser -VOLUME ["/etc/pretalx", "/data"] +VOLUME ["/etc/pretalx", "/data", "/public"] EXPOSE 80 ENTRYPOINT ["pretalx"] CMD ["all"] diff --git a/README.md b/README.md index 1683b67..53ff247 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ This repository contains a docker-compose setup as well as an [ansible](https:// traefic as reverse proxy) or change the line to ``ports: - "127.0.0.1:8355:80"`` (if you use nginx). **Change the database password.** * If you don't want to use docker volumes, create directories for the persistent data and make them read-writeable for - the userid 999 and the groupid 999. Change ``pretalx-redis, pretalx-db and pretalx-data`` to the corresponding + the userid 999 and the groupid 999. Change ``pretalx-redis``, ``pretalx-db``, ``pretalx-data`` and ``pretalx-public`` to the corresponding directories you've chosen. * Configure a reverse-proxy for better security and to handle TLS. Pretalx listens on port 80 in the ``pretalxdocker`` network. I recommend to go with traefik for its ease of setup, docker integration and [LetsEncrypt @@ -29,7 +29,7 @@ This repository contains a docker-compose setup as well as an [ansible](https:// ``reverse-proxy-examples/nginx`` * Optional: To adjust the number of [Gunicorn workers](https://docs.gunicorn.org/en/stable/settings.html#workers), provide the container with `GUNICORN_WORKERS` environment variable. Similarly you can use `GUNICORN_MAX_REQUESTS` and - `GUNICORN_MAX_REQUESTS_JITTER` to configure the requests a worker instance will process before restarting. + `GUNICORN_MAX_REQUESTS_JITTER` to configure the requests a worker instance will process before restarting. `GUNICORN_FORWARDED_ALLOW_IPS` lets you specify which IPs to trust (i.e. which reverse proxies' `X-Forwarded-*` headers can be used to infer connection security). Here's how to set an environment variable [in `docker-compose.yml`](https://docs.docker.com/compose/environment-variables/set-environment-variables/) or when using [`docker run` command](https://docs.docker.com/engine/reference/run/#env-environment-variables). diff --git a/ansible-role/pretalx/tasks/main.yml b/ansible-role/pretalx/tasks/main.yml index ca7173e..5179e95 100644 --- a/ansible-role/pretalx/tasks/main.yml +++ b/ansible-role/pretalx/tasks/main.yml @@ -33,6 +33,10 @@ docker_volume: name: pretalx_data +- name: Create pretalx public volume + docker_volume: + name: pretalx_public + - name: Create redis container docker_container: name: pretalx-redis @@ -77,6 +81,7 @@ restart_policy: unless-stopped volumes: - pretalx_data:/data + - pretalx_public:/public - "{{ pretalx_cfg_dir }}/pretalx.cfg:/etc/pretalx/pretalx.cfg" networks: - name: web @@ -84,6 +89,9 @@ labels: traefik.docker.network: "web" traefik.enable: "true" + env: + PRETALX_FILESYSTEM_MEDIA: /public/media + PRETALX_FILESYSTEM_STATIC: /public/static purge_networks: yes register: pretalx_change when: not testsetup @@ -98,6 +106,7 @@ - "80:80" volumes: - pretalx_data:/data + - pretalx_public:/public - "{{ pretalx_cfg_dir }}/pretalx.cfg:/etc/pretalx/pretalx.cfg" networks: - name: web @@ -105,6 +114,9 @@ labels: traefik.docker.network: "web" traefik.enable: "true" + env: + PRETALX_FILESYSTEM_MEDIA: /public/media + PRETALX_FILESYSTEM_STATIC: /public/static purge_networks: yes register: pretalx_change when: testsetup diff --git a/ansible-role/pretalx/templates/pretalx.cfg.j2 b/ansible-role/pretalx/templates/pretalx.cfg.j2 index cdf2648..be945e9 100644 --- a/ansible-role/pretalx/templates/pretalx.cfg.j2 +++ b/ansible-role/pretalx/templates/pretalx.cfg.j2 @@ -1,7 +1,5 @@ [filesystem] -data = /data -media = /data/media -logs = /data/logs +# use PRETALX_FILESYSTEM_* env vars [site] debug = {{ pretalx_debug }} diff --git a/conf/pretalx.cfg b/conf/pretalx.cfg index 84725b3..b0cbf80 100644 --- a/conf/pretalx.cfg +++ b/conf/pretalx.cfg @@ -1,7 +1,5 @@ [filesystem] -data = /data -media = /data/media -logs = /data/logs +# use PRETALX_FILESYSTEM_* env vars [site] ; never run debug in production diff --git a/deployment/docker/pretalx.bash b/deployment/docker/pretalx.bash index 2d44cd2..f1ad2be 100644 --- a/deployment/docker/pretalx.bash +++ b/deployment/docker/pretalx.bash @@ -1,23 +1,50 @@ #!/bin/bash -cd /pretalx/src -export PRETALX_DATA_DIR=/data +cd /pretalx/src || exit 1 +export PRETALX_DATA_DIR="${PRETALX_DATA_DIR:-/data}" export HOME=/pretalx -export GUNICORN_WORKERS="${GUNICORN_WORKERS:-${WEB_CONCURRENCY:-$((2 * $(nproc --all)))}}" -export GUNICORN_MAX_REQUESTS="${GUNICORN_MAX_REQUESTS:-1200}" -export GUNICORN_MAX_REQUESTS_JITTER="${GUNICORN_MAX_REQUESTS_JITTER:-50}" -if [ ! -d /data/logs ]; then - mkdir /data/logs; +PRETALX_FILESYSTEM_LOGS="${PRETALX_FILESYSTEM_LOGS:-/data/logs}" +PRETALX_FILESYSTEM_MEDIA="${PRETALX_FILESYSTEM_MEDIA:-/data/media}" +PRETALX_FILESYSTEM_STATIC="${PRETALX_FILESYSTEM_STATIC:-/pretalx/src/static.dist}" + +GUNICORN_WORKERS="${GUNICORN_WORKERS:-${WEB_CONCURRENCY:-$((2 * $(nproc)))}}" +GUNICORN_MAX_REQUESTS="${GUNICORN_MAX_REQUESTS:-1200}" +GUNICORN_MAX_REQUESTS_JITTER="${GUNICORN_MAX_REQUESTS_JITTER:-50}" +GUNICORN_FORWARDED_ALLOW_IPS="${GUNICORN_FORWARDED_ALLOW_IPS:-127.0.0.1}" + +AUTOMIGRATE="${AUTOMIGRATE:-yes}" +AUTOREBUILD="${AUTOREBUILD:-yes}" + +if [ "$PRETALX_FILESYSTEM_LOGS" != "/data/logs" ]; then + export PRETALX_FILESYSTEM_LOGS fi -if [ ! -d /data/media ]; then - mkdir /data/media; +if [ "$PRETALX_FILESYSTEM_MEDIA" != "/data/media" ]; then + export PRETALX_FILESYSTEM_MEDIA +fi +if [ "$PRETALX_FILESYSTEM_STATIC" != "/pretalx/src/static.dist" ]; then + export PRETALX_FILESYSTEM_STATIC +fi + +if [ ! -d "$PRETALX_FILESYSTEM_LOGS" ]; then + mkdir "$PRETALX_FILESYSTEM_LOGS"; +fi +if [ ! -d "$PRETALX_FILESYSTEM_MEDIA" ]; then + mkdir "$PRETALX_FILESYSTEM_MEDIA"; +fi +if [ "$PRETALX_FILESYSTEM_STATIC" != "/pretalx/src/static.dist" ] && + [ ! -d "$PRETALX_FILESYSTEM_STATIC" ] && + [ "$AUTOREBUILD" = "yes" ]; then + mkdir -p "$PRETALX_FILESYSTEM_STATIC" + flock --nonblock /pretalx/.lockfile python3 -m pretalx rebuild fi if [ "$1" == "cron" ]; then exec python3 -m pretalx runperiodic fi -python3 -m pretalx migrate --noinput +if [ "$AUTOMIGRATE" = "yes" ]; then + python3 -m pretalx migrate --noinput +fi if [ "$1" == "all" ]; then exec sudo /usr/bin/supervisord -n -c /etc/supervisord.conf @@ -29,12 +56,12 @@ if [ "$1" == "webworker" ]; then --workers "${GUNICORN_WORKERS}" \ --max-requests "${GUNICORN_MAX_REQUESTS}" \ --max-requests-jitter "${GUNICORN_MAX_REQUESTS_JITTER}" \ + --forwarded-allow-ips "${GUNICORN_FORWARDED_ALLOW_IPS}" \ --log-level=info \ --bind=0.0.0.0:80 fi if [ "$1" == "taskworker" ]; then - export C_FORCE_ROOT=True exec celery -A pretalx.celery_app worker -l info fi @@ -43,7 +70,8 @@ if [ "$1" == "shell" ]; then fi if [ "$1" == "upgrade" ]; then - exec python3 -m pretalx rebuild + python3 -m pretalx rebuild + exec python3 -m pretalx regenerate_css fi -exec python3 -m pretalx $* +exec python3 -m pretalx "$@" diff --git a/docker-compose.yml b/docker-compose.yml index 2240ac6..82ff75b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,11 +7,15 @@ services: depends_on: - redis - db + environment: + PRETALX_FILESYSTEM_MEDIA: /public/media + PRETALX_FILESYSTEM_STATIC: /public/static ports: - "80:80" volumes: - ./conf/pretalx.cfg:/etc/pretalx/pretalx.cfg:ro - pretalx-data:/data + - pretalx-public:/public labels: traefik.docker.network: "pretalxdocker" traefik.enable: "true" @@ -39,5 +43,6 @@ services: volumes: pretalx-db: pretalx-data: + pretalx-public: pretalx-redis: