diff --git a/.github/workflows/build_push.yml b/.github/workflows/build_push.yml index f1b5245..114f864 100644 --- a/.github/workflows/build_push.yml +++ b/.github/workflows/build_push.yml @@ -19,16 +19,22 @@ jobs: id: vars run: echo ::set-output name=tag::$(echo ${GITHUB_REF:10}) - - name: Build image from alpine + - name: Build image from alpine - v5 + run: make build-alpine-v5 TAG="${{steps.vars.outputs.tag}}" + + - name: Push alpine-based image - v5 + run: make push-alpine-v5 TAG="${{steps.vars.outputs.tag}}" + + - name: Build image from alpine - v4 run: make build-alpine TAG="${{steps.vars.outputs.tag}}" - - name: Push alpine-based image + - name: Push alpine-based image - v4 run: make push-alpine TAG="${{steps.vars.outputs.tag}}" - - name: Build image from debian + - name: Build image from debian - v4 run: make build-debian TAG="${{steps.vars.outputs.tag}}" - - name: Push debian-based image + - name: Push debian-based image - v4 run: make push-debian TAG="${{steps.vars.outputs.tag}}" - name: Logout from DockerHub diff --git a/Makefile b/Makefile index 47b467c..b7373b9 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,9 @@ HUB_NAMESPACE="invoiceninja" # Image name IMAGE="invoiceninja" +# Check if v5 tag is passed, so that a v5 version should be built +IS_V5=$(shell echo ${TAG} | egrep ^5) + # Building docker images based on alpine. # Assigned tags: @@ -15,17 +18,41 @@ IMAGE="invoiceninja" # - :alpine- .PHONY: build-alpine build-alpine: +ifeq ($(IS_V5),) $(info Make: Building "$(TAG)" tagged images from alpine.) @docker build -t ${HUB_NAMESPACE}/${IMAGE}:alpine-${TAG} --build-arg INVOICENINJA_VERSION=${TAG} --file ./alpine/Dockerfile . - @docker tag ${HUB_NAMESPACE}/${IMAGE}:alpine-${TAG} ${HUB_NAMESPACE}/${IMAGE}:alpine + # Tag as alpine-4 + @docker tag ${HUB_NAMESPACE}/${IMAGE}:alpine-${TAG} ${HUB_NAMESPACE}/${IMAGE}:alpine-4 $(info Make: Done.) +endif .PHONY: push-alpine push-alpine: +ifeq ($(IS_V5),) $(info Make: Pushing tagged images from alpine.) @docker push ${HUB_NAMESPACE}/${IMAGE}:alpine-${TAG} @docker push ${HUB_NAMESPACE}/${IMAGE}:alpine $(info Make: Done.) +endif + +.PHONY: build-alpine-v5 +build-alpine-v5: +ifneq ($(IS_V5),) + $(info Make: Building "$(TAG)" tagged images from alpine.) + @docker build -t ${HUB_NAMESPACE}/${IMAGE}:${TAG} --build-arg INVOICENINJA_VERSION=${TAG} --file ./alpine/Dockerfile_v5 . + @docker tag ${HUB_NAMESPACE}/${IMAGE}:${TAG} ${HUB_NAMESPACE}/${IMAGE}:5 + @docker tag ${HUB_NAMESPACE}/${IMAGE}:${TAG} ${HUB_NAMESPACE}/${IMAGE}:latest + $(info Make: Done.) +endif + +.PHONY: push-alpine-v5 +push-alpine-v5: +ifneq ($(IS_V5),) + $(info Make: Pushing tagged images from alpine.) + @docker push ${HUB_NAMESPACE}/${IMAGE}:${TAG} + @docker push ${HUB_NAMESPACE}/${IMAGE}:5 + @docker push ${HUB_NAMESPACE}/${IMAGE}:latest +endif # Building docker images based on debian. # Assigned tags: @@ -33,14 +60,17 @@ push-alpine: # - : .PHONY: build-debian build-debian: +ifeq ($(IS_V5),) $(info Make: Building "$(TAG)" tagged images from debian.) @docker build -t ${HUB_NAMESPACE}/${IMAGE}:${TAG} --build-arg INVOICENINJA_VERSION=${TAG} --file ./debian/Dockerfile . - @docker tag ${HUB_NAMESPACE}/${IMAGE}:${TAG} ${HUB_NAMESPACE}/${IMAGE}:latest $(info Make: Done.) +endif .PHONY: push-debian push-debian: +ifeq ($(IS_V5),) $(info Make: Pushing tagged images from debian.) @docker push ${HUB_NAMESPACE}/${IMAGE}:${TAG} @docker push ${HUB_NAMESPACE}/${IMAGE}:latest - $(info Make: Done.) \ No newline at end of file + $(info Make: Done.) +endif \ No newline at end of file diff --git a/alpine/Dockerfile_v5 b/alpine/Dockerfile_v5 new file mode 100644 index 0000000..dd58fa3 --- /dev/null +++ b/alpine/Dockerfile_v5 @@ -0,0 +1,97 @@ +ARG PHP_VERSION=7.3 + +# Get Invoice Ninja +FROM alpine:latest as base +ARG INVOICENINJA_VERSION + +RUN set -eux; \ + apk add --no-cache \ + curl \ + libarchive-tools; \ + mkdir -p /var/www/app + +RUN curl -o /tmp/ninja.tar.gz -LJ0 https://github.com/invoiceninja/invoiceninja/tarball/v$INVOICENINJA_VERSION \ + && bsdtar --strip-components=1 -C /var/www/app -xf /tmp/ninja.tar.gz \ + && rm /tmp/ninja.tar.gz \ + && cp -R /var/www/app/storage /var/www/app/docker-backup-storage \ + && cp -R /var/www/app/public /var/www/app/docker-backup-public \ + && mkdir -p /var/www/app/public/logo /var/www/app/storage \ + && cp /var/www/app/.env.example /var/www/app/.env \ + && cp /var/www/app/.env.dusk.example /var/www/app/.env.dusk.local \ + && rm -rf /var/www/app/docs /var/www/app/tests + +# Install nodejs packages +FROM node:12-alpine as frontend + +COPY --from=base /var/www/app /var/www/app +WORKDIR /var/www/app/ + +RUN npm install + +# Prepare php image +FROM php:${PHP_VERSION}-fpm-alpine +ARG INVOICENINJA_VERSION + +LABEL maintainer="Samuel Laulhau , Holger Lösken " + +WORKDIR /var/www/app + +COPY --from=frontend /var/www/app /var/www/app +COPY ./alpine/entrypoint_v5.sh /usr/local/bin/docker-entrypoint +RUN chmod +x /usr/local/bin/docker-entrypoint + +RUN set -eux; \ + apk add --no-cache \ + freetype-dev \ + gmp-dev \ + libjpeg-turbo-dev \ + libpng-dev \ + libzip-dev; \ + docker-php-ext-configure zip --with-libzip; \ + docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/; \ + docker-php-ext-install -j$(nproc) \ + bcmath \ + exif \ + gd \ + gmp \ + mbstring \ + mysqli \ + opcache \ + pdo \ + pdo_mysql \ + zip + +COPY ./config/php/php.ini /usr/local/etc/php/php.ini +COPY ./config/php/php-cli.ini /usr/local/etc/php/php-cli.ini + +## Separate user +ENV INVOICENINJA_USER=invoiceninja + +RUN addgroup -S "$INVOICENINJA_USER" && \ + adduser \ + --disabled-password \ + --gecos "" \ + --home "$(pwd)" \ + --ingroup "$INVOICENINJA_USER" \ + --no-create-home \ + "$INVOICENINJA_USER"; \ + addgroup "$INVOICENINJA_USER" www-data; \ + chown -R "$INVOICENINJA_USER":"$INVOICENINJA_USER" /var/www/app + +# Install Composer +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer; \ + composer global require hirak/prestissimo; + +USER $INVOICENINJA_USER + +RUN composer install --no-dev --no-suggest --no-progress + +# Override the environment settings from projects .env file +ENV APP_ENV production +ENV LOG errorlog + +# Use to be mounted into nginx +VOLUME /var/www/app/public + +ENTRYPOINT ["docker-entrypoint"] +CMD ["php-fpm"] \ No newline at end of file diff --git a/alpine/entrypoint_v5.sh b/alpine/entrypoint_v5.sh new file mode 100755 index 0000000..00fe18d --- /dev/null +++ b/alpine/entrypoint_v5.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env sh +set -e + +# first arg is `-f` or `--some-option` +if [ "${1#-}" != "$1" ]; then + set -- php-fpm "$@" +fi + +BAK_STORAGE_PATH=/var/www/app/docker-backup-storage/ +BAK_LOGO_PATH=/var/www/app/docker-backup-public/logo/ + +if [ ! -d /var/www/app/storage ]; then + cp -Rp $BAK_STORAGE_PATH /var/www/app/storage +else + if [ -d $BAK_STORAGE_PATH ]; then + IN_STORAGE_BACKUP="$(ls $BAK_STORAGE_PATH)" + for path in $IN_STORAGE_BACKUP; do + if [ ! -e "/var/www/app/storage/$path" ]; then + cp -Rp "$BAK_STORAGE_PATH/$path" "/var/www/app/storage/" + fi + done + fi +fi + +if [ ! -d /var/www/app/public/logo ] && [ -d $BAK_LOGO_PATH ]; then + cp -Rp $BAK_LOGO_PATH /var/www/app/public/logo +else + if [ -d $BAK_LOGO_PATH ]; then + IN_LOGO_BACKUP="$(ls $BAK_LOGO_PATH)" + for path in $IN_LOGO_BACKUP; do + if [ ! -e "/var/www/app/public/logo/$path" ]; then + cp -Rp "$BAK_LOGO_PATH/$path" "/var/www/app/public/logo/" + fi + done + fi +fi + +# compare public volume version with image version +if [ ! -e /var/www/app/public/version ] || [ "$INVOICENINJA_VERSION" != "$(cat /var/www/app/public/version)" ]; then + cp -au /var/www/app/docker-backup-public/* /var/www/app/public/ + echo $INVOICENINJA_VERSION > /var/www/app/public/version +fi + +# Set permission for mounted directories +chown invoiceninja:www-data /var/www/app/storage +chown invoiceninja:www-data /var/www/app/public + +php artisan optimize + +exec docker-php-entrypoint "$@" diff --git a/docker-compose.yml b/docker-compose.yml index 17cc1fd..66b00b4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,12 +28,14 @@ services: - invoiceninja app: - image: invoiceninja/invoiceninja:alpine + image: invoiceninja/invoiceninja:5 restart: always environment: - APP_URL=https://localhost - APP_KEY= - - DB_HOST=db + - MULTI_DB_ENABLED=false + - DB_HOST1=db + - DB_DATABASE1=ninja volumes: # Configure your mounted directories, make sure the folder 'public' and 'storage' # exist, before mounting them