diff --git a/3.3/Dockerfile b/3.3/Dockerfile index 6cf9c1d3..f188e8be 100644 --- a/3.3/Dockerfile +++ b/3.3/Dockerfile @@ -74,8 +74,11 @@ RUN wget -O redmine.tar.gz "https://www.redmine.org/releases/redmine-${REDMINE_V && echo "$REDMINE_DOWNLOAD_MD5 redmine.tar.gz" | md5sum -c - \ && tar -xvf redmine.tar.gz --strip-components=1 \ && rm redmine.tar.gz files/delete.me log/delete.me \ - && mkdir -p tmp/pdf public/plugin_assets \ - && chown -R redmine:redmine ./ + && mkdir -p log public/plugin_assets sqlite tmp/pdf tmp/pids \ + && chown -R redmine:redmine ./ \ +# fix permissions for running as an arbitrary user + && chmod -R ugo=rwX config db sqlite \ + && find log tmp -type d -exec chmod 1777 '{}' + RUN set -eux; \ \ @@ -120,6 +123,8 @@ RUN set -eux; \ cp Gemfile.lock "Gemfile.lock.${adapter}"; \ done; \ rm ./config/database.yml; \ +# fix permissions for running as an arbitrary user + chmod ugo=rwX Gemfile.lock; \ \ # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies apt-mark auto '.*' > /dev/null; \ diff --git a/3.3/docker-entrypoint.sh b/3.3/docker-entrypoint.sh index c24cade3..9e3dd4d9 100755 --- a/3.3/docker-entrypoint.sh +++ b/3.3/docker-entrypoint.sh @@ -1,5 +1,6 @@ -#!/bin/bash -set -e +#!/usr/bin/env bash +set -Eeo pipefail +# TODO add "-u" # usage: file_env VAR [DEFAULT] # ie: file_env 'XYZ_DB_PASSWORD' 'example' @@ -23,131 +24,143 @@ file_env() { unset "$fileVar" } +isLikelyRedmine= case "$1" in - rails|rake|passenger) - if [ ! -f './config/database.yml' ]; then - file_env 'REDMINE_DB_MYSQL' - file_env 'REDMINE_DB_POSTGRES' - file_env 'REDMINE_DB_SQLSERVER' - - if [ "$MYSQL_PORT_3306_TCP" ] && [ -z "$REDMINE_DB_MYSQL" ]; then - export REDMINE_DB_MYSQL='mysql' - elif [ "$POSTGRES_PORT_5432_TCP" ] && [ -z "$REDMINE_DB_POSTGRES" ]; then - export REDMINE_DB_POSTGRES='postgres' - fi - - if [ "$REDMINE_DB_MYSQL" ]; then - adapter='mysql2' - host="$REDMINE_DB_MYSQL" - file_env 'REDMINE_DB_PORT' '3306' - file_env 'REDMINE_DB_USERNAME' "${MYSQL_ENV_MYSQL_USER:-root}" - file_env 'REDMINE_DB_PASSWORD' "${MYSQL_ENV_MYSQL_PASSWORD:-${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}" - file_env 'REDMINE_DB_DATABASE' "${MYSQL_ENV_MYSQL_DATABASE:-${MYSQL_ENV_MYSQL_USER:-redmine}}" - file_env 'REDMINE_DB_ENCODING' '' - elif [ "$REDMINE_DB_POSTGRES" ]; then - adapter='postgresql' - host="$REDMINE_DB_POSTGRES" - file_env 'REDMINE_DB_PORT' '5432' - file_env 'REDMINE_DB_USERNAME' "${POSTGRES_ENV_POSTGRES_USER:-postgres}" - file_env 'REDMINE_DB_PASSWORD' "${POSTGRES_ENV_POSTGRES_PASSWORD}" - file_env 'REDMINE_DB_DATABASE' "${POSTGRES_ENV_POSTGRES_DB:-${REDMINE_DB_USERNAME:-}}" - file_env 'REDMINE_DB_ENCODING' 'utf8' - elif [ "$REDMINE_DB_SQLSERVER" ]; then - adapter='sqlserver' - host="$REDMINE_DB_SQLSERVER" - file_env 'REDMINE_DB_PORT' '1433' - file_env 'REDMINE_DB_USERNAME' '' - file_env 'REDMINE_DB_PASSWORD' '' - file_env 'REDMINE_DB_DATABASE' '' - file_env 'REDMINE_DB_ENCODING' '' - else - echo >&2 - echo >&2 'warning: missing REDMINE_DB_MYSQL, REDMINE_DB_POSTGRES, or REDMINE_DB_SQLSERVER environment variables' - echo >&2 - echo >&2 '*** Using sqlite3 as fallback. ***' - echo >&2 - - adapter='sqlite3' - host='localhost' - file_env 'REDMINE_DB_PORT' '' - file_env 'REDMINE_DB_USERNAME' 'redmine' - file_env 'REDMINE_DB_PASSWORD' '' - file_env 'REDMINE_DB_DATABASE' 'sqlite/redmine.db' - file_env 'REDMINE_DB_ENCODING' 'utf8' - - mkdir -p "$(dirname "$REDMINE_DB_DATABASE")" - find "$(dirname "$REDMINE_DB_DATABASE")" \! -user redmine -exec chown redmine '{}' + - fi - - REDMINE_DB_ADAPTER="$adapter" - REDMINE_DB_HOST="$host" - echo "$RAILS_ENV:" > config/database.yml - for var in \ - adapter \ - host \ - port \ - username \ - password \ - database \ - encoding \ - ; do - env="REDMINE_DB_${var^^}" - val="${!env}" - [ -n "$val" ] || continue - echo " $var: \"$val\"" >> config/database.yml - done - else - # parse the database config to get the database adapter name - # so we can use the right Gemfile.lock - adapter="$( - ruby -e " - require 'yaml' - conf = YAML.load_file('./config/database.yml') - puts conf['$RAILS_ENV']['adapter'] - " - )" + rails | rake | passenger ) isLikelyRedmine=1 ;; +esac + +_fix_permissions() { + # https://www.redmine.org/projects/redmine/wiki/RedmineInstall#Step-8-File-system-permissions + if [ "$(id -u)" = '0' ]; then + find config files log public/plugin_assets \! -user redmine -exec chown redmine:redmine '{}' + + fi + # directories 755, files 644: + find config files log public/plugin_assets tmp -type d \! -perm 755 -exec chmod 755 '{}' + 2>/dev/null || : + find config files log public/plugin_assets tmp -type f \! -perm 644 -exec chmod 644 '{}' + 2>/dev/null || : +} + +# allow the container to be started with `--user` +if [ -n "$isLikelyRedmine" ] && [ "$(id -u)" = '0' ]; then + _fix_permissions + exec gosu redmine "$BASH_SOURCE" "$@" +fi + +if [ -n "$isLikelyRedmine" ]; then + _fix_permissions + if [ ! -f './config/database.yml' ]; then + file_env 'REDMINE_DB_MYSQL' + file_env 'REDMINE_DB_POSTGRES' + file_env 'REDMINE_DB_SQLSERVER' + + if [ "$MYSQL_PORT_3306_TCP" ] && [ -z "$REDMINE_DB_MYSQL" ]; then + export REDMINE_DB_MYSQL='mysql' + elif [ "$POSTGRES_PORT_5432_TCP" ] && [ -z "$REDMINE_DB_POSTGRES" ]; then + export REDMINE_DB_POSTGRES='postgres' fi - - # ensure the right database adapter is active in the Gemfile.lock - cp "Gemfile.lock.${adapter}" Gemfile.lock - # install additional gems for Gemfile.local and plugins - bundle check || bundle install --without development test - - if [ ! -s config/secrets.yml ]; then - file_env 'REDMINE_SECRET_KEY_BASE' - if [ "$REDMINE_SECRET_KEY_BASE" ]; then - cat > 'config/secrets.yml' <<-YML - $RAILS_ENV: - secret_key_base: "$REDMINE_SECRET_KEY_BASE" - YML - elif [ ! -f /usr/src/redmine/config/initializers/secret_token.rb ]; then - rake generate_secret_token + + if [ "$REDMINE_DB_MYSQL" ]; then + adapter='mysql2' + host="$REDMINE_DB_MYSQL" + file_env 'REDMINE_DB_PORT' '3306' + file_env 'REDMINE_DB_USERNAME' "${MYSQL_ENV_MYSQL_USER:-root}" + file_env 'REDMINE_DB_PASSWORD' "${MYSQL_ENV_MYSQL_PASSWORD:-${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}" + file_env 'REDMINE_DB_DATABASE' "${MYSQL_ENV_MYSQL_DATABASE:-${MYSQL_ENV_MYSQL_USER:-redmine}}" + file_env 'REDMINE_DB_ENCODING' '' + elif [ "$REDMINE_DB_POSTGRES" ]; then + adapter='postgresql' + host="$REDMINE_DB_POSTGRES" + file_env 'REDMINE_DB_PORT' '5432' + file_env 'REDMINE_DB_USERNAME' "${POSTGRES_ENV_POSTGRES_USER:-postgres}" + file_env 'REDMINE_DB_PASSWORD' "${POSTGRES_ENV_POSTGRES_PASSWORD}" + file_env 'REDMINE_DB_DATABASE' "${POSTGRES_ENV_POSTGRES_DB:-${REDMINE_DB_USERNAME:-}}" + file_env 'REDMINE_DB_ENCODING' 'utf8' + elif [ "$REDMINE_DB_SQLSERVER" ]; then + adapter='sqlserver' + host="$REDMINE_DB_SQLSERVER" + file_env 'REDMINE_DB_PORT' '1433' + file_env 'REDMINE_DB_USERNAME' '' + file_env 'REDMINE_DB_PASSWORD' '' + file_env 'REDMINE_DB_DATABASE' '' + file_env 'REDMINE_DB_ENCODING' '' + else + echo >&2 + echo >&2 'warning: missing REDMINE_DB_MYSQL, REDMINE_DB_POSTGRES, or REDMINE_DB_SQLSERVER environment variables' + echo >&2 + echo >&2 '*** Using sqlite3 as fallback. ***' + echo >&2 + + adapter='sqlite3' + host='localhost' + file_env 'REDMINE_DB_PORT' '' + file_env 'REDMINE_DB_USERNAME' 'redmine' + file_env 'REDMINE_DB_PASSWORD' '' + file_env 'REDMINE_DB_DATABASE' 'sqlite/redmine.db' + file_env 'REDMINE_DB_ENCODING' 'utf8' + + mkdir -p "$(dirname "$REDMINE_DB_DATABASE")" + if [ "$(id -u)" = '0' ]; then + find "$(dirname "$REDMINE_DB_DATABASE")" \! -user redmine -exec chown redmine '{}' + fi fi - if [ "$1" != 'rake' -a -z "$REDMINE_NO_DB_MIGRATE" ]; then - gosu redmine rake db:migrate - fi - - # https://www.redmine.org/projects/redmine/wiki/RedmineInstall#Step-8-File-system-permissions - find files log public/plugin_assets \! -user redmine -exec chown redmine:redmine '{}' + - # directories 755, files 644: - find files log tmp public/plugin_assets -type d \! -perm 755 -exec chmod 755 '{}' + - find files log tmp public/plugin_assets -type f \! -perm 644 -exec chmod 644 '{}' + - - if [ "$1" != 'rake' -a -n "$REDMINE_PLUGINS_MIGRATE" ]; then - gosu redmine rake redmine:plugins:migrate - fi - - # remove PID file to enable restarting the container - rm -f /usr/src/redmine/tmp/pids/server.pid - - if [ "$1" = 'passenger' ]; then - # Don't fear the reaper. - set -- tini -- "$@" + + REDMINE_DB_ADAPTER="$adapter" + REDMINE_DB_HOST="$host" + echo "$RAILS_ENV:" > config/database.yml + for var in \ + adapter \ + host \ + port \ + username \ + password \ + database \ + encoding \ + ; do + env="REDMINE_DB_${var^^}" + val="${!env}" + [ -n "$val" ] || continue + echo " $var: \"$val\"" >> config/database.yml + done + else + # parse the database config to get the database adapter name + # so we can use the right Gemfile.lock + adapter="$(ruby -e " + require 'yaml' + conf = YAML.load_file('./config/database.yml') + puts conf['$RAILS_ENV']['adapter'] + ")" + fi + + # ensure the right database adapter is active in the Gemfile.lock + cp "Gemfile.lock.${adapter}" Gemfile.lock + # install additional gems for Gemfile.local and plugins + bundle check || bundle install --without development test + + if [ ! -s config/secrets.yml ]; then + file_env 'REDMINE_SECRET_KEY_BASE' + if [ -n "$REDMINE_SECRET_KEY_BASE" ]; then + cat > 'config/secrets.yml' <<-YML + $RAILS_ENV: + secret_key_base: "$REDMINE_SECRET_KEY_BASE" + YML + elif [ ! -f config/initializers/secret_token.rb ]; then + rake generate_secret_token fi - - set -- gosu redmine "$@" - ;; -esac + fi + if [ "$1" != 'rake' -a -z "$REDMINE_NO_DB_MIGRATE" ]; then + rake db:migrate + fi + + if [ "$1" != 'rake' -a -n "$REDMINE_PLUGINS_MIGRATE" ]; then + rake redmine:plugins:migrate + fi + + # remove PID file to enable restarting the container + rm -f tmp/pids/server.pid + + if [ "$1" = 'passenger' ]; then + # Don't fear the reaper. + set -- tini -- "$@" + fi +fi exec "$@" diff --git a/3.3/passenger/Dockerfile b/3.3/passenger/Dockerfile index c926b0ac..7f8d5e78 100644 --- a/3.3/passenger/Dockerfile +++ b/3.3/passenger/Dockerfile @@ -27,4 +27,7 @@ RUN set -eux; \ passenger-config install-agent; \ passenger-config download-nginx-engine +# adjust Passenger to write the PID to the same file as "rails server" +ENV PASSENGER_PID_FILE tmp/pids/server.pid + CMD ["passenger", "start"] diff --git a/3.4/Dockerfile b/3.4/Dockerfile index 05fbd8ac..46a67c7c 100644 --- a/3.4/Dockerfile +++ b/3.4/Dockerfile @@ -74,8 +74,11 @@ RUN wget -O redmine.tar.gz "https://www.redmine.org/releases/redmine-${REDMINE_V && echo "$REDMINE_DOWNLOAD_MD5 redmine.tar.gz" | md5sum -c - \ && tar -xvf redmine.tar.gz --strip-components=1 \ && rm redmine.tar.gz files/delete.me log/delete.me \ - && mkdir -p tmp/pdf public/plugin_assets \ - && chown -R redmine:redmine ./ + && mkdir -p log public/plugin_assets sqlite tmp/pdf tmp/pids \ + && chown -R redmine:redmine ./ \ +# fix permissions for running as an arbitrary user + && chmod -R ugo=rwX config db sqlite \ + && find log tmp -type d -exec chmod 1777 '{}' + RUN set -eux; \ \ @@ -120,6 +123,8 @@ RUN set -eux; \ cp Gemfile.lock "Gemfile.lock.${adapter}"; \ done; \ rm ./config/database.yml; \ +# fix permissions for running as an arbitrary user + chmod ugo=rwX Gemfile.lock; \ \ # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies apt-mark auto '.*' > /dev/null; \ diff --git a/3.4/docker-entrypoint.sh b/3.4/docker-entrypoint.sh index c24cade3..9e3dd4d9 100755 --- a/3.4/docker-entrypoint.sh +++ b/3.4/docker-entrypoint.sh @@ -1,5 +1,6 @@ -#!/bin/bash -set -e +#!/usr/bin/env bash +set -Eeo pipefail +# TODO add "-u" # usage: file_env VAR [DEFAULT] # ie: file_env 'XYZ_DB_PASSWORD' 'example' @@ -23,131 +24,143 @@ file_env() { unset "$fileVar" } +isLikelyRedmine= case "$1" in - rails|rake|passenger) - if [ ! -f './config/database.yml' ]; then - file_env 'REDMINE_DB_MYSQL' - file_env 'REDMINE_DB_POSTGRES' - file_env 'REDMINE_DB_SQLSERVER' - - if [ "$MYSQL_PORT_3306_TCP" ] && [ -z "$REDMINE_DB_MYSQL" ]; then - export REDMINE_DB_MYSQL='mysql' - elif [ "$POSTGRES_PORT_5432_TCP" ] && [ -z "$REDMINE_DB_POSTGRES" ]; then - export REDMINE_DB_POSTGRES='postgres' - fi - - if [ "$REDMINE_DB_MYSQL" ]; then - adapter='mysql2' - host="$REDMINE_DB_MYSQL" - file_env 'REDMINE_DB_PORT' '3306' - file_env 'REDMINE_DB_USERNAME' "${MYSQL_ENV_MYSQL_USER:-root}" - file_env 'REDMINE_DB_PASSWORD' "${MYSQL_ENV_MYSQL_PASSWORD:-${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}" - file_env 'REDMINE_DB_DATABASE' "${MYSQL_ENV_MYSQL_DATABASE:-${MYSQL_ENV_MYSQL_USER:-redmine}}" - file_env 'REDMINE_DB_ENCODING' '' - elif [ "$REDMINE_DB_POSTGRES" ]; then - adapter='postgresql' - host="$REDMINE_DB_POSTGRES" - file_env 'REDMINE_DB_PORT' '5432' - file_env 'REDMINE_DB_USERNAME' "${POSTGRES_ENV_POSTGRES_USER:-postgres}" - file_env 'REDMINE_DB_PASSWORD' "${POSTGRES_ENV_POSTGRES_PASSWORD}" - file_env 'REDMINE_DB_DATABASE' "${POSTGRES_ENV_POSTGRES_DB:-${REDMINE_DB_USERNAME:-}}" - file_env 'REDMINE_DB_ENCODING' 'utf8' - elif [ "$REDMINE_DB_SQLSERVER" ]; then - adapter='sqlserver' - host="$REDMINE_DB_SQLSERVER" - file_env 'REDMINE_DB_PORT' '1433' - file_env 'REDMINE_DB_USERNAME' '' - file_env 'REDMINE_DB_PASSWORD' '' - file_env 'REDMINE_DB_DATABASE' '' - file_env 'REDMINE_DB_ENCODING' '' - else - echo >&2 - echo >&2 'warning: missing REDMINE_DB_MYSQL, REDMINE_DB_POSTGRES, or REDMINE_DB_SQLSERVER environment variables' - echo >&2 - echo >&2 '*** Using sqlite3 as fallback. ***' - echo >&2 - - adapter='sqlite3' - host='localhost' - file_env 'REDMINE_DB_PORT' '' - file_env 'REDMINE_DB_USERNAME' 'redmine' - file_env 'REDMINE_DB_PASSWORD' '' - file_env 'REDMINE_DB_DATABASE' 'sqlite/redmine.db' - file_env 'REDMINE_DB_ENCODING' 'utf8' - - mkdir -p "$(dirname "$REDMINE_DB_DATABASE")" - find "$(dirname "$REDMINE_DB_DATABASE")" \! -user redmine -exec chown redmine '{}' + - fi - - REDMINE_DB_ADAPTER="$adapter" - REDMINE_DB_HOST="$host" - echo "$RAILS_ENV:" > config/database.yml - for var in \ - adapter \ - host \ - port \ - username \ - password \ - database \ - encoding \ - ; do - env="REDMINE_DB_${var^^}" - val="${!env}" - [ -n "$val" ] || continue - echo " $var: \"$val\"" >> config/database.yml - done - else - # parse the database config to get the database adapter name - # so we can use the right Gemfile.lock - adapter="$( - ruby -e " - require 'yaml' - conf = YAML.load_file('./config/database.yml') - puts conf['$RAILS_ENV']['adapter'] - " - )" + rails | rake | passenger ) isLikelyRedmine=1 ;; +esac + +_fix_permissions() { + # https://www.redmine.org/projects/redmine/wiki/RedmineInstall#Step-8-File-system-permissions + if [ "$(id -u)" = '0' ]; then + find config files log public/plugin_assets \! -user redmine -exec chown redmine:redmine '{}' + + fi + # directories 755, files 644: + find config files log public/plugin_assets tmp -type d \! -perm 755 -exec chmod 755 '{}' + 2>/dev/null || : + find config files log public/plugin_assets tmp -type f \! -perm 644 -exec chmod 644 '{}' + 2>/dev/null || : +} + +# allow the container to be started with `--user` +if [ -n "$isLikelyRedmine" ] && [ "$(id -u)" = '0' ]; then + _fix_permissions + exec gosu redmine "$BASH_SOURCE" "$@" +fi + +if [ -n "$isLikelyRedmine" ]; then + _fix_permissions + if [ ! -f './config/database.yml' ]; then + file_env 'REDMINE_DB_MYSQL' + file_env 'REDMINE_DB_POSTGRES' + file_env 'REDMINE_DB_SQLSERVER' + + if [ "$MYSQL_PORT_3306_TCP" ] && [ -z "$REDMINE_DB_MYSQL" ]; then + export REDMINE_DB_MYSQL='mysql' + elif [ "$POSTGRES_PORT_5432_TCP" ] && [ -z "$REDMINE_DB_POSTGRES" ]; then + export REDMINE_DB_POSTGRES='postgres' fi - - # ensure the right database adapter is active in the Gemfile.lock - cp "Gemfile.lock.${adapter}" Gemfile.lock - # install additional gems for Gemfile.local and plugins - bundle check || bundle install --without development test - - if [ ! -s config/secrets.yml ]; then - file_env 'REDMINE_SECRET_KEY_BASE' - if [ "$REDMINE_SECRET_KEY_BASE" ]; then - cat > 'config/secrets.yml' <<-YML - $RAILS_ENV: - secret_key_base: "$REDMINE_SECRET_KEY_BASE" - YML - elif [ ! -f /usr/src/redmine/config/initializers/secret_token.rb ]; then - rake generate_secret_token + + if [ "$REDMINE_DB_MYSQL" ]; then + adapter='mysql2' + host="$REDMINE_DB_MYSQL" + file_env 'REDMINE_DB_PORT' '3306' + file_env 'REDMINE_DB_USERNAME' "${MYSQL_ENV_MYSQL_USER:-root}" + file_env 'REDMINE_DB_PASSWORD' "${MYSQL_ENV_MYSQL_PASSWORD:-${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}" + file_env 'REDMINE_DB_DATABASE' "${MYSQL_ENV_MYSQL_DATABASE:-${MYSQL_ENV_MYSQL_USER:-redmine}}" + file_env 'REDMINE_DB_ENCODING' '' + elif [ "$REDMINE_DB_POSTGRES" ]; then + adapter='postgresql' + host="$REDMINE_DB_POSTGRES" + file_env 'REDMINE_DB_PORT' '5432' + file_env 'REDMINE_DB_USERNAME' "${POSTGRES_ENV_POSTGRES_USER:-postgres}" + file_env 'REDMINE_DB_PASSWORD' "${POSTGRES_ENV_POSTGRES_PASSWORD}" + file_env 'REDMINE_DB_DATABASE' "${POSTGRES_ENV_POSTGRES_DB:-${REDMINE_DB_USERNAME:-}}" + file_env 'REDMINE_DB_ENCODING' 'utf8' + elif [ "$REDMINE_DB_SQLSERVER" ]; then + adapter='sqlserver' + host="$REDMINE_DB_SQLSERVER" + file_env 'REDMINE_DB_PORT' '1433' + file_env 'REDMINE_DB_USERNAME' '' + file_env 'REDMINE_DB_PASSWORD' '' + file_env 'REDMINE_DB_DATABASE' '' + file_env 'REDMINE_DB_ENCODING' '' + else + echo >&2 + echo >&2 'warning: missing REDMINE_DB_MYSQL, REDMINE_DB_POSTGRES, or REDMINE_DB_SQLSERVER environment variables' + echo >&2 + echo >&2 '*** Using sqlite3 as fallback. ***' + echo >&2 + + adapter='sqlite3' + host='localhost' + file_env 'REDMINE_DB_PORT' '' + file_env 'REDMINE_DB_USERNAME' 'redmine' + file_env 'REDMINE_DB_PASSWORD' '' + file_env 'REDMINE_DB_DATABASE' 'sqlite/redmine.db' + file_env 'REDMINE_DB_ENCODING' 'utf8' + + mkdir -p "$(dirname "$REDMINE_DB_DATABASE")" + if [ "$(id -u)" = '0' ]; then + find "$(dirname "$REDMINE_DB_DATABASE")" \! -user redmine -exec chown redmine '{}' + fi fi - if [ "$1" != 'rake' -a -z "$REDMINE_NO_DB_MIGRATE" ]; then - gosu redmine rake db:migrate - fi - - # https://www.redmine.org/projects/redmine/wiki/RedmineInstall#Step-8-File-system-permissions - find files log public/plugin_assets \! -user redmine -exec chown redmine:redmine '{}' + - # directories 755, files 644: - find files log tmp public/plugin_assets -type d \! -perm 755 -exec chmod 755 '{}' + - find files log tmp public/plugin_assets -type f \! -perm 644 -exec chmod 644 '{}' + - - if [ "$1" != 'rake' -a -n "$REDMINE_PLUGINS_MIGRATE" ]; then - gosu redmine rake redmine:plugins:migrate - fi - - # remove PID file to enable restarting the container - rm -f /usr/src/redmine/tmp/pids/server.pid - - if [ "$1" = 'passenger' ]; then - # Don't fear the reaper. - set -- tini -- "$@" + + REDMINE_DB_ADAPTER="$adapter" + REDMINE_DB_HOST="$host" + echo "$RAILS_ENV:" > config/database.yml + for var in \ + adapter \ + host \ + port \ + username \ + password \ + database \ + encoding \ + ; do + env="REDMINE_DB_${var^^}" + val="${!env}" + [ -n "$val" ] || continue + echo " $var: \"$val\"" >> config/database.yml + done + else + # parse the database config to get the database adapter name + # so we can use the right Gemfile.lock + adapter="$(ruby -e " + require 'yaml' + conf = YAML.load_file('./config/database.yml') + puts conf['$RAILS_ENV']['adapter'] + ")" + fi + + # ensure the right database adapter is active in the Gemfile.lock + cp "Gemfile.lock.${adapter}" Gemfile.lock + # install additional gems for Gemfile.local and plugins + bundle check || bundle install --without development test + + if [ ! -s config/secrets.yml ]; then + file_env 'REDMINE_SECRET_KEY_BASE' + if [ -n "$REDMINE_SECRET_KEY_BASE" ]; then + cat > 'config/secrets.yml' <<-YML + $RAILS_ENV: + secret_key_base: "$REDMINE_SECRET_KEY_BASE" + YML + elif [ ! -f config/initializers/secret_token.rb ]; then + rake generate_secret_token fi - - set -- gosu redmine "$@" - ;; -esac + fi + if [ "$1" != 'rake' -a -z "$REDMINE_NO_DB_MIGRATE" ]; then + rake db:migrate + fi + + if [ "$1" != 'rake' -a -n "$REDMINE_PLUGINS_MIGRATE" ]; then + rake redmine:plugins:migrate + fi + + # remove PID file to enable restarting the container + rm -f tmp/pids/server.pid + + if [ "$1" = 'passenger' ]; then + # Don't fear the reaper. + set -- tini -- "$@" + fi +fi exec "$@" diff --git a/3.4/passenger/Dockerfile b/3.4/passenger/Dockerfile index 56ef60d2..05aa7eed 100644 --- a/3.4/passenger/Dockerfile +++ b/3.4/passenger/Dockerfile @@ -27,4 +27,7 @@ RUN set -eux; \ passenger-config install-agent; \ passenger-config download-nginx-engine +# adjust Passenger to write the PID to the same file as "rails server" +ENV PASSENGER_PID_FILE tmp/pids/server.pid + CMD ["passenger", "start"] diff --git a/Dockerfile-passenger.template b/Dockerfile-passenger.template index 9214b912..091a0e38 100644 --- a/Dockerfile-passenger.template +++ b/Dockerfile-passenger.template @@ -27,4 +27,7 @@ RUN set -eux; \ passenger-config install-agent; \ passenger-config download-nginx-engine +# adjust Passenger to write the PID to the same file as "rails server" +ENV PASSENGER_PID_FILE tmp/pids/server.pid + CMD ["passenger", "start"] diff --git a/Dockerfile.template b/Dockerfile.template index 136f6c42..43ae9389 100644 --- a/Dockerfile.template +++ b/Dockerfile.template @@ -74,8 +74,11 @@ RUN wget -O redmine.tar.gz "https://www.redmine.org/releases/redmine-${REDMINE_V && echo "$REDMINE_DOWNLOAD_MD5 redmine.tar.gz" | md5sum -c - \ && tar -xvf redmine.tar.gz --strip-components=1 \ && rm redmine.tar.gz files/delete.me log/delete.me \ - && mkdir -p tmp/pdf public/plugin_assets \ - && chown -R redmine:redmine ./ + && mkdir -p log public/plugin_assets sqlite tmp/pdf tmp/pids \ + && chown -R redmine:redmine ./ \ +# fix permissions for running as an arbitrary user + && chmod -R ugo=rwX config db sqlite \ + && find log tmp -type d -exec chmod 1777 '{}' + RUN set -eux; \ \ @@ -120,6 +123,8 @@ RUN set -eux; \ cp Gemfile.lock "Gemfile.lock.${adapter}"; \ done; \ rm ./config/database.yml; \ +# fix permissions for running as an arbitrary user + chmod ugo=rwX Gemfile.lock; \ \ # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies apt-mark auto '.*' > /dev/null; \ diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index c24cade3..9e3dd4d9 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -1,5 +1,6 @@ -#!/bin/bash -set -e +#!/usr/bin/env bash +set -Eeo pipefail +# TODO add "-u" # usage: file_env VAR [DEFAULT] # ie: file_env 'XYZ_DB_PASSWORD' 'example' @@ -23,131 +24,143 @@ file_env() { unset "$fileVar" } +isLikelyRedmine= case "$1" in - rails|rake|passenger) - if [ ! -f './config/database.yml' ]; then - file_env 'REDMINE_DB_MYSQL' - file_env 'REDMINE_DB_POSTGRES' - file_env 'REDMINE_DB_SQLSERVER' - - if [ "$MYSQL_PORT_3306_TCP" ] && [ -z "$REDMINE_DB_MYSQL" ]; then - export REDMINE_DB_MYSQL='mysql' - elif [ "$POSTGRES_PORT_5432_TCP" ] && [ -z "$REDMINE_DB_POSTGRES" ]; then - export REDMINE_DB_POSTGRES='postgres' - fi - - if [ "$REDMINE_DB_MYSQL" ]; then - adapter='mysql2' - host="$REDMINE_DB_MYSQL" - file_env 'REDMINE_DB_PORT' '3306' - file_env 'REDMINE_DB_USERNAME' "${MYSQL_ENV_MYSQL_USER:-root}" - file_env 'REDMINE_DB_PASSWORD' "${MYSQL_ENV_MYSQL_PASSWORD:-${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}" - file_env 'REDMINE_DB_DATABASE' "${MYSQL_ENV_MYSQL_DATABASE:-${MYSQL_ENV_MYSQL_USER:-redmine}}" - file_env 'REDMINE_DB_ENCODING' '' - elif [ "$REDMINE_DB_POSTGRES" ]; then - adapter='postgresql' - host="$REDMINE_DB_POSTGRES" - file_env 'REDMINE_DB_PORT' '5432' - file_env 'REDMINE_DB_USERNAME' "${POSTGRES_ENV_POSTGRES_USER:-postgres}" - file_env 'REDMINE_DB_PASSWORD' "${POSTGRES_ENV_POSTGRES_PASSWORD}" - file_env 'REDMINE_DB_DATABASE' "${POSTGRES_ENV_POSTGRES_DB:-${REDMINE_DB_USERNAME:-}}" - file_env 'REDMINE_DB_ENCODING' 'utf8' - elif [ "$REDMINE_DB_SQLSERVER" ]; then - adapter='sqlserver' - host="$REDMINE_DB_SQLSERVER" - file_env 'REDMINE_DB_PORT' '1433' - file_env 'REDMINE_DB_USERNAME' '' - file_env 'REDMINE_DB_PASSWORD' '' - file_env 'REDMINE_DB_DATABASE' '' - file_env 'REDMINE_DB_ENCODING' '' - else - echo >&2 - echo >&2 'warning: missing REDMINE_DB_MYSQL, REDMINE_DB_POSTGRES, or REDMINE_DB_SQLSERVER environment variables' - echo >&2 - echo >&2 '*** Using sqlite3 as fallback. ***' - echo >&2 - - adapter='sqlite3' - host='localhost' - file_env 'REDMINE_DB_PORT' '' - file_env 'REDMINE_DB_USERNAME' 'redmine' - file_env 'REDMINE_DB_PASSWORD' '' - file_env 'REDMINE_DB_DATABASE' 'sqlite/redmine.db' - file_env 'REDMINE_DB_ENCODING' 'utf8' - - mkdir -p "$(dirname "$REDMINE_DB_DATABASE")" - find "$(dirname "$REDMINE_DB_DATABASE")" \! -user redmine -exec chown redmine '{}' + - fi - - REDMINE_DB_ADAPTER="$adapter" - REDMINE_DB_HOST="$host" - echo "$RAILS_ENV:" > config/database.yml - for var in \ - adapter \ - host \ - port \ - username \ - password \ - database \ - encoding \ - ; do - env="REDMINE_DB_${var^^}" - val="${!env}" - [ -n "$val" ] || continue - echo " $var: \"$val\"" >> config/database.yml - done - else - # parse the database config to get the database adapter name - # so we can use the right Gemfile.lock - adapter="$( - ruby -e " - require 'yaml' - conf = YAML.load_file('./config/database.yml') - puts conf['$RAILS_ENV']['adapter'] - " - )" + rails | rake | passenger ) isLikelyRedmine=1 ;; +esac + +_fix_permissions() { + # https://www.redmine.org/projects/redmine/wiki/RedmineInstall#Step-8-File-system-permissions + if [ "$(id -u)" = '0' ]; then + find config files log public/plugin_assets \! -user redmine -exec chown redmine:redmine '{}' + + fi + # directories 755, files 644: + find config files log public/plugin_assets tmp -type d \! -perm 755 -exec chmod 755 '{}' + 2>/dev/null || : + find config files log public/plugin_assets tmp -type f \! -perm 644 -exec chmod 644 '{}' + 2>/dev/null || : +} + +# allow the container to be started with `--user` +if [ -n "$isLikelyRedmine" ] && [ "$(id -u)" = '0' ]; then + _fix_permissions + exec gosu redmine "$BASH_SOURCE" "$@" +fi + +if [ -n "$isLikelyRedmine" ]; then + _fix_permissions + if [ ! -f './config/database.yml' ]; then + file_env 'REDMINE_DB_MYSQL' + file_env 'REDMINE_DB_POSTGRES' + file_env 'REDMINE_DB_SQLSERVER' + + if [ "$MYSQL_PORT_3306_TCP" ] && [ -z "$REDMINE_DB_MYSQL" ]; then + export REDMINE_DB_MYSQL='mysql' + elif [ "$POSTGRES_PORT_5432_TCP" ] && [ -z "$REDMINE_DB_POSTGRES" ]; then + export REDMINE_DB_POSTGRES='postgres' fi - - # ensure the right database adapter is active in the Gemfile.lock - cp "Gemfile.lock.${adapter}" Gemfile.lock - # install additional gems for Gemfile.local and plugins - bundle check || bundle install --without development test - - if [ ! -s config/secrets.yml ]; then - file_env 'REDMINE_SECRET_KEY_BASE' - if [ "$REDMINE_SECRET_KEY_BASE" ]; then - cat > 'config/secrets.yml' <<-YML - $RAILS_ENV: - secret_key_base: "$REDMINE_SECRET_KEY_BASE" - YML - elif [ ! -f /usr/src/redmine/config/initializers/secret_token.rb ]; then - rake generate_secret_token + + if [ "$REDMINE_DB_MYSQL" ]; then + adapter='mysql2' + host="$REDMINE_DB_MYSQL" + file_env 'REDMINE_DB_PORT' '3306' + file_env 'REDMINE_DB_USERNAME' "${MYSQL_ENV_MYSQL_USER:-root}" + file_env 'REDMINE_DB_PASSWORD' "${MYSQL_ENV_MYSQL_PASSWORD:-${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}" + file_env 'REDMINE_DB_DATABASE' "${MYSQL_ENV_MYSQL_DATABASE:-${MYSQL_ENV_MYSQL_USER:-redmine}}" + file_env 'REDMINE_DB_ENCODING' '' + elif [ "$REDMINE_DB_POSTGRES" ]; then + adapter='postgresql' + host="$REDMINE_DB_POSTGRES" + file_env 'REDMINE_DB_PORT' '5432' + file_env 'REDMINE_DB_USERNAME' "${POSTGRES_ENV_POSTGRES_USER:-postgres}" + file_env 'REDMINE_DB_PASSWORD' "${POSTGRES_ENV_POSTGRES_PASSWORD}" + file_env 'REDMINE_DB_DATABASE' "${POSTGRES_ENV_POSTGRES_DB:-${REDMINE_DB_USERNAME:-}}" + file_env 'REDMINE_DB_ENCODING' 'utf8' + elif [ "$REDMINE_DB_SQLSERVER" ]; then + adapter='sqlserver' + host="$REDMINE_DB_SQLSERVER" + file_env 'REDMINE_DB_PORT' '1433' + file_env 'REDMINE_DB_USERNAME' '' + file_env 'REDMINE_DB_PASSWORD' '' + file_env 'REDMINE_DB_DATABASE' '' + file_env 'REDMINE_DB_ENCODING' '' + else + echo >&2 + echo >&2 'warning: missing REDMINE_DB_MYSQL, REDMINE_DB_POSTGRES, or REDMINE_DB_SQLSERVER environment variables' + echo >&2 + echo >&2 '*** Using sqlite3 as fallback. ***' + echo >&2 + + adapter='sqlite3' + host='localhost' + file_env 'REDMINE_DB_PORT' '' + file_env 'REDMINE_DB_USERNAME' 'redmine' + file_env 'REDMINE_DB_PASSWORD' '' + file_env 'REDMINE_DB_DATABASE' 'sqlite/redmine.db' + file_env 'REDMINE_DB_ENCODING' 'utf8' + + mkdir -p "$(dirname "$REDMINE_DB_DATABASE")" + if [ "$(id -u)" = '0' ]; then + find "$(dirname "$REDMINE_DB_DATABASE")" \! -user redmine -exec chown redmine '{}' + fi fi - if [ "$1" != 'rake' -a -z "$REDMINE_NO_DB_MIGRATE" ]; then - gosu redmine rake db:migrate - fi - - # https://www.redmine.org/projects/redmine/wiki/RedmineInstall#Step-8-File-system-permissions - find files log public/plugin_assets \! -user redmine -exec chown redmine:redmine '{}' + - # directories 755, files 644: - find files log tmp public/plugin_assets -type d \! -perm 755 -exec chmod 755 '{}' + - find files log tmp public/plugin_assets -type f \! -perm 644 -exec chmod 644 '{}' + - - if [ "$1" != 'rake' -a -n "$REDMINE_PLUGINS_MIGRATE" ]; then - gosu redmine rake redmine:plugins:migrate - fi - - # remove PID file to enable restarting the container - rm -f /usr/src/redmine/tmp/pids/server.pid - - if [ "$1" = 'passenger' ]; then - # Don't fear the reaper. - set -- tini -- "$@" + + REDMINE_DB_ADAPTER="$adapter" + REDMINE_DB_HOST="$host" + echo "$RAILS_ENV:" > config/database.yml + for var in \ + adapter \ + host \ + port \ + username \ + password \ + database \ + encoding \ + ; do + env="REDMINE_DB_${var^^}" + val="${!env}" + [ -n "$val" ] || continue + echo " $var: \"$val\"" >> config/database.yml + done + else + # parse the database config to get the database adapter name + # so we can use the right Gemfile.lock + adapter="$(ruby -e " + require 'yaml' + conf = YAML.load_file('./config/database.yml') + puts conf['$RAILS_ENV']['adapter'] + ")" + fi + + # ensure the right database adapter is active in the Gemfile.lock + cp "Gemfile.lock.${adapter}" Gemfile.lock + # install additional gems for Gemfile.local and plugins + bundle check || bundle install --without development test + + if [ ! -s config/secrets.yml ]; then + file_env 'REDMINE_SECRET_KEY_BASE' + if [ -n "$REDMINE_SECRET_KEY_BASE" ]; then + cat > 'config/secrets.yml' <<-YML + $RAILS_ENV: + secret_key_base: "$REDMINE_SECRET_KEY_BASE" + YML + elif [ ! -f config/initializers/secret_token.rb ]; then + rake generate_secret_token fi - - set -- gosu redmine "$@" - ;; -esac + fi + if [ "$1" != 'rake' -a -z "$REDMINE_NO_DB_MIGRATE" ]; then + rake db:migrate + fi + + if [ "$1" != 'rake' -a -n "$REDMINE_PLUGINS_MIGRATE" ]; then + rake redmine:plugins:migrate + fi + + # remove PID file to enable restarting the container + rm -f tmp/pids/server.pid + + if [ "$1" = 'passenger' ]; then + # Don't fear the reaper. + set -- tini -- "$@" + fi +fi exec "$@"