From 8ec78343e72d4a5d86de94ff7bf747ccf67ef2fc Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Sat, 19 Feb 2022 16:32:34 +0100 Subject: [PATCH] Update docker setup. It's simple, and it works, but it's not best practice Closes #4 --- Dockerfile | 32 ++++++++++++-- README.md | 45 +++++++++++++++++++- docker-run.sh | 68 ++++++------------------------ examples/docker/email-transport.sh | 5 +++ examples/docker/travelynx.conf | 26 ------------ 5 files changed, 91 insertions(+), 85 deletions(-) create mode 100644 examples/docker/email-transport.sh delete mode 100644 examples/docker/travelynx.conf diff --git a/Dockerfile b/Dockerfile index d916c6c..63f33dc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,27 @@ -FROM debian:stretch-slim +FROM debian:buster-slim as files + +ARG travelynx_version=git + +COPY docker-run.sh /app/ +COPY index.pl /app/ +COPY lib/ /app/lib/ +COPY public/ /app/public/ +COPY templates/ /app/templates/ +COPY share/ /app/share/ + +WORKDIR /app + +RUN ln -sf ../local/imprint.html.ep templates && \ + ln -sf ../local/privacy.html.ep templates && \ + ln -sf ../local/travelynx.conf + +RUN sed -i "s/qx{git describe --dirty}/'${travelynx_version}'/" lib/Travelynx/Controller/Static.pm +RUN sed -i "s/\$self->plugin('Config');/\$self->plugin('Config'); \$self->config->{version} = '${travelynx_version}';/" lib/Travelynx.pm + +FROM perl:5.30-slim ARG DEBIAN_FRONTEND=noninteractive +ARG APT_LISTCHANGES_FRONTEND=none COPY cpanfile* /app/ WORKDIR /app @@ -32,8 +53,11 @@ RUN apt-get update && apt-get install --no-install-recommends -y \ libxml2-dev \ make \ zlib1g-dev \ - && apt-get autoremove -y + && apt-get autoremove -y \ + && rm -rf /var/cache/apt/* /var/lib/apt/lists/* -COPY . /app +COPY --from=files /app/ /app/ -CMD ["/app/docker-run.sh"] +EXPOSE 8093 + +ENTRYPOINT ["/app/docker-run.sh"] diff --git a/README.md b/README.md index 4a9435d..b84e4de 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,10 @@ annotated with real-time delays and service messages. At the moment, it only supports german railways and trains which are exposed by the Deutsche Bahn [IRIS Interface](https://finalrewind.org/projects/Travel-Status-DE-IRIS/). +You can use the public instance on [travelynx.de](https://travelynx.de) or +host your own via carton/cpanminus. Experimental Docker images are also +available. See the Setup notes below. + Dependencies --- @@ -14,9 +18,10 @@ Dependencies * carton or cpanminus * build-essential * libpq-dev + * libxml2-dev * git -Perl Dependencies +Installation --- travelynx depends on a set of Perl modules which are documented in `cpanfile`. @@ -103,6 +108,44 @@ updates automatically in the future. If you used carton for installation, use `carton exec perl ...` in the snippet above; if you used cpanm, export `PERL5LIB=.../local/lib/perl5`. +Setup with Docker +--- + +Note that travelynx Docker support is experimental and, in its current form, +far from best practices. Pull requests are appreciated. + +First, you need to set up a PostgreSQL database so that travelynx can store +user accounts and journeys. It must be at least version 9.4 and must use a +UTF-8 locale. See above (or `examples/docker/postgres-init.sh`) for database +initialization. You do not need to perform the `database migrate` step. + +Next, you need to prepare three files that will be mounted into the travelynx +container: travelynx configuration, e-mail configuration, and imprint and +privacy policy. For the sake of this readme, we assume that you are using the +`local/` directory to store these + +* `mkdir local` +* copy examples/travelynx.conf to local/travelynx.conf and configure it. +* copy examples/docker/email-transport.sh to local/email-transport.sh and configure it. + The travelynx container does not contain a mail server, so it needs a + separate SMTP server to send mail. It does not receive mail. +* create local/imprint.html.ep and enter imprint as well as privacy policy data. +* Configure your web server to reverse-provy requests to the travelynx + instance. See `examples/nginx-site` for an nginx config. + +travelynx consists of two runtimes: the web application and a background +worker. Your service supervisor (or docker compose / docker stack / kubernetes +setup) should orchestrate them somewhere along these lines. + +* `docker pull derfnull/travelynx:latest` +* Start web application: `docker run -p 8093:8093 -v ${PWD}/local:/local:ro travelynx:latest` +* Wait until localhost:8093 responds to requests +* Start worker: `docker run -v ${PWD}/local:/local:ro travelynx:latest worker` + +To install an update: stop worker and web application, update the travelynx +image, and start them again. Database migrations will be performed +automatically. Note that downgrades are not supported. + Usage --- diff --git a/docker-run.sh b/docker-run.sh index c6746c3..a75d5a0 100755 --- a/docker-run.sh +++ b/docker-run.sh @@ -1,62 +1,22 @@ -#!/bin/bash +#!/bin/sh # # Copyright (C) Markus Witt +# Copyright (C) Daniel Friesel # # SPDX-License-Identifier: CC0-1.0 -set -eu -WAIT_DB_HOST=${TRAVELYNX_DB_HOST} -WAIT_DB_PORT=5432 +set -e -check_config() { - if [ ! -f travelynx.conf ] - then - echo "The configuration file is missing" - exit 1 - fi -} - -wait_for_db() { - set +e - for i in $(seq 1 ${WAIT_DB_TIMEOUT:-5}) - do - (echo >/dev/tcp/${WAIT_DB_HOST}/${WAIT_DB_PORT}) &>/dev/null - if [ $? -eq 0 ]; then - break - else - echo "Can't reach DB @ ${WAIT_DB_HOST}:${WAIT_DB_PORT}" - fi - sleep 1 - done - set -e -} - -run_app() { - if [ \ - "${TRAVELYNX_MAIL_DISABLE:-0}" -eq 0 \ - -a "${TRAVELYNX_MAIL_HOST:-unset}" != "unset" \ - ] - then - export EMAIL_SENDER_TRANSPORT=SMTP - export EMAIL_SENDER_TRANSPORT_HOST=${TRAVELYNX_MAIL_HOST} - export EMAIL_SENDER_TRANSPORT_PORT=${TRAVELYNX_MAIL_PORT:-25} - fi - - perl index.pl database migrate - - exec /usr/local/bin/hypnotoad -f index.pl -} - -run_cron() { - exec perl index.pl worker -} - -check_config -wait_for_db - -if [ "${CRON:-0}" -ne "0" ] -then - run_cron +if ! [ -r travelynx.conf ]; then + echo "Configuration file (travelynx.conf) is missing. Did you set up the '/local' mountpoint?" + exit 1 fi -run_app +. local/email-transport.sh + +if [ "$1" = worker ]; then + exec perl index.pl worker +fi + +perl index.pl database migrate +exec hypnotoad -f index.pl diff --git a/examples/docker/email-transport.sh b/examples/docker/email-transport.sh new file mode 100644 index 0000000..c04f187 --- /dev/null +++ b/examples/docker/email-transport.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +export EMAIL_SENDER_TRANSPORT=SMTP +export EMAIL_SENDER_TRANSPORT_HOST=smtp.example.com +export EMAIL_SENDER_TRANSPORT_PORT=25 diff --git a/examples/docker/travelynx.conf b/examples/docker/travelynx.conf deleted file mode 100644 index b3dc003..0000000 --- a/examples/docker/travelynx.conf +++ /dev/null @@ -1,26 +0,0 @@ -{ - cache => { - schedule => $ENV{TRAVELYNX_IRIS_CACHE} // '/var/cache/travelynx/iris', - realtime => $ENV{TRAVELYNX_IRISRT_CACHE} // '/var/cache/travelynx/iris-rt', - }, - db => { - host => $ENV{TRAVELYNX_DB_HOST} // die("Please set TRAVELYNX_DB_HOST"), - database => $ENV{TRAVELYNX_DB_NAME} // 'travelynx', - user => $ENV{TRAVELYNX_DB_USERNAME} // 'travelynx', - password => $ENV{TRAVELYNX_DB_PASSWORD} // die("Please set TRAVELYNX_DB_PASSWORD"), - }, - hypnotoad => { - accepts => $ENV{TRAVELYNX_HYPNOTOAD_ACCEPTS} // 100, - clients => $ENV{TRAVELYNX_HYPNOTOAD_CLIENTS} // 10, - listen => [ $ENV{TRALELYNX_HYPNOTOAD_LISTEN} // 'http://*:8093' ], - pid_file => '/tmp/travelynx.pid', - workers => $ENV{TRAVELYNX_HYPNOTOAD_WORKERS} // 2, - spare => $ENV{TRAVELYNX_HYPNOTOAD_SPARE} // 2, - }, - mail => { - disabled => $ENV{TRAVELYNX_MAIL_DISABLE} // 0, - }, - secrets => [ - $ENV{TRAVELYNX_SECRET} // die("Please set TRAVELYNX_SECRET"), - ], -};