diff --git a/Dockerfile b/Dockerfile index ead94d3..1a81d71 100644 --- a/Dockerfile +++ b/Dockerfile @@ -200,6 +200,7 @@ RUN ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime && echo ${TZ} > /etc/timezo # copy startup script & DB checking script COPY assets/startup.sh /startup.sh +COPY assets/service.sh /service.sh COPY assets/self-test.sh /self-test.sh COPY assets/dbtest.php /dbtest.php @@ -250,6 +251,8 @@ ENV COMPOSER_MEMORY_LIMIT=-1 # If this set then the image will start, run a self test and then exit. It's used for the release process ENV TEST_AND_EXIT= ENV COMPOSER_ALLOW_SUPERUSER=1 +ENV USER_ID=1000 +ENV GROUP_ID=1000 VOLUME [ "/opt/kimai/var" ] @@ -284,7 +287,6 @@ RUN \ ENV APP_ENV=dev ENV DATABASE_URL= ENV memory_limit=256 -USER www-data # production build FROM base AS prod @@ -308,4 +310,3 @@ RUN \ ENV APP_ENV=prod ENV DATABASE_URL= ENV memory_limit=128 -USER www-data diff --git a/assets/service.sh b/assets/service.sh new file mode 100755 index 0000000..99d78e2 --- /dev/null +++ b/assets/service.sh @@ -0,0 +1,60 @@ +#!/bin/bash -x + +function waitForDB() { + # Parse sql connection data + if [ ! -z "$DATABASE_URL" ]; then + DB_TYPE=$(awk -F '[/:@]' '{print $1}' <<< "$DATABASE_URL") + DB_USER=$(awk -F '[/:@]' '{print $4}' <<< "$DATABASE_URL") + DB_PASS=$(awk -F '[/:@]' '{print $5}' <<< "$DATABASE_URL") + DB_HOST=$(awk -F '[/:@]' '{print $6}' <<< "$DATABASE_URL") + DB_PORT=$(awk -F '[/:@]' '{print $7}' <<< "$DATABASE_URL") + DB_BASE=$(awk -F '[/?]' '{print $4}' <<< "$DATABASE_URL") + else + DB_TYPE=${DB_TYPE:mysql} + if [ "$DB_TYPE" == "mysql" ]; then + export DATABASE_URL="${DB_TYPE}://${DB_USER:=kimai}:${DB_PASS:=kimai}@${DB_HOST:=sqldb}:${DB_PORT:=3306}/${DB_BASE:=kimai}" + else + echo "Unknown database type, cannot proceed. Only 'mysql' is supported, received: [$DB_TYPE]" + exit 1 + fi + fi + + re='^[0-9]+$' + if ! [[ $DB_PORT =~ $re ]] ; then + DB_PORT=3306 + fi + + echo "Wait for MySQL DB connection ..." + until php /dbtest.php $DB_HOST $DB_BASE $DB_PORT $DB_USER $DB_PASS; do + echo Checking DB: $? + sleep 3 + done + echo "Connection established" +} + +function handleStartup() { + # These are idempotent, run them anyway + /opt/kimai/bin/console -n kimai:install + /opt/kimai/bin/console -n kimai:update + if [ ! -z "$ADMINPASS" ] && [ ! -a "$ADMINMAIL" ]; then + /opt/kimai/bin/console kimai:create-user superadmin "$ADMINMAIL" ROLE_SUPER_ADMIN "$ADMINPASS" + fi + echo "$KIMAI" > /opt/kimai/var/installed + echo "Kimai2 ready" +} + +function runServer() { + /opt/kimai/bin/console kimai:reload --env="$APP_ENV" + if [ -e /use_apache ]; then + /usr/sbin/apache2ctl -D FOREGROUND + elif [ -e /use_fpm ]; then + exec php-fpm + else + echo "Error, unknown server type" + fi +} + +waitForDB +handleStartup +runServer +exit diff --git a/assets/startup.sh b/assets/startup.sh index 0139c85..187c7e2 100755 --- a/assets/startup.sh +++ b/assets/startup.sh @@ -1,81 +1,65 @@ -#!/bin/bash +#!/bin/bash -x -echo $KIMAI +# shellcheck disable=SC2155 +export KIMAI=$(/opt/kimai/bin/console kimai:version --short) +echo "***********************************************" +echo "STARTING KIMAI VERSION ${KIMAI} in ${APP_ENV}" +echo "***********************************************" -function waitForDB() { - # Parse sql connection data - if [ ! -z "$DATABASE_URL" ]; then - DB_TYPE=$(awk -F '[/:@]' '{print $1}' <<< $DATABASE_URL) - DB_USER=$(awk -F '[/:@]' '{print $4}' <<< $DATABASE_URL) - DB_PASS=$(awk -F '[/:@]' '{print $5}' <<< $DATABASE_URL) - DB_HOST=$(awk -F '[/:@]' '{print $6}' <<< $DATABASE_URL) - DB_PORT=$(awk -F '[/:@]' '{print $7}' <<< $DATABASE_URL) - DB_BASE=$(awk -F '[/?]' '{print $4}' <<< $DATABASE_URL) - else - DB_TYPE=${DB_TYPE:mysql} - if [ "$DB_TYPE" == "mysql" ]; then - export DATABASE_URL="${DB_TYPE}://${DB_USER:=kimai}:${DB_PASS:=kimai}@${DB_HOST:=sqldb}:${DB_PORT:=3306}/${DB_BASE:=kimai}" - else - echo "Unknown database type, cannot proceed. Only 'mysql' is supported, received: [$DB_TYPE]" - exit 1 - fi - fi - re='^[0-9]+$' - if ! [[ $DB_PORT =~ $re ]] ; then - DB_PORT=3306 +function config() { + # set mem limits and copy in custom logger config + if [ -z "$memory_limit" ]; then + memory_limit=256 fi - echo "Wait for MySQL DB connection ..." - until php /dbtest.php $DB_HOST $DB_BASE $DB_PORT $DB_USER $DB_PASS; do - echo Checking DB: $? - sleep 3 - done - echo "Connection established" -} - -function handleStartup() { - # set mem limits and copy in custom logger config if [ "${APP_ENV}" == "prod" ]; then sed "s/128M/${memory_limit}M/g" /usr/local/etc/php/php.ini-production > /usr/local/etc/php/php.ini if [ "${KIMAI:0:1}" -lt "2" ]; then cp /assets/monolog-prod.yaml /opt/kimai/config/packages/monolog.yaml else - assets/monolog.yaml /opt/kimai/config/packages/monolog.yaml + cp /assets/monolog.yaml /opt/kimai/config/packages/monolog.yaml fi else sed "s/128M/${memory_limit}M/g" /usr/local/etc/php/php.ini-development > /usr/local/etc/php/php.ini if [ "${KIMAI:0:1}" -lt "2" ]; then cp /assets/monolog-dev.yaml /opt/kimai/config/packages/monolog.yaml else - assets/monolog.yaml /opt/kimai/config/packages/monolog.yaml + cp /assets/monolog.yaml /opt/kimai/config/packages/monolog.yaml fi fi - # These are idempotent, run them anyway tar -zx -C /opt/kimai -f /var/tmp/public.tgz - /opt/kimai/bin/console -n kimai:install - /opt/kimai/bin/console -n kimai:update - if [ ! -z "$ADMINPASS" ] && [ ! -a "$ADMINMAIL" ]; then - /opt/kimai/bin/console kimai:create-user superadmin $ADMINMAIL ROLE_SUPER_ADMIN $ADMINPASS + + if [ -z "$USER_ID" ]; then + USER_ID=$(id -u www-data) + fi + if [ -z "$GROUP_ID" ]; then + GROUP_ID=$(id -g www-data) fi - export KIMAI=$(/opt/kimai/bin/console kimai:version --short) - echo $KIMAI > /opt/kimai/var/installed - echo "Kimai2 ready" -} -function runServer() { - /opt/kimai/bin/console kimai:reload --env=$APP_ENV - if [ -e /use_apache ]; then - /usr/sbin/apache2ctl -D FOREGROUND - elif [ -e /use_fpm ]; then - exec php-fpm + chown -R $USER_ID:$GROUP_ID /opt/kimai/var + + # if user doesn't exist + if id $USER_ID &>/dev/null; then + echo User already exists else - echo "Error, unknown server type" + echo www-kimai:x:$USER_ID:$GROUP_ID:www-kimai:/var/www:/usr/sbin/nologin >> /etc/passwd + echo www-data:x:33: >> /etc/group + pwconv + fi + + if [ -e /use_apache ]; then + export APACHE_RUN_USER=$(id -nu 33) + export APACHE_RUN_GROUP=$(id -ng 33) + elif [ -e /use_fpm ]; then + sed -i "s/user = .*/user = $USER_ID/g" /usr/local/etc/php-fpm.d/www.conf + sed -i "s/group = .*/group = $GROUP_ID/g" /usr/local/etc/php-fpm.d/www.conf + else + echo "Error, unknown server type" fi } -waitForDB -handleStartup -runServer +config +/service.sh exit diff --git a/compose/docker-compose.apache.cli.yml b/compose/docker-compose.apache.cli.yml new file mode 100644 index 0000000..5f71651 --- /dev/null +++ b/compose/docker-compose.apache.cli.yml @@ -0,0 +1,33 @@ +version: '3.5' +services: + + sqldb: + image: mysql:5.7 + environment: + - MYSQL_DATABASE=kimai + - MYSQL_USER=kimaiuser + - MYSQL_PASSWORD=kimaipassword + - MYSQL_ROOT_PASSWORD=changemeplease + command: --default-storage-engine innodb + restart: unless-stopped + healthcheck: + test: mysqladmin -p$$MYSQL_ROOT_PASSWORD ping -h localhost + interval: 20s + start_period: 10s + timeout: 10s + retries: 3 + + kimai: + image: kimai/kimai2:apache-dev + ports: + - 8001:8001 + environment: + - ADMINMAIL=admin@kimai.local + - ADMINPASS=changemeplease + - DATABASE_URL=mysql://kimaiuser:kimaipassword@sqldb/kimai + - TRUSTED_HOSTS=nginx,localhost,127.0.0.1 + restart: unless-stopped + entrypoint: sh + stdin_open: true # docker run -i + tty: true # docker run -t + diff --git a/docker-compose.yml b/docker-compose.yml index 02f196b..1dd27ca 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -42,6 +42,8 @@ services: - ADMINPASS=changemeplease - DATABASE_URL=mysql://kimaiuser:kimaipassword@sqldb/kimai - TRUSTED_HOSTS=nginx,localhost,127.0.0.1 + - USER_ID=1009 + - GROUP_ID=1009 volumes: - public:/opt/kimai/public # - var:/opt/kimai/var diff --git a/docs/runtime-args.md b/docs/runtime-args.md index cf446c4..ec25d9a 100644 --- a/docs/runtime-args.md +++ b/docs/runtime-args.md @@ -34,6 +34,15 @@ ADMINPASS= ADMINMAIL= ``` +## Changing UID and GID + +It is possible to set the user that FPM or Apache run as. If the user does not exist a new user called www-kimai is created and the server is then run under that user. + +```bash +USER_ID=1000 +GROUP_ID=1000 +``` + ## Alternate DB config It is possible to pass the DB config in individual values. If the ENV variable ```DB_TYPE``` is set then the following values will be expected: