From 08e9b3d53121229fd897676be1be21e6262be61c Mon Sep 17 00:00:00 2001 From: Alexis Saettler Date: Sun, 6 Sep 2020 10:16:54 +0200 Subject: [PATCH] chore: add a master docker build (#4413) --- .github/workflows/docker.yml | 29 +++++ Dockerfile.dev | 82 ------------- docker-compose.dev.yml | 32 +++-- scripts/docker/000-default.conf | 23 ---- scripts/docker/Dockerfile | 189 ++++++++++++++++++++++++++++++ scripts/docker/apache2-foreground | 6 - scripts/docker/cron.sh | 2 +- scripts/docker/entrypoint.sh | 29 ++--- scripts/docker/opcache.ini | 11 -- scripts/docker/queue.sh | 2 +- 10 files changed, 252 insertions(+), 153 deletions(-) create mode 100644 .github/workflows/docker.yml delete mode 100644 Dockerfile.dev delete mode 100644 scripts/docker/000-default.conf create mode 100644 scripts/docker/Dockerfile delete mode 100755 scripts/docker/apache2-foreground delete mode 100644 scripts/docker/opcache.ini diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 000000000..56c4e2d8b --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,29 @@ +name: Docker + +on: + push: + branches: + - 'master' + +jobs: + docker-run: + runs-on: ubuntu-latest + strategy: + fail-fast: false + name: Docker build master + + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - name: Build image + uses: docker/build-push-action@v1 + with: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + repository: monicahq/monica/monica + registry: docker.pkg.github.com + dockerfile: scripts/docker/Dockerfile + add_git_labels: true + labels: org.opencontainers.image.version="master" + tags: master diff --git a/Dockerfile.dev b/Dockerfile.dev deleted file mode 100644 index 79c070ab4..000000000 --- a/Dockerfile.dev +++ /dev/null @@ -1,82 +0,0 @@ -FROM alpine:latest - -RUN apk update && apk upgrade; \ - apk add --virtual .build-deps \ - curl openssl; \ - apk add netcat-openbsd \ - #- base - php7 php7-intl php7-openssl php7-ctype \ - php7-zip php7-zlib \ - php7-redis \ - #- Authentication Guards - php7-session php7-tokenizer \ - #- laravel/cashier sabre/vobject sabre/xml - php7-dom \ - #- intervention/image - php7-fileinfo \ - #- laravel/cashier - php7-gd \ - #- composer - php7-phar php7-json php7-iconv \ - #- laravel/framework sabre/vobject - php7-mbstring \ - #- league/flysystem-aws-s3-v3 - php7-simplexml \ - #- sabre/vobject sabre/xml - php7-xml php7-xmlreader php7-xmlwriter \ - #- mysql - php7-mysqli php7-pdo_mysql \ - #- pgsql - php7-pgsql php7-pdo_pgsql \ - #- vinkla/hashids - php7-bcmath \ - #- sentry/sentry - php7-curl \ - #- cbor-php (webauthn) - php7-gmp \ -# apache variant - apache2 php7-apache2; - -# Create a user to own all the code and assets and give them a working -# directory -RUN mkdir -p /var/www/monica -RUN grep -q apache /etc/group || addgroup -S apache -RUN adduser -D monica apache -h /var/www/monica -WORKDIR /var/www/monica - -# Copy the local (outside Docker) source into the working directory, -# copy system files into their proper homes, and set file ownership -# correctly -COPY . . - -RUN mkdir -p bootstrap/cache; \ - mkdir -p storage; \ - chown -R monica:monica .; \ - chgrp -R apache bootstrap/cache storage; \ - chmod -R g+w bootstrap/cache storage; -COPY .env.dev .env - -# Composer installation -RUN scripts/docker/install-composer.sh - -# Install composer dependencies -USER monica -RUN composer global require hirak/prestissimo; \ - composer install --no-interaction --no-suggest --ignore-platform-reqs; \ - composer global remove hirak/prestissimo; \ - composer clear-cache -USER root - -# Cleanup -RUN apk del .build-deps && \ - rm -rf /var/cache/apk/* - -ENTRYPOINT ["scripts/docker/entrypoint.sh"] - -# Apache2 -COPY scripts/docker/apache2-foreground /usr/local/sbin/ -COPY scripts/docker/000-default.conf /etc/apache2/conf.d/ -RUN echo 'LoadModule rewrite_module modules/mod_rewrite.so' > /etc/apache2/conf.d/rewrite.conf - -EXPOSE 80 -CMD ["apache2-foreground"] diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index a8e36f164..dc486c7d4 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -1,21 +1,29 @@ +### +### ~ Monica dev docker-compose +### +### This file is used for dev purpose. +### The standard monica image definition will be found here: https://github.com/monicahq/docker +### + version: '3' services: - monicahq: + app: build: context: . - dockerfile: Dockerfile.dev - image: monicahq/monicahq:dev + dockerfile: scripts/docker/Dockerfile + image: monica:dev depends_on: - mysql ports: - 8080:80 env_file: .env.dev volumes: - - /var/www/monica/storage - - ./app:/var/www/monica/app - - ./routes:/var/www/monica/routes - - ./database:/var/www/monica/database + - /var/www/html/storage + - ./app:/var/www/html/app + - ./database:/var/www/html/database + - ./resources:/var/www/html/resources + - ./routes:/var/www/html/routes mysql: image: mysql:8 @@ -29,7 +37,7 @@ services: - /var/lib/mysql phpmyadmin: - image: phpmyadmin/phpmyadmin + image: phpmyadmin depends_on: - mysql environment: @@ -38,13 +46,13 @@ services: PMA_PASSWORD: sekret_root_password restart: always ports: - - "3000:80" + - 3000:80 volumes: - - "/sessions" + - /sessions mail: container_name: fake_mail image: mailhog/mailhog ports: - - "8025:8025" - - "1025:1025" + - 8025:8025 + - 1025:1025 diff --git a/scripts/docker/000-default.conf b/scripts/docker/000-default.conf deleted file mode 100644 index 06d473d28..000000000 --- a/scripts/docker/000-default.conf +++ /dev/null @@ -1,23 +0,0 @@ - - ServerAdmin webmaster@localhost - DocumentRoot /var/www/monica/public - - - Options Indexes FollowSymLinks - AllowOverride All - Require all granted - - - - ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/monica/public/$1 - DirectoryIndex index.php - - - - ErrorLog /proc/1/fd/2 - CustomLog /proc/1/fd/1 combined - - - - -# vim: syntax=apache ts=4 sw=4 sts=4 sr noet \ No newline at end of file diff --git a/scripts/docker/Dockerfile b/scripts/docker/Dockerfile new file mode 100644 index 000000000..cb5a18743 --- /dev/null +++ b/scripts/docker/Dockerfile @@ -0,0 +1,189 @@ +### +### ~ Monica dev Dockerfile +### +### This file is used for dev purpose. +### The standard monica image definition will be found here: https://github.com/monicahq/docker +### + +FROM php:7.3-apache + +# opencontainers annotations https://github.com/opencontainers/image-spec/blob/master/annotations.md +LABEL org.opencontainers.image.authors="Alexis Saettler " \ + org.opencontainers.image.title="MonicaHQ, the Personal Relationship Manager" \ + org.opencontainers.image.description="This is MonicaHQ, your personal memory! MonicaHQ is like a CRM but for the friends, family, and acquaintances around you." \ + org.opencontainers.image.url="https://monicahq.com" \ + org.opencontainers.image.vendor="Monica" + +# entrypoint.sh dependencies +RUN set -ex; \ + \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + bash \ + busybox-static \ + ; \ + rm -rf /var/lib/apt/lists/* + +# Install required PHP extensions +RUN set -ex; \ + \ + savedAptMark="$(apt-mark showmanual)"; \ + \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + libicu-dev \ + zlib1g-dev \ + libzip-dev \ + libpng-dev \ + libxml2-dev \ + libfreetype6-dev \ + libjpeg62-turbo-dev \ + libgmp-dev \ + libmemcached-dev \ + libmagickwand-dev \ + ; \ + \ + debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \ + if [ ! -e /usr/include/gmp.h ]; then ln -s /usr/include/$debMultiarch/gmp.h /usr/include/gmp.h; fi;\ + docker-php-ext-configure intl; \ + docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/; \ + docker-php-ext-configure gmp --with-gmp="/usr/include/$debMultiarch"; \ + docker-php-ext-install -j$(nproc) \ + intl \ + zip \ + bcmath \ + gd \ + gmp \ + pdo_mysql \ + mysqli \ + soap \ + ; \ + \ +# pecl will claim success even if one install fails, so we need to perform each install separately + pecl install APCu; \ + pecl install memcached; \ + pecl install redis; \ + pecl install imagick; \ + \ + docker-php-ext-enable \ + apcu \ + memcached \ + redis \ + imagick \ + ; \ + \ +# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies + apt-mark auto '.*' > /dev/null; \ + apt-mark manual $savedAptMark; \ + ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \ + | awk '/=>/ { print $3 }' \ + | sort -u \ + | xargs -r dpkg-query -S \ + | cut -d: -f1 \ + | sort -u \ + | xargs -rt apt-mark manual; \ + \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + rm -rf /var/lib/apt/lists/* + +# Set crontab for schedules +RUN set -ex; \ + \ + mkdir -p /var/spool/cron/crontabs; \ + rm -f /var/spool/cron/crontabs/root; \ + echo '*/5 * * * * php /var/www/html/artisan schedule:run -v' > /var/spool/cron/crontabs/www-data + +# Opcache +ENV PHP_OPCACHE_VALIDATE_TIMESTAMPS="0" \ + PHP_OPCACHE_MAX_ACCELERATED_FILES="20000" \ + PHP_OPCACHE_MEMORY_CONSUMPTION="192" \ + PHP_OPCACHE_MAX_WASTED_PERCENTAGE="10" +RUN set -ex; \ + \ + docker-php-ext-enable opcache; \ + { \ + echo '[opcache]'; \ + echo 'opcache.enable=1'; \ + echo 'opcache.revalidate_freq=0'; \ + echo 'opcache.validate_timestamps=${PHP_OPCACHE_VALIDATE_TIMESTAMPS}'; \ + echo 'opcache.max_accelerated_files=${PHP_OPCACHE_MAX_ACCELERATED_FILES}'; \ + echo 'opcache.memory_consumption=${PHP_OPCACHE_MEMORY_CONSUMPTION}'; \ + echo 'opcache.max_wasted_percentage=${PHP_OPCACHE_MAX_WASTED_PERCENTAGE}'; \ + echo 'opcache.interned_strings_buffer=16'; \ + echo 'opcache.fast_shutdown=1'; \ + } > $PHP_INI_DIR/conf.d/opcache-recommended.ini; \ + \ + echo 'apc.enable_cli=1' >> $PHP_INI_DIR/conf.d/docker-php-ext-apcu.ini; \ + \ + echo 'memory_limit=512M' > $PHP_INI_DIR/conf.d/memory-limit.ini + +RUN set -ex; \ + \ + a2enmod headers rewrite remoteip; \ + { \ + echo RemoteIPHeader X-Real-IP; \ + echo RemoteIPTrustedProxy 10.0.0.0/8; \ + echo RemoteIPTrustedProxy 172.16.0.0/12; \ + echo RemoteIPTrustedProxy 192.168.0.0/16; \ + } > $APACHE_CONFDIR/conf-available/remoteip.conf; \ + a2enconf remoteip + +RUN set -ex; \ + APACHE_DOCUMENT_ROOT=/var/www/html/public; \ + sed -ri -e "s!/var/www/html!${APACHE_DOCUMENT_ROOT}!g" $APACHE_CONFDIR/sites-available/*.conf; \ + sed -ri -e "s!/var/www/!${APACHE_DOCUMENT_ROOT}!g" $APACHE_CONFDIR/apache2.conf $APACHE_CONFDIR/conf-available/*.conf + +WORKDIR /var/www/html + + +# Copy the local (outside Docker) source into the working directory, +# copy system files into their proper homes, and set file ownership +# correctly +COPY --chown=www-data:www-data \ + readme.md \ + CONTRIBUTING.md \ + CHANGELOG.md \ + CONTRIBUTORS \ + LICENSE \ + artisan \ + composer.json \ + composer.lock \ + ./ +COPY --chown=www-data:www-data app ./app +COPY --chown=www-data:www-data bootstrap ./bootstrap +COPY --chown=www-data:www-data config ./config +COPY --chown=www-data:www-data database ./database +COPY --chown=www-data:www-data public ./public +COPY --chown=www-data:www-data resources ./resources +COPY --chown=www-data:www-data routes ./routes + +RUN set -ex; \ + \ + mkdir -p bootstrap/cache; \ + mkdir -p storage; \ + chown -R www-data:www-data bootstrap/cache storage; \ + chmod -R g+w bootstrap/cache storage +COPY --chown=www-data:www-data .env.example .env + +# Composer installation +COPY scripts/docker/install-composer.sh /usr/local/sbin/ +RUN install-composer.sh + +# Install composer dependencies +RUN set -ex; \ + \ + composer global require hirak/prestissimo; \ + mkdir -p storage/framework/views; \ + composer install --no-interaction --no-suggest --no-progress --no-dev --ignore-platform-reqs; \ + composer global remove hirak/prestissimo; \ + \ + composer clear-cache; \ + rm -rf .composer + +COPY scripts/docker/entrypoint.sh \ + scripts/docker/cron.sh \ + scripts/docker/queue.sh \ + /usr/local/bin/ + +ENTRYPOINT ["entrypoint.sh"] +CMD ["apache2-foreground"] diff --git a/scripts/docker/apache2-foreground b/scripts/docker/apache2-foreground deleted file mode 100755 index 549977483..000000000 --- a/scripts/docker/apache2-foreground +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -# Run apache2 -mkdir -p /run/apache2 -rm -f /run/apache2/httpd.pid -httpd -DFOREGROUND "$@" diff --git a/scripts/docker/cron.sh b/scripts/docker/cron.sh index 8a2d3c18d..f38e3a03c 100755 --- a/scripts/docker/cron.sh +++ b/scripts/docker/cron.sh @@ -1,4 +1,4 @@ #!/bin/sh set -eu -/usr/sbin/crond -f -l 0 +exec busybox crond -f -l 0 -L /proc/1/fd/1 diff --git a/scripts/docker/entrypoint.sh b/scripts/docker/entrypoint.sh index 8addb7820..b98d29cf1 100755 --- a/scripts/docker/entrypoint.sh +++ b/scripts/docker/entrypoint.sh @@ -1,9 +1,6 @@ -#!/bin/sh +#!/bin/bash -# return true if specified directory is empty -directory_empty() { - [ -z "$(ls -A "$1/")" ] -} +set -Eeo pipefail # wait for the database to start waitfordb() { @@ -14,7 +11,7 @@ waitfordb() { attempts=0 max_attempts=30 while [ $attempts -lt $max_attempts ]; do - nc -z "${HOST}" "${PORT}" && break + busybox nc -w 1 "${HOST}:${PORT}" && break echo "Waiting for ${HOST}:${PORT}..." sleep 1 let "attempts=attempts+1" @@ -29,9 +26,9 @@ waitfordb() { sleep 3 } -if expr "$1" : "apache" 1>/dev/null || [ "$1" = "php-fpm7" ]; then +if expr "$1" : "apache" 1>/dev/null || [ "$1" = "php-fpm" ]; then - MONICADIR=/var/www/monica + MONICADIR=/var/www/html ARTISAN="php ${MONICADIR}/artisan" # Ensure storage directories are present @@ -41,7 +38,7 @@ if expr "$1" : "apache" 1>/dev/null || [ "$1" = "php-fpm7" ]; then mkdir -p ${STORAGE}/framework/views mkdir -p ${STORAGE}/framework/cache mkdir -p ${STORAGE}/framework/sessions - chown -R monica:apache ${STORAGE} + chown -R www-data:www-data ${STORAGE} chmod -R g+rw ${STORAGE} if [ -z "${APP_KEY:-}" -o "$APP_KEY" = "ChangeMeBy32KeyLengthOrGenerated" ]; then @@ -60,15 +57,13 @@ if expr "$1" : "apache" 1>/dev/null || [ "$1" = "php-fpm7" ]; then ${ARTISAN} sentry:release --release="$release" --commit="$commit" --environment="$SENTRY_ENV" --force -v || true fi - # Run cron - if [ -f "/usr/sbin/crond" ]; then - if [ "$CRON_LEGACY" = "true" ]; then - crond -b -l 0 - else - echo "cron is not launched by default. Add CRON_LEGACY=true, use another container, or use supervisor." - fi + if [ ! -f "${STORAGE}/oauth-public.key" -o ! -f "${STORAGE}/oauth-private.key" ]; then + echo "Passport keys creation ..." + ${ARTISAN} passport:keys + ${ARTISAN} passport:client --personal --no-interaction + echo "! Please be careful to backup $MONICADIR/storage/oauth-public.key and $MONICADIR/storage/oauth-private.key files !" fi fi -exec $@ +exec "$@" diff --git a/scripts/docker/opcache.ini b/scripts/docker/opcache.ini deleted file mode 100644 index b8a42a1f1..000000000 --- a/scripts/docker/opcache.ini +++ /dev/null @@ -1,11 +0,0 @@ -[opcache] - -opcache.enable=1 -opcache.revalidate_freq=0 -opcache.validate_timestamps=${PHP_OPCACHE_VALIDATE_TIMESTAMPS} -opcache.max_accelerated_files=${PHP_OPCACHE_MAX_ACCELERATED_FILES} -opcache.memory_consumption=${PHP_OPCACHE_MEMORY_CONSUMPTION} -opcache.max_wasted_percentage=${PHP_OPCACHE_MAX_WASTED_PERCENTAGE} -opcache.interned_strings_buffer=16 - -opcache.fast_shutdown=1 \ No newline at end of file diff --git a/scripts/docker/queue.sh b/scripts/docker/queue.sh index c36a77a19..d2150c5d5 100755 --- a/scripts/docker/queue.sh +++ b/scripts/docker/queue.sh @@ -1,4 +1,4 @@ #!/bin/sh set -eu -/usr/bin/php /var/www/monica/artisan queue:work --sleep=10 --timeout=0 --tries=3 --queue=default,migration >/proc/1/fd/1 2>/proc/1/fd/2 +exec php /var/www/html/artisan queue:work --sleep=10 --timeout=0 --tries=3 --queue=default,migration >/proc/1/fd/1 2>/proc/1/fd/2