diff --git a/Dockerfile b/Dockerfile index 7409fe6..588181a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM php:7-fpm-alpine3.7 +FROM php:7-fpm LABEL maintainer="diego@passbolt.com" @@ -10,50 +10,58 @@ ARG PHP_EXTENSIONS="gd \ pdo_mysql \ xsl" -ARG PHP_GNUPG_BUILD_DEPS="php7-dev \ - make \ - gcc \ - g++ \ - libc-dev \ - pkgconfig \ - re2c \ - gpgme-dev \ - autoconf \ - zlib-dev \ - file" - ARG PECL_PASSBOLT_EXTENSIONS="gnupg \ - redis" + redis \ + mcrypt" -RUN apk add --no-cache $PHP_GNUPG_BUILD_DEPS \ - nginx \ - gpgme \ - gnupg1 \ - mysql-client \ +ARG PASSBOLT_DEV_PACKAGES="libgpgme11-dev \ libpng-dev \ - icu-dev \ - libxslt-dev \ + libicu-dev \ + libxslt1-dev \ libmcrypt-dev \ - supervisor \ - git \ - && pecl install $PECL_PASSBOLT_EXTENSIONS mcrypt-snapshot \ - && docker-php-ext-install -j4 $PHP_EXTENSIONS \ - && docker-php-ext-enable $PHP_EXTENSIONS $PECL_PASSBOLT_EXTENSIONS mcrypt \ - && apk del $PHP_GNUPG_BUILD_DEPS \ - && curl -sS https://getcomposer.org/installer | php \ - && mv composer.phar /usr/local/bin/composer + unzip \ + git" + +ENV PECL_BASE_URL="https://pecl.php.net/get" +ENV PHP_EXT_DIR="/usr/src/php/ext" WORKDIR /var/www/passbolt -RUN curl -sSL $PASSBOLT_URL | tar zxf - -C . --strip-components 1 \ - && composer install --no-dev --optimize-autoloader \ +RUN apt-get update \ + && apt-get -y install --no-install-recommends $PASSBOLT_DEV_PACKAGES \ + nginx \ + gnupg \ + libgpgme11 \ + libmcrypt4 \ + mysql-client \ + supervisor \ + netcat \ + cron \ + && mkdir /home/www-data \ + && chown -R www-data:www-data /home/www-data \ + && usermod -d /home/www-data www-data \ + && docker-php-source extract \ + && for i in $PECL_PASSBOLT_EXTENSIONS; do \ + mkdir $PHP_EXT_DIR/$i; \ + curl -sSL $PECL_BASE_URL/$i | tar zxf - -C $PHP_EXT_DIR/$i --strip-components 1; \ + done \ + && docker-php-ext-install -j4 $PHP_EXTENSIONS $PECL_PASSBOLT_EXTENSIONS \ + && docker-php-ext-enable $PHP_EXTENSIONS $PECL_PASSBOLT_EXTENSIONS \ + && docker-php-source delete \ + && curl -sS https://getcomposer.org/installer | php \ + && mv composer.phar /usr/local/bin/composer \ + && curl -sSL $PASSBOLT_URL | tar zxf - -C . --strip-components 1 \ + && composer install -n --no-dev --optimize-autoloader \ && chown -R www-data:www-data . \ && chmod 775 $(find /var/www/passbolt/tmp -type d) \ && chmod 664 $(find /var/www/passbolt/tmp -type f) \ && chmod 775 $(find /var/www/passbolt/webroot/img/public -type d) \ - && chmod 664 $(find /var/www/passbolt/webroot/img/public -type f) + && chmod 664 $(find /var/www/passbolt/webroot/img/public -type f) \ + && rm /etc/nginx/sites-enabled/default \ + && apt-get purge -y --auto-remove $PASSBOLT_DEV_PACKAGES \ + && rm -rf /var/lib/apt/lists/* COPY conf/passbolt.conf /etc/nginx/conf.d/default.conf -COPY conf/supervisord.conf /etc/supervisord.conf +COPY conf/supervisord.conf /etc/supervisor/supervisord.conf COPY bin/docker-entrypoint.sh /docker-entrypoint.sh EXPOSE 80 443 diff --git a/README.md b/README.md index 16ac4dc..69114b5 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ $ docker run --name passbolt \ -e DATASOURCES_DEFAULT_USERNAME= \ -e DATASOURCES_DEFAULT_DATABASE= \ -e APP_FULL_BASE_URL=https://mydomain.com \ - passbolt/passbolt:2.0.0-rc1 + passbolt/passbolt:develop-debian ``` Once the container is running create your first admin user: @@ -133,6 +133,6 @@ $ docker-compose up # Requirements: -* rng-tools are required on host machine to speed up entropy generation on containers. +* rng-tools or haveged are required on host machine to speed up entropy generation on containers. This way gpg key creation on passbolt container will be faster. * mysql >= 5.6 diff --git a/bin/docker-entrypoint.sh b/bin/docker-entrypoint.sh index a13ec1b..f266d14 100755 --- a/bin/docker-entrypoint.sh +++ b/bin/docker-entrypoint.sh @@ -1,6 +1,6 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash -set -eo pipefail +set -euo pipefail gpg_private_key="${PASSBOLT_GPG_SERVER_KEY_PRIVATE:-/var/www/passbolt/config/gpg/serverkey_private.asc}" gpg_public_key="${PASSBOLT_GPG_SERVER_KEY_PUBLIC:-/var/www/passbolt/config/gpg/serverkey.asc}" @@ -8,6 +8,8 @@ gpg_public_key="${PASSBOLT_GPG_SERVER_KEY_PUBLIC:-/var/www/passbolt/config/gpg/s ssl_key='/etc/ssl/certs/certificate.key' ssl_cert='/etc/ssl/certs/certificate.crt' +export GNUPGHOME="/home/www-data/.gnupg" + gpg_gen_key() { key_email="${PASSBOLT_KEY_EMAIL:-passbolt@yourdomain.com}" key_name="${PASSBOLT_KEY_NAME:-Passbolt default user}" @@ -15,25 +17,27 @@ gpg_gen_key() { subkey_length="${PASSBOLT_SUBKEY_LENGTH:-2048}" expiration="${PASSBOLT_KEY_EXPIRATION:-0}" - su -m -c "gpg --batch --gen-key < $gpg_private_key" -ls /bin/sh www-data - su -c "gpg --armor --export $key_email > $gpg_public_key" -ls /bin/sh www-data + su -c "gpg --batch --yes --pinentry-mode loopback --quick-gen-key --passphrase '' $key_email" -ls /bin/bash www-data + + su -c "gpg --armor --export-secret-keys $key_email > $gpg_private_key" -ls /bin/bash www-data + su -c "gpg --armor --export $key_email > $gpg_public_key" -ls /bin/bash www-data } gpg_import_key() { - key_id=$(su -m -c "gpg --with-colons $gpg_private_key | grep sec |cut -f5 -d:" -ls /bin/sh www-data) - su -c "gpg --batch --import $gpg_public_key" -ls /bin/sh www-data - su -c "gpg -K $key_id" -ls /bin/sh www-data || su -m -c "gpg --batch --import $gpg_private_key" -ls /bin/sh www-data + su -c "gpg --batch --import $gpg_public_key" -ls /bin/bash www-data + su -c "gpg --batch --import $gpg_private_key" -ls /bin/bash www-data } gen_ssl_cert() { @@ -44,40 +48,37 @@ gen_ssl_cert() { install() { tables=$(mysql \ - -u "$DATASOURCES_DEFAULT_USERNAME" \ - -h "$DATASOURCES_DEFAULT_HOST" \ - -P "$DATASOURCES_DEFAULT_PORT" \ - -BN -e "SHOW TABLES FROM $DATASOURCES_DEFAULT_DATABASE" \ - -p"$DATASOURCES_DEFAULT_PASSWORD" |wc -l) + -u "${DATASOURCES_DEFAULT_USERNAME:-passbolt}" \ + -h "${DATASOURCES_DEFAULT_HOST:-localhost}" \ + -P "${DATASOURCES_DEFAULT_PORT:-3306}" \ + -BN -e "SHOW TABLES FROM ${DATASOURCES_DEFAULT_DATABASE:-passbolt}" \ + -p"${DATASOURCES_DEFAULT_PASSWORD:-P4ssb0lt}" |wc -l) app_config="/var/www/passbolt/config/app.php" if [ ! -f "$app_config" ]; then - su -c 'cp /var/www/passbolt/config/app.default.php /var/www/passbolt/config/app.php' -s /bin/sh www-data + su -c 'cp /var/www/passbolt/config/app.default.php /var/www/passbolt/config/app.php' -s /bin/bash www-data fi - if [ -z "$PASSBOLT_GPG_SERVER_KEY_FINGERPRINT" ]; then - gpg_auto_fingerprint="$(su -c "gpg --with-fingerprint $gpg_public_key | grep fingerprint | awk '{for(i=4;i<=NF;++i)printf \$i}'" -ls /bin/sh www-data)" + if [ -z "${PASSBOLT_GPG_SERVER_KEY_FINGERPRINT+xxx}" ]; then + gpg_auto_fingerprint="$(su -c "gpg --list-keys --with-colons ${PASSBOLT_KEY_EMAIL:-passbolt@yourdomain.com} |grep fpr |head -1| cut -f10 -d:" -ls /bin/bash www-data)" export PASSBOLT_GPG_SERVER_KEY_FINGERPRINT=$gpg_auto_fingerprint fi if [ "$tables" -eq 0 ]; then - su -c '/var/www/passbolt/bin/cake passbolt install --no-admin --force' -s /bin/sh www-data + su -c '/var/www/passbolt/bin/cake passbolt install --no-admin --force' -s /bin/bash www-data else + su -c '/var/www/passbolt/bin/cake migrations migrate' -s /bin/bash www-data echo "Enjoy! ☮" fi } email_cron_job() { - root_crontab='/etc/crontabs/root' - cron_task_dir='/etc/periodic/1min' - cron_task='/etc/periodic/1min/email_queue_processing' - process_email="/var/www/passbolt/bin/cake EmailQueue.sender --quiet" + printenv > /etc/environment + sed -i 's/=\(.*\)/="\1"/g' /etc/environment + cron_task='/etc/cron.d/passbolt_email' + echo "* * * * * su -c \"source /etc/environment ; /var/www/passbolt/bin/cake EmailQueue.sender\" -s /bin/bash www-data >> /var/log/cron.log 2>&1" >> $cron_task - mkdir -p $cron_task_dir - echo "* * * * * run-parts $cron_task_dir" >> $root_crontab - echo "#!/bin/sh" > $cron_task - chmod +x $cron_task - echo "su -c \"$process_email\" -s /bin/sh www-data" >> $cron_task + crontab /etc/cron.d/passbolt_email } if [ ! -f "$gpg_private_key" ] && [ ! -L "$gpg_private_key" ] || \ @@ -96,4 +97,4 @@ fi install email_cron_job -/usr/bin/supervisord -n -c /etc/supervisord.conf +/usr/bin/supervisord -n diff --git a/conf/supervisord.conf b/conf/supervisord.conf index 9cd1f5a..cb90377 100644 --- a/conf/supervisord.conf +++ b/conf/supervisord.conf @@ -1,15 +1,13 @@ +; supervisor config file + [unix_http_server] -file=/tmp/supervisor.sock ; (the path to the socket file) +file=/var/run/supervisor.sock ; (the path to the socket file) +chmod=0700 ; sockef file mode (default 0700) [supervisord] -logfile=/tmp/supervisord.log ; (main log file;default $CWD/supervisord.log) -logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB) -logfile_backups=10 ; (num of main logfile rotation backups;default 10) -loglevel=info ; (log level;default info; others: debug,warn,trace) -pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid) -nodaemon=false ; (start in foreground if true;default false) -minfds=1024 ; (min. avail startup file descriptors;default 1024) -minprocs=200 ; (min. avail process descriptors;default 200) +logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log) +pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) +childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP) ; the below section must remain in the config file for RPC ; (supervisorctl/web interface) to work, additional interfaces may be @@ -18,19 +16,37 @@ minprocs=200 ; (min. avail process descriptors;default 200) supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface [supervisorctl] -serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket +serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket + +; The [include] section can just contain the "files" setting. This +; setting can list multiple files (separated by whitespace or +; newlines). It can also contain wildcards. The filenames are +; interpreted as relative to this file. Included files *cannot* +; include files themselves. [program:php-fpm] command=php-fpm autostart=true priority=5 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 [program:nginx] -command=nginx -g "pid /tmp/nginx.pid; daemon off;" +command=nginx -g "daemon off;" autostart=true priority=10 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 -[program:crond] -command=crond -f -c /etc/crontabs +[program:cron] +command=cron -f -l autostart=true priority=20 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 diff --git a/docker-compose.yml b/docker-compose.yml index a147a8c..56177fd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,15 +10,16 @@ services: - 3306 passbolt: - image: passbolt/passbolt:2.0.0-rc2-alpine + image: passbolt/passbolt:develop-debian + tty: true depends_on: - db env_file: - env/passbolt.env volumes: - - gpg_volume:/var/www/passbolt/config/gpg - - images_volume:/var/www/passbolt/webroot/img/public/images - ./scripts/wait-for.sh:/usr/bin/wait-for.sh + tmpfs: + - /run command: ["/usr/bin/wait-for.sh", "db:3306", "--", "/docker-entrypoint.sh"] ports: - 80:80 diff --git a/env/passbolt.env b/env/passbolt.env index 01ff892..c5cffef 100644 --- a/env/passbolt.env +++ b/env/passbolt.env @@ -6,6 +6,7 @@ DATASOURCES_DEFAULT_HOST=db DATASOURCES_DEFAULT_USERNAME=passbolt DATASOURCES_DEFAULT_PASSWORD=P4ssb0lt DATASOURCES_DEFAULT_DATABASE=passbolt +DATASOURCES_DEFAULT_PORT=3306 # Misc PASSBOLT_REGISTRATION_PUBLIC=true diff --git a/spec/docker_image/image_spec.rb b/spec/docker_image/image_spec.rb index ef89ec5..81288ef 100644 --- a/spec/docker_image/image_spec.rb +++ b/spec/docker_image/image_spec.rb @@ -26,7 +26,7 @@ describe 'Dockerfile' do let(:composer) { '/usr/local/bin/composer'} let(:php_extensions) { [ 'curl', 'gd', 'intl', 'json', 'mcrypt', 'mysqlnd', 'xsl', 'phar', - 'posix', 'xml', 'xsl', 'zlib', 'ctype', 'pdo', 'gnupg', 'pdo_mysql' + 'posix', 'xml', 'zlib', 'ctype', 'pdo', 'gnupg', 'pdo_mysql' ] } describe 'passbolt required php extensions' do diff --git a/spec/docker_runtime/runtime_spec.rb b/spec/docker_runtime/runtime_spec.rb index 752f6a4..0ce9062 100644 --- a/spec/docker_runtime/runtime_spec.rb +++ b/spec/docker_runtime/runtime_spec.rb @@ -49,17 +49,17 @@ describe 'passbolt_api service' do describe 'php service' do it 'is running supervised' do - expect(process('php-fpm')).to be_running.under('supervisor') + expect(service('php-fpm')).to be_running.under('supervisor') end it 'has its port open' do - expect(port(9000)).to be_listening.with('tcp') + expect(@container.json['Config']['ExposedPorts']).to have_key('9000/tcp') end end describe 'email cron' do it 'is running supervised' do - expect(service('crond')).to be_running.under('supervisor') + expect(service('cron')).to be_running.under('supervisor') end end @@ -69,11 +69,11 @@ describe 'passbolt_api service' do end it 'is listening on port 80' do - expect(port(80)).to be_listening.with('tcp') + expect(@container.json['Config']['ExposedPorts']).to have_key('80/tcp') end it 'is listening on port 443' do - expect(port(443)).to be_listening.with('tcp') + expect(@container.json['Config']['ExposedPorts']).to have_key('443/tcp') end end