Compare commits

..

91 Commits

Author SHA1 Message Date
Ween Jiann
ff897d568f Change php-alpine from latest to 3.13 (#367) 2021-06-27 18:00:41 +08:00
David Bomba
b0bb0ffd25 Merge pull request #366 from turbo124/master
Rollback php-installer tags
2021-06-27 15:57:54 +10:00
David Bomba
3902b40bc1 remove tags 2021-06-27 15:55:52 +10:00
David Bomba
29e2d93e59 Merge pull request #365 from turbo124/master
Download php-installer
2021-06-27 15:21:28 +10:00
David Bomba
b7aea66e62 Download php-installer 2021-06-27 15:17:43 +10:00
David Bomba
e2db08f207 Update env
Set QUEUE_CONNECTION=database as default
2021-06-07 08:01:09 +10:00
Ffaen
59291d8687 Set trusted proxy value to allow invoiceninja to read nginx headers (#356)
Fixes #355
2021-05-27 00:32:56 +08:00
Ween Jiann
6f747207ec Add values for initial user creation to Chart (#350)
* Added user details in values.yaml

* Fix grammer in README.md

* Remove '1' suffix in DB config

* Add user password to secret

* Bump version

* Updated wait-db

* Bump IN version
2021-05-21 18:32:42 +08:00
Ween Jiann
c2aabd14ac Fix storageClass (#353) 2021-05-18 09:55:04 +08:00
Ffaen
07f1e601ab Update README to add information on env variables (#351)
* Update README to add information on env variables

References #349

* Set APP_URL to https if TLS enabled
2021-05-17 09:41:20 +08:00
Ween Jiann
13423d38c0 Fix chown in v4 (#348) 2021-05-14 09:45:32 +08:00
Ween Jiann
e34ac95617 Use logging with timestamp (#346) 2021-05-13 09:59:43 +08:00
Ween Jiann
6c68882449 Automatically create user and skip setup page (#345)
* Added checks to docker-entrypoint

* Add init scripts feature

* Added backward compatibility

* Added auto user creation

* Updated README.md and env

* Use dbCheck for checking DB connection
2021-05-13 09:41:08 +08:00
Ween Jiann
8e9e7c47da Updated dependent charts (#340)
* Updated dependent charts

* Fix releaser version

* Bump chart version
2021-05-11 09:40:19 +08:00
Ffaen
7da83b40f4 Change github actions chart release branch from master to main (#338)
The repo has renamed their master branch to main: https://github.com/helm/chart-releaser-action
2021-05-11 09:30:11 +08:00
Ween Jiann
1b48ab6983 Fix environment issues (#337)
* Clean env file

* Remove generated .env

* Fix file_env exporting empty values
2021-05-10 16:40:55 +08:00
Ween Jiann
14357b93a1 Update Chart Dependency (#336)
* Updated IN version

* Bump chart version
2021-05-10 12:15:23 +08:00
Ween Jiann
8a68fda3f3 Added volume permissions initcontainer (#335) 2021-05-10 11:40:45 +08:00
Ween Jiann
4ee20766ef Updated chart readme and bump IN version (#323)
* Updated README.md

* Bump chart version

* Fix trailing slash in APP_URL

* Bump IN version
2021-04-09 13:01:27 +08:00
David Bomba
5ba28528c3 Merge pull request #321 from turbo124/master
Set larger client max body size
2021-04-08 10:15:23 +10:00
David Bomba
9388f66a29 Set larger client max body size 2021-04-08 10:14:58 +10:00
Ween Jiann
b445cf0402 Fix Redis password in Chart (#320)
* Fix NOTES.txt

* Added Redis password

* Updated README.md
2021-04-07 22:42:42 +08:00
Ween Jiann
11c8901fe4 Use registry cache 2021-04-07 00:47:20 +08:00
Ween Jiann
3814e957e0 Use Redis Sentinel for chart (#317)
* Added sentinel config

* Bump chart version

* Fix trailing space
2021-04-06 18:18:34 +08:00
Thibaut De Muynck
62b1d8cb94 Added MariaDB to Docker compose for ARM64 (#315)
* Added option to use MariaDB instead of MySQL

* Moved MYSQL environment variables to env file
2021-04-06 09:29:04 +08:00
Ween Jiann
4cd773700e Update .gitignore 2021-04-05 17:31:27 +08:00
Ween Jiann
9f6e086633 Added Redis to Chart (#312)
* Added redis to chart

* Add snappdf config

* Updated configmap

* Updated appVersion
2021-03-29 22:20:33 +08:00
Ween Jiann
8df49feaf8 Update README.md 2021-03-29 00:54:57 +08:00
Ween Jiann
de856d0a88 Remove chmod for rootfs files 2021-03-28 23:39:37 +08:00
Ween Jiann
1f7458c9f7 Update build_push.yml 2021-03-28 23:16:04 +08:00
Ween Jiann
40e3add863 Update README.md 2021-03-28 14:47:40 +08:00
Ween Jiann
f4f8c79ce7 Split docker v4 and v5 files to different directories (#310)
* Move v4/5 files to separate folders

* Updated github build_push.yml action

* Updated docker-compose.yml
2021-03-28 14:18:54 +08:00
Ween Jiann
524e79c486 Build on ARM64 (#307)
* Updated Dockerfile for multiplatform

* Added linux/arm64 to build_push.yml
2021-03-26 09:09:37 +08:00
Ween Jiann
4ec70c8da6 Reshuffle Dockerfile to optimise caching (#306)
* Refactor alpine folder

* Rearrange Dockerfile

* Updated build_push.yml for testing

* Updated build_push.yml for production

* Added IS_DOCKER env

* Added target to build_push.yml
2021-03-25 22:05:47 +08:00
Ween Jiann
176e2c96d6 Fixed entrypoint chown statement (#304)
* Fix entrypoint

* Rescope chart actions
2021-03-25 11:18:23 +08:00
Ween Jiann
36db897022 Update bug_report.md 2021-03-24 23:58:14 +08:00
Lee Ween Jiann
022cf8c1e8 Refactor chart to charts 2021-03-24 10:12:10 +08:00
Lee Ween Jiann
517ef61313 Updated chart README.md 2021-03-24 10:08:17 +08:00
Lee Ween Jiann
8e75344717 Updated token in release.yaml 2021-03-24 09:56:29 +08:00
Ween Jiann
e19641f754 Merge Helm to Master branch (#302)
* Added chart

* Added github actions

* Fix actions

* Added README.md

Co-authored-by: David Bomba <turbo124@gmail.com>
2021-03-24 09:33:29 +08:00
David Bomba
789e49fe1b Merge pull request #301 from lwj5/actions
Rescope build_push.yaml
2021-03-24 12:28:16 +11:00
Lee Ween Jiann
d462cd64ed Rescope build_push.yaml 2021-03-24 09:18:19 +08:00
David Bomba
51629ef283 Merge pull request #300 from lwj5/docker-helm
Updated Dockerfile and supervisord.conf
2021-03-24 11:58:56 +11:00
Lee Ween Jiann
8d37d6a4c5 Added DB_PORT1 to env 2021-03-24 08:40:35 +08:00
Lee Ween Jiann
a604f4e8b6 Updated entrypoint to chown only in <4 2021-03-24 08:14:30 +08:00
Lee Ween Jiann
18fb27ad9f Merge branch 'master' into docker-helm 2021-03-24 07:59:56 +08:00
David Bomba
ff1dfee088 Merge pull request #279 from tms0/cleanup_supervisor
Cleanup supervisor conf
2021-03-24 07:51:13 +11:00
Lee Ween Jiann
f16815e960 Updated supervisor files 2021-03-23 23:18:29 +08:00
Lee Ween Jiann
c0350de418 Modified to fit k8s 2021-03-23 19:47:11 +08:00
David Bomba
f175fa4fb0 Update env 2021-03-20 16:47:37 +11:00
David Bomba
0d93596cde Update README.md 2021-03-05 20:44:54 +11:00
=
10aaf3fb6e Set auto DB backups to optin by default 2021-03-03 16:48:54 +11:00
David Bomba
8117d0c5bd Merge pull request #291 from danielgroen/master
auto db backup script
2021-03-03 16:46:13 +11:00
danielgroen
fef92891cb auto db backup script 2021-03-02 13:05:12 +01:00
David Bomba
7f415803fb Merge pull request #286 from invoiceninja/revert-284-dotenv_improvements
Revert "got all the vars onto the dotenv file"
2021-02-11 16:04:19 +11:00
David Bomba
1caa8c7e70 Revert "got all the vars onto the dotenv file" 2021-02-11 16:04:11 +11:00
David Bomba
e35653fe59 Merge pull request #284 from danielgroen/dotenv_improvements
got all the vars onto the dotenv file
2021-02-09 22:48:47 +11:00
danielgroen
4d7cc8e464 got all the vars onto the dotenv file 2021-02-09 11:35:45 +01:00
David Bomba
f42fc93aa5 Merge branch 'master' into cleanup_supervisor 2021-02-03 09:35:50 +11:00
David Bomba
c6e122b81f Merge pull request #282 from turbo124/master
Remove redis queue worker from defaults
2021-02-03 09:32:29 +11:00
David Bomba
421a1f10e6 Remove redis queue worker from defaults 2021-02-03 09:31:14 +11:00
David Bomba
84db77cde8 Merge pull request #281 from turbo124/master
Improve supervisor configuration
2021-02-01 08:31:32 +11:00
David Bomba
e8706de11c Improve supervisor configuration 2021-02-01 08:30:50 +11:00
Valentin Day
f9f79ceb21 Cleanup supervisor conf 2021-01-28 11:11:24 +01:00
David Bomba
960a85d8a7 Merge pull request #278 from turbo124/master
fix for defaults of supervisor
2021-01-28 21:03:28 +11:00
David Bomba
6cd85f48cd fix for defaults of supervisor 2021-01-28 21:03:09 +11:00
David Bomba
eca3af3da5 Merge pull request #277 from turbo124/master
Adjustments for supervisor
2021-01-28 20:38:28 +11:00
David Bomba
b141cfe449 Adjustments for supervisor 2021-01-28 20:38:03 +11:00
David Bomba
3104ec0be9 Merge pull request #276 from turbo124/master
Adjustments for supervisor
2021-01-28 20:18:21 +11:00
David Bomba
acd778f815 Adjustments for supervisor 2021-01-28 20:18:03 +11:00
David Bomba
0641860c3f Merge pull request #275 from turbo124/master
Adjustments for supervisor
2021-01-28 20:09:27 +11:00
David Bomba
f6564ffb14 Adjustments for supervisor 2021-01-28 20:09:11 +11:00
David Bomba
d751217d9a Merge pull request #274 from turbo124/master
Adjustments for supervisor
2021-01-28 19:59:24 +11:00
David Bomba
9bd40b98df Adjustments for supervisor 2021-01-28 19:59:07 +11:00
David Bomba
54f789d5a1 Merge pull request #273 from turbo124/master
Add supervisor to DockerFile
2021-01-28 19:55:39 +11:00
David Bomba
a6644abaa2 Add supervisor to DockerFile 2021-01-28 19:55:20 +11:00
David Bomba
d42e333248 Merge pull request #272 from turbo124/master
Change from queue:listen to queue:work.
2021-01-28 19:36:01 +11:00
David Bomba
2e4ccb920b Adjustments for supervisor 2021-01-28 19:35:29 +11:00
David Bomba
ebe353ca52 Adjustments for supervisor 2021-01-28 19:34:48 +11:00
David Bomba
1af91f451d Merge pull request #271 from turbo124/master
Remove cron container
2021-01-28 19:31:52 +11:00
David Bomba
386f6ed8c1 Remove cron container 2021-01-28 19:31:20 +11:00
David Bomba
73e88f6042 Merge pull request #270 from tms0/supervisor_v5
Add example to run php-fpm, scheduler and queue worker in the same container with supervisor
2021-01-28 19:30:25 +11:00
Valentin Day
758709a796 Change supervisord logging options 2021-01-28 09:05:50 +01:00
Valentin Day
a67de32b6e Move supervisor example into an examples folder 2021-01-27 15:43:45 +01:00
Valentin Day
49d3e562de Add example to run php-fpm, scheduler and queue worker in the same container with supervisor 2021-01-27 15:30:14 +01:00
David Bomba
7d4afadbb5 Merge pull request #268 from turbo124/master
Add mysql-client back in
2021-01-26 17:13:07 +11:00
David Bomba
3709355309 Add mysql-client back in 2021-01-26 17:12:52 +11:00
David Bomba
4b63e1f76d Merge pull request #265 from lwj5/php
Added install-php-extensions
2021-01-21 13:55:48 +11:00
Lee Ween Jiann
5118eac0ea Added install-php-extensions 2021-01-20 22:56:32 +08:00
David Bomba
486d38d6e1 Merge pull request #263 from turbo124/master
Remove sys_admin, add application variable
2021-01-19 07:39:15 +11:00
David Bomba
89ae36315d Remove sys_admin, add application variable 2021-01-19 07:38:54 +11:00
45 changed files with 2505 additions and 298 deletions

View File

@@ -7,20 +7,52 @@ assignees: ''
---
# Before creating an issue
<!--
*** Before creating an issue ***
*** Be sure the issue isn't yet reported here or dicussed on stackoverflow ***
-->
Be sure the issue isn't yet reported here or dicussed on stackoverflow
**Setup information**
<!-- Remove accordingly -->
docker run / docker-compose / Helm
# Logs
**Describe the bug**
A clear and concise description of what the bug is.
Did you check the logs ?
If any Error is present there please copy/paste it below
**To reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots/logs**
If applicable, add screenshots to help explain your problem.
<!-- Did you check the logs? If any Error is present there please copy/paste it below -->
```
Any Error that sucks
```
# Setup information
**Docker/Kubernetes/Helm**:
- Output of `docker version`:
```
(paste your output here)
```
<!-- Additional info if using helm on k8s, add the info below -->
<!-- Delete this block if not applicable -->
- Output of `helm version`:
```
(paste your output here)
```
- Output of `kubectl version`:
```
(paste your output here)
```
<!-- End Additional info if using helm on k8s -->
What version do you run?
Do you run docker-compose or a single Dockerfile ?
**Additional context**
Add any other context about the problem here.

6
.github/ct-install.yaml vendored Normal file
View File

@@ -0,0 +1,6 @@
chart-dirs:
- charts
chart-repos:
- bitnami=https://charts.bitnami.com/bitnami
check-version-increment: true
debug: true

9
.github/ct-lint.yaml vendored Normal file
View File

@@ -0,0 +1,9 @@
chart-dirs:
- charts
chart-repos:
- bitnami=https://charts.bitnami.com/bitnami
check-version-increment: true
debug: false
validate-chart-schema: true
validate-maintainers: true
validate-yaml: true

View File

@@ -1,35 +1,77 @@
name: Docker images
name: Publish Releases to Hub
# When its time to do a release do a full cross platform build for all supported
# architectures and push all of them to Docker Hub.
# Only trigger on semver shaped tags.
# Ref: https://github.com/metcalfc/docker-action-examples/blob/main/.github/workflows/release.yml
on:
release:
types: [published]
push:
tags-ignore:
- "invoiceninja-*"
jobs:
deploy:
name: Build images
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Login to DockerHub
run: echo ${{ secrets.DOCKERHUB_PASSWORD }} | docker login -u ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin
- name: Get the latest tag
id: vars
run: echo ::set-output name=tag::$(echo ${GITHUB_REF:10})
- name: Checkout
uses: actions/checkout@v2
- name: Build image from alpine - v5
run: make build-alpine-v5 TAG="${{steps.vars.outputs.tag}}"
- name: Prepare
id: prep
run: |
DOCKER_IMAGE=invoiceninja/invoiceninja
VERSION=edge
if [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
fi
TAGS="${DOCKER_IMAGE}:${VERSION}"
MAJOR="$(echo "${VERSION}" | cut -d. -f1)"
MINOR="$(echo "${VERSION}" | cut -d. -f2)"
TAGS="$TAGS,${DOCKER_IMAGE}:${MAJOR},${DOCKER_IMAGE}:${MAJOR}.${MINOR}"
if [[ $VERSION =~ ^5\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
TAGS="$TAGS,${DOCKER_IMAGE}:latest"
fi
echo ::set-output name=tags::${TAGS}
echo ::set-output name=version::${VERSION}
echo ::set-output name=major::${MAJOR}
- name: Push alpine-based image - v5
run: make push-alpine-v5 TAG="${{steps.vars.outputs.tag}}"
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
with:
platforms: all
- name: Build image from alpine - v4
run: make build-alpine TAG="${{steps.vars.outputs.tag}}"
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
- name: Push alpine-based image - v4
run: make push-alpine TAG="${{steps.vars.outputs.tag}}"
# - name: Cache Docker layers
# uses: actions/cache@v2
# with:
# path: /tmp/.buildx-cache
# key: ${{ runner.os }}-buildx-${{ github.sha }}
# restore-keys: |
# ${{ runner.os }}-buildx-
- name: Logout from DockerHub
run: docker logout
- name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
builder: ${{ steps.buildx.outputs.name }}
context: ./alpine/${{ steps.prep.outputs.major }}/
build-args: INVOICENINJA_VERSION=${{ steps.prep.outputs.version }}
target: prod
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.prep.outputs.tags }}
cache-from: invoiceninja/invoiceninja:${{ steps.prep.outputs.major }}
cache-to: type=inline
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}

98
.github/workflows/charts.yaml vendored Normal file
View File

@@ -0,0 +1,98 @@
name: Lint and Test Charts
on:
pull_request:
paths:
- "charts/**"
jobs:
lint-chart:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Fetch history
run: git fetch --prune --unshallow
- name: Set up Helm
uses: azure/setup-helm@v1
- uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Set up chart-testing
uses: helm/chart-testing-action@v2.0.1
- name: Run chart-testing (list-changed)
id: list-changed
run: |
echo "::set-output name=changed::[\"$(ct list-changed --config .github/ct-lint.yaml)\"]"
- name: Parse list-changed
id: set-matrix
env:
CHANGED: ${{ steps.list-changed.outputs.changed }}
run: |
echo "::set-output name=matrix::$(echo "${CHANGED//\\n/\",\"}")"
- name: Run chart-testing (lint)
run: ct lint --config .github/ct-lint.yaml
kubeval-chart:
runs-on: ubuntu-latest
needs:
- lint-chart
strategy:
matrix:
chart: ${{ fromJson(needs.lint-chart.outputs.matrix) }}
k8s:
- v1.17.11
- v1.18.8
- v1.19.4
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Update Helm depdendencies
env:
CHART_DIR: ${{ matrix.chart }}
run: |
helm dependency update "${CHART_DIR}"
mkdir kubeval
helm template "${CHART_DIR}" > kubeval/combined.yaml
- name: Run kubeval
uses: instrumenta/kubeval-action@master
with:
files: kubeval
version: ${{ matrix.k8s }}
install-chart:
name: install-chart
runs-on: ubuntu-latest
needs:
- lint-chart
- kubeval-chart
strategy:
matrix:
k8s:
- v1.17.11
- v1.18.8
- v1.19.4
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Create kind ${{ matrix.k8s }} cluster
uses: helm/kind-action@v1.1.0
with:
node_image: kindest/node:${{ matrix.k8s }}
- name: Run chart-testing (install)
uses: helm/chart-testing-action@v2.0.1
with:
command: install
config: .github/ct-install.yaml

32
.github/workflows/release.yaml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: Release Charts
on:
push:
branches:
- master
paths:
- "charts/**"
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Configure Git
run: |
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- uses: azure/setup-helm@v1
id: install
- name: Add Helm repos
run: |
helm repo add bitnami https://charts.bitnami.com/bitnami
- name: Run chart-releaser
uses: helm/chart-releaser-action@v1.2.1
env:
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"

14
.gitignore vendored Normal file
View File

@@ -0,0 +1,14 @@
# OS files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Helm
charts/**/charts/
# Compose filesystem
/docker

View File

@@ -17,15 +17,15 @@ VERSION=$(shell echo ${TAG} | sed "s/-.*//")
# Building docker images based on alpine.
# Assigned tags:
# - :alpine
# - :alpine-<RELEASE VERSION>
# - :4
# - :<RELEASE VERSION>
.PHONY: build-alpine
build-alpine:
ifeq ($(IS_V5),)
$(info Make: Building "$(VERSION)" tagged images from alpine.)
@docker build -t ${HUB_NAMESPACE}/${IMAGE}:alpine-${VERSION} --build-arg INVOICENINJA_VERSION=${VERSION} --file ./alpine/Dockerfile .
# Tag as alpine-4
@docker tag ${HUB_NAMESPACE}/${IMAGE}:alpine-${VERSION} ${HUB_NAMESPACE}/${IMAGE}:alpine-4
@docker build -t ${HUB_NAMESPACE}/${IMAGE}:${VERSION} --build-arg INVOICENINJA_VERSION=${VERSION} ./alpine/4/
# Tag as 4
@docker tag ${HUB_NAMESPACE}/${IMAGE}:alpine-${VERSION} ${HUB_NAMESPACE}/${IMAGE}:4
$(info Make: Done.)
endif
@@ -33,8 +33,8 @@ endif
push-alpine:
ifeq ($(IS_V5),)
$(info Make: Pushing tagged images from alpine.)
@docker push ${HUB_NAMESPACE}/${IMAGE}:alpine-${VERSION}
@docker push ${HUB_NAMESPACE}/${IMAGE}:alpine-4
@docker push ${HUB_NAMESPACE}/${IMAGE}:${VERSION}
@docker push ${HUB_NAMESPACE}/${IMAGE}:4
$(info Make: Done.)
endif
@@ -42,7 +42,7 @@ endif
build-alpine-v5:
ifneq ($(IS_V5),)
$(info Make: Building "$(VERSION)" tagged images from alpine.)
@docker build -t ${HUB_NAMESPACE}/${IMAGE}:${VERSION} --build-arg INVOICENINJA_VERSION=${VERSION} --file ./alpine/Dockerfile_v5 .
@docker build -t ${HUB_NAMESPACE}/${IMAGE}:${VERSION} --build-arg INVOICENINJA_VERSION=${VERSION} ./alpine/5/
@docker tag ${HUB_NAMESPACE}/${IMAGE}:${VERSION} ${HUB_NAMESPACE}/${IMAGE}:5
@docker tag ${HUB_NAMESPACE}/${IMAGE}:${VERSION} ${HUB_NAMESPACE}/${IMAGE}:latest
$(info Make: Done.)

View File

@@ -1,52 +1,65 @@
![Docker images](https://github.com/invoiceninja/dockerfiles/workflows/Docker%20images/badge.svg)
[![Docker image, latest](https://img.shields.io/docker/image-size/invoiceninja/invoiceninja/latest?label=latest)](https://hub.docker.com/r/invoiceninja/invoiceninja)
[![Docker image, alpine](https://img.shields.io/docker/image-size/invoiceninja/invoiceninja/alpine?label=alpine)](https://hub.docker.com/r/invoiceninja/invoiceninja)
[![Artifact HUB](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/invoiceninja)](https://artifacthub.io/packages/search?repo=invoiceninja)
# Docker for [Invoice Ninja](https://www.invoiceninja.com/)
# Docker for [Invoice Ninja](https://www.invoiceninja.com/)
:crown: **Features**
:lock: Automatic HTTPS (:heart: [Caddy](https://caddyserver.com/))
:fire: NGINX webserver support [NGINX](https://nginx.org/)
:hammer: Fully production-ready through docker-compose
:hammer: Fully production-ready through Helm Chart
:pencil: Adjustable to your needs via environment variable
## Quickstart V5 Launch
## Get some Kubernetes + Helm with that!
The dockerfile has been revamped to make is easier to get started, by default the base image selected in 5 which will pull in the latest v5 stable image.
Introducing our very own [Helm Chart](https://github.com/invoiceninja/dockerfiles/tree/master/charts/invoiceninja) that helps you launch a simple standalone app to a production-ready, highly available Invoice Ninja setup. All you need to do is initialise Kubernetes (available with Docker Desktop), install [Helm](https://helm.sh/docs/intro/install/), and spin up Invoice Ninja using the steps provided [here](https://github.com/invoiceninja/dockerfiles/tree/master/charts/invoiceninja#installing-the-chart).
```
Other resources:
[Helm Chart](https://github.com/Saddamus/invoiceninja-helm) by @Saddamus
[K8s Manifest](https://github.com/invoiceninja/dockerfiles/issues/94) by @spacepluk
## Alternatively get started with Docker Compose
The dockerfile has been revamped to make it easier to get started, by default the base image selected is 5 which will pull in the latest v5 stable image.
```bash
git clone https://github.com/invoiceninja/dockerfiles.git
cd dockerfiles
```
Instead of defining our environment variables inside our docker-compose.yml file we now define this in the ```env``` file, open this file up and insert your APP_URL and your APP_KEY
Instead of defining our environment variables inside our docker-compose.yml file we now define this in the `env` file, open this file up and insert your `APP_URL`, `APP_KEY` and update the rest of the variables as required.
```
APP_URL=http://in.localhost:8003/
APP_KEY=<insert your generated key in here>
APP_DEBUG=true
MULTI_DB_ENABLED=false
DB_HOST1=db
DB_USERNAME1=ninja
DB_PASSWORD1=ninja
DB_DATABASE1=ninja
PHANTOMJS_PDF_GENERATION=false
REQUIRE_HTTPS=false
IN_USER_EMAIL=
IN_PASSWORD=
```
The ```APP_KEY``` can be generated by running
If `IN_USER_EMAIL` and `IN_PASSWORD` is not set the default user email and password is "admin@example.com" and "changeme!" respectively. You will use this for the initial login, thereafter, you can delete this two environment variables.
```
The `APP_KEY` can be generated by running
```bash
docker run --rm -it invoiceninja/invoiceninja php artisan key:generate --show
```
Copy the entire string and insert in the env file at ```APP_KEY=base64....```
Copy the entire string and insert in the env file at `APP_KEY=base64....`
To ensure folder permissions are correct when the container comes up for the first time it is important that you set the correct folder permissions on the ```docker``` folder.
To ensure folder permissions are correct when the container comes up for the first time it is important that you set the correct folder permissions on the `docker` folder.
From the terminal run
```sudo chown -R 1500:1500 docker/app```
```bash
chmod 755 docker/app/public
sudo chown -R 1500:1500 docker/app
```
### Note for people running the container locally on their PC ###
@@ -57,7 +70,7 @@ For example, lets say your APP_URL is ```http://in5.test:8000``` and your LAN IP
```192.168.0.124 in5.test```
**Please note that PDF generation using local host your domain name MUST end in .test for your PDFs to generate correctly, this is a DNS resolver issue with chromium.
**Please note that for PDF generation using local host, your domain name MUST end in .test for your PDFs to generate correctly, this is a DNS resolver issue with chromium.
All that is left to do now is bring up the container
@@ -67,9 +80,22 @@ All that is left to do now is bring up the container
**Note: When performing the setup, the Database host is ```db```
### Running on ARM64 (Raspberry Pi 4)
When deploying on an ARM64 system, you need to comment out the `image: mysql:5` line and uncomment `image: mariadb:10.4` in the `docker-compose.yml` file.
### Updating the Image when using `docker-compose`
As `docker-compose` does not support any form of version control, this git provide updates to `docker-compose.yml` directly.
To upgrade to a newer release image, please make sure to update the `docker-compose.yml` first by running
```bash
git pull
```
You may need to manually merge any changes that cannot be merged automatically by git.
## Support
If you discover a bug, please create and issue, if you query is general in nature please visit us on our [Forum ](https://forum.invoiceninja.com/)

73
alpine/4/Dockerfile Normal file
View File

@@ -0,0 +1,73 @@
ARG PHP_VERSION=7.2
ARG BAK_STORAGE_PATH=/var/www/app/docker-backup-storage/
ARG BAK_PUBLIC_PATH=/var/www/app/docker-backup-public/
FROM php:${PHP_VERSION}-fpm-alpine as prod
LABEL maintainer="David Bomba <turbo124@gmail.com>"
#####
# SYSTEM REQUIREMENT
#####
ARG INVOICENINJA_VERSION
ARG BAK_STORAGE_PATH
ARG BAK_PUBLIC_PATH
RUN mv /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini
# Install PHP extensions
# https://hub.docker.com/r/mlocati/php-extension-installer/tags
COPY --from=mlocati/php-extension-installer:1.1.41 /usr/bin/install-php-extensions /usr/local/bin/
RUN install-php-extensions \
gd \
gmp \
opcache \
pdo_mysql \
zip
# Separate user
ENV INVOICENINJA_USER=invoiceninja
WORKDIR /var/www/app
RUN addgroup --gid=1500 -S "$INVOICENINJA_USER" \
&& adduser --uid=1500 \
--disabled-password \
--gecos "" \
--home "$(pwd)" \
--ingroup "$INVOICENINJA_USER" \
--no-create-home \
"$INVOICENINJA_USER" \
&& chown -R "$INVOICENINJA_USER":"$INVOICENINJA_USER" .
COPY rootfs /
RUN chmod +x /usr/local/bin/docker-entrypoint
USER 1500
# Download and install IN
ENV INVOICENINJA_VERSION="${INVOICENINJA_VERSION}"
ENV BAK_STORAGE_PATH $BAK_STORAGE_PATH
ENV BAK_PUBLIC_PATH $BAK_PUBLIC_PATH
RUN curl -o /tmp/ninja.zip -L https://download.invoiceninja.com/ninja-v${INVOICENINJA_VERSION}.zip \
&& unzip -q /tmp/ninja.zip -d /tmp/ \
&& mv /tmp/ninja/* /var/www/app \
&& rm -rf /tmp/ninja* \
&& mv /var/www/app/storage $BAK_STORAGE_PATH \
&& mv /var/www/app/public $BAK_PUBLIC_PATH \
&& mkdir -p /var/www/app/public/logo /var/www/app/storage \
&& chmod -R 755 /var/www/app/storage \
&& rm -rf /var/www/app/docs /var/www/app/tests
# Override the environment settings from projects .env file
ENV IS_DOCKER true
ENV LOG errorlog
ENV SELF_UPDATER_SOURCE ''
# Use to be mounted into nginx
VOLUME /var/www/app/public
ENTRYPOINT ["docker-entrypoint"]
CMD ["php-fpm"]

View File

@@ -0,0 +1,17 @@
; How often (in seconds) to check file timestamps for changes to the shared
; memory storage allocation. ("1" means validate once per second, but only
; once per request. "0" means always validate)
;opcache.revalidate_freq=2
opcache.revalidate_freq=60
# http://symfony.com/doc/current/performance.html
; Duration of time, in seconds for which to cache realpath information for a given
; file or directory. For systems with rarely changing files, consider increasing this
; value.
; http://php.net/realpath-cache-ttl
;realpath_cache_ttl = 120
realpath_cache_ttl = 600
; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
upload_max_filesize = 8M

View File

@@ -82,8 +82,8 @@ elif [ -d "$BAK_PUBLIC_PATH/logo" ]; then
fi
rm -rf "$BAK_PUBLIC_PATH"
# Set permission for web server to create/update files
chown -R "$INVOICENINJA_USER":www-data /var/www/app/storage /var/www/app/public /var/www/app/bootstrap
# Set permission for web server to create/update files (only <v4)
chown -R "$INVOICENINJA_USER":"$INVOICENINJA_USER" /var/www/app/storage /var/www/app/public /var/www/app/bootstrap
# Initialize values that might be stored in a file
file_env 'APP_KEY'
@@ -102,8 +102,9 @@ file_env 'S3_KEY'
file_env 'S3_SECRET'
# Run Laravel stuff
php artisan config:cache
php artisan optimize
php artisan migrate --force
if [[ "$1" == "supervisord" ]] || [[ "$1" == "php-fpm" ]]; then
echo "Initialising Laravel..."
. laravel-init.sh
fi
exec docker-php-entrypoint "$@"

View File

@@ -0,0 +1,5 @@
#!/bin/sh
php artisan config:cache
php artisan optimize
php artisan migrate --force

View File

@@ -3,19 +3,16 @@ ARG BAK_STORAGE_PATH=/var/www/app/docker-backup-storage/
ARG BAK_PUBLIC_PATH=/var/www/app/docker-backup-public/
# Get Invoice Ninja and install nodejs packages
FROM node:lts-alpine as frontend
FROM --platform=$BUILDPLATFORM node:lts-alpine as build
ARG INVOICENINJA_VERSION
ARG BAK_STORAGE_PATH
ARG BAK_PUBLIC_PATH
# Install dependencies
RUN set -eux; \
apk add --no-cache \
curl
# Download Invoice Ninja
RUN curl -o /tmp/ninja.tar.gz -LJ0 https://github.com/invoiceninja/invoiceninja/tarball/v$INVOICENINJA_VERSION \
&& mkdir -p /var/www/app \
ADD https://github.com/invoiceninja/invoiceninja/tarball/v$INVOICENINJA_VERSION /tmp/ninja.tar.gz
# Extract Invoice Ninja
RUN mkdir -p /var/www/app \
&& tar --strip-components=1 -xf /tmp/ninja.tar.gz -C /var/www/app/ \
&& mkdir -p /var/www/app/public/logo /var/www/app/storage \
&& mv /var/www/app/.env.example /var/www/app/.env \
@@ -28,75 +25,69 @@ RUN npm install --production \
&& npm run production \
&& rm -rf node_modules \
&& mv /var/www/app/storage $BAK_STORAGE_PATH \
&& mv /var/www/app/public $BAK_PUBLIC_PATH
&& mv /var/www/app/public $BAK_PUBLIC_PATH
# Prepare php image
FROM php:${PHP_VERSION}-fpm-alpine
FROM php:${PHP_VERSION}-fpm-alpine3.13 as prod
ARG INVOICENINJA_VERSION
ARG BAK_STORAGE_PATH
ARG BAK_PUBLIC_PATH
ENV INVOICENINJA_VERSION $INVOICENINJA_VERSION
ENV BAK_STORAGE_PATH $BAK_STORAGE_PATH
ENV BAK_PUBLIC_PATH $BAK_PUBLIC_PATH
LABEL maintainer="David Bomba <turbo124@gmail.com>"
WORKDIR /var/www/app
RUN mv /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini
COPY --from=frontend /var/www/app /var/www/app
COPY entrypoint.sh /usr/local/bin/docker-entrypoint
RUN chmod +x /usr/local/bin/docker-entrypoint
# Install PHP extensions
# https://hub.docker.com/r/mlocati/php-extension-installer/tags
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
RUN install-php-extensions \
bcmath \
exif \
gd \
gmp \
mysqli \
opcache \
pdo_mysql \
zip \
@composer \
&& rm /usr/local/bin/install-php-extensions
# Install chromium
RUN set -eux; \
apk add --no-cache \
supervisor \
mysql-client \
freetype-dev \
gmp-dev \
libjpeg-turbo-dev \
libpng-dev \
libzip-dev \
# oniguruma-dev \
git \
# busybox-suid \
zip \
chromium \
harfbuzz \
ttf-freefont \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) \
bcmath \
exif \
gd \
gmp \
mysqli \
opcache \
pdo_mysql \
zip
ttf-freefont
COPY ./config/php/php.ini /usr/local/etc/php/php.ini
COPY ./config/php/php-cli.ini /usr/local/etc/php/php-cli.ini
# Copy files
COPY rootfs /
## Separate user
## Create user
ARG UID=1500
ENV INVOICENINJA_USER=invoiceninja
ENV INVOICENINJA_USER invoiceninja
RUN addgroup --gid=$UID -S "$INVOICENINJA_USER" \
&& adduser --uid=$UID \
--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
--home "/var/www/app" \
--ingroup "$INVOICENINJA_USER" \
"$INVOICENINJA_USER"
# Install Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer;
# Set up app
ENV INVOICENINJA_VERSION $INVOICENINJA_VERSION
ENV BAK_STORAGE_PATH $BAK_STORAGE_PATH
ENV BAK_PUBLIC_PATH $BAK_PUBLIC_PATH
COPY --from=build --chown=$INVOICENINJA_USER:$INVOICENINJA_USER /var/www/app /var/www/app
USER $UID
WORKDIR /var/www/app
# Do not remove this ENV
ENV IS_DOCKER true
RUN /usr/local/bin/composer install --no-dev --quiet
# Override the environment settings from projects .env file
@@ -105,4 +96,4 @@ ENV LOG errorlog
ENV SNAPPDF_EXECUTABLE_PATH /usr/bin/chromium-browser
ENTRYPOINT ["docker-entrypoint"]
CMD ["php-fpm"]
CMD ["supervisord"]

View File

@@ -0,0 +1,14 @@
#!/bin/sh
php artisan db:seed --force
# Build up array of arguments...
if [[ ! -z "${IN_USER_EMAIL}" ]]; then
email="--email ${IN_USER_EMAIL}"
fi
if [[ ! -z "${IN_PASSWORD}" ]]; then
password="--password ${IN_PASSWORD}"
fi
php artisan ninja:create-account $email $password

View File

@@ -0,0 +1,42 @@
[supervisord]
nodaemon=true
pidfile=/tmp/supervisord.pid
logfile=/dev/null ; nodaemon will cause logs to go to stdout
logfile_maxbytes=0
loglevel=info
[program:php-fpm]
redirect_stderr=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
command=php-fpm
[program:scheduler]
autorestart=true
redirect_stderr=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
command=php artisan schedule:work
[program:queue-worker]
process_name=%(program_name)s_%(process_num)02d
autorestart=true
redirect_stderr=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
numprocs=2
command=php artisan queue:work --sleep=3 --tries=1 --memory=256 --timeout=3600
[eventlistener:shutdown]
command=shutdown.sh
events=PROCESS_STATE_STOPPED, PROCESS_STATE_EXITED, PROCESS_STATE_FATAL
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

View File

@@ -0,0 +1,118 @@
#!/usr/bin/env sh
set -e
# logging functions
in_log() {
local type="$1"
shift
printf '%s [%s] [Entrypoint]: %s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" "$type" "$*"
}
in_error() {
in_log ERROR "$@" >&2
exit 1
}
# Indirect expansion (ie) is not supported in bourne shell. That's why we are using this "magic" here.
ie_gv() {
eval "echo \$$1"
}
# usage: file_env VAR [DEFAULT]
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
file_env() {
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "$(ie_gv ${var})" != "" ]; then
if [ "$(ie_gv ${fileVar})" != "" ]; then
in_error "Both $var and $fileVar are set (but are exclusive)"
fi
unset "$fileVar"
return
fi
if [ "$(ie_gv ${fileVar})" != "" ] && [ -f "$(ie_gv ${fileVar})" ]; then
export "$var"="$(cat $(ie_gv ${fileVar}))"
elif [ ! -z "$def" ]; then
export "$var"="$def"
fi
unset "$fileVar"
}
# first arg is `-f` or `--some-option`
if [ "${1#-}" != "$1" ]; then
set -- supervisord "$@"
fi
# create storage volume
if [ -d "$BAK_STORAGE_PATH" ]; then
if [ ! -d /var/www/app/storage ]; then
mv "$BAK_STORAGE_PATH" /var/www/app/storage
else
# copy missing folders in storage
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
rm -rf "$BAK_STORAGE_PATH"
fi
# prevent init scripts from running when upgrading from IN <= 5.1.62
if [ -f /var/www/app/public/version ] && [ "$INVOICENINJA_VERSION" != "$(cat /var/www/app/public/version)" ]; then
touch /var/www/app/storage/.initialized
fi
# create public volume
if [ -d "$BAK_PUBLIC_PATH" ]; then
if [ ! -d /var/www/app/public ]; then
mv "$BAK_PUBLIC_PATH" /var/www/app/public
elif [ ! -f /var/www/app/public/version ] || [ "$INVOICENINJA_VERSION" != "$(cat /var/www/app/public/version)" ]; then
# version mismatch, update all
cp -au "$BAK_PUBLIC_PATH/"* /var/www/app/public
echo "$INVOICENINJA_VERSION" >/var/www/app/public/version
elif [ ! -d /var/www/app/public/logo ] && [ -d "$BAK_PUBLIC_PATH/logo" ]; then
# missing logo folder only, copy folder
cp -a "$BAK_PUBLIC_PATH/logo" /var/www/app/public/logo
elif [ -d "$BAK_PUBLIC_PATH/logo" ]; then
# copy missing folders in logo
IN_LOGO_BACKUP="$(ls "$BAK_PUBLIC_PATH/logo")"
for path in $IN_LOGO_BACKUP; do
if [ ! -e "/var/www/app/public/logo/$path" ]; then
cp -a "$BAK_PUBLIC_PATH/logo/$path" "/var/www/app/public/logo/"
fi
done
fi
rm -rf "$BAK_PUBLIC_PATH"
fi
# Initialize values that might be stored in a file
file_env 'APP_KEY'
file_env 'API_SECRET'
file_env 'CLOUDFLARE_API_KEY'
file_env 'DB_USERNAME'
file_env 'DB_USERNAME1'
file_env 'DB_USERNAME2'
file_env 'DB_PASSWORD'
file_env 'DB_PASSWORD1'
file_env 'DB_PASSWORD2'
file_env 'MAIL_USERNAME'
file_env 'MAIL_PASSWORD'
file_env 'MAILGUN_SECRET'
file_env 'S3_KEY'
file_env 'S3_SECRET'
# Run IN/Laravel stuff
if [[ "$1" == "supervisord" ]] || [[ "$1" == "php-fpm" ]]; then
in_log INFO "Initialising Invoice Ninja..."
. invoiceninja-init.sh
fi
exec docker-php-entrypoint "$@"

View File

@@ -0,0 +1,44 @@
#!/bin/sh
# usage: docker_process_init_files [file [file [...]]]
# ie: docker_process_init_files /always-initdb.d/*
# process initializer files, based on file extensions
docker_process_init_files() {
echo
local f
for f; do
case "$f" in
*.sh)
# https://github.com/docker-library/postgres/issues/450#issuecomment-393167936
# https://github.com/docker-library/postgres/pull/452
if [ -x "$f" ]; then
in_log INFO "$0: running $f"
"$f"
else
in_log INFO "$0: sourcing $f"
. "$f"
fi
;;
*) in_log INFO "$0: ignoring $f" ;;
esac
echo
done
}
php artisan config:cache
php artisan optimize
# Check if DB works, if not crash the app.
DB_READY=$(php artisan tinker --execute='echo app()->call("App\Utils\SystemHealth@dbCheck")["success"];')
if [ "$DB_READY" != "1" ]; then
php artisan migrate:status # Print verbose error
in_error "Error connecting to DB"
fi
php artisan migrate --force
# If first IN run, it needs to be initialized
if [ ! -f /var/www/app/storage/.initialized ]; then
docker_process_init_files /docker-entrypoint-init.d/*
touch /var/www/app/storage/.initialized
fi

View File

@@ -0,0 +1,8 @@
#!/bin/sh
printf "READY\n"
while read line; do
echo "Processing Event: $line" >&2
kill -SIGQUIT $PPID
done </dev/stdin

View File

@@ -0,0 +1,17 @@
; How often (in seconds) to check file timestamps for changes to the shared
; memory storage allocation. ("1" means validate once per second, but only
; once per request. "0" means always validate)
;opcache.revalidate_freq=2
opcache.revalidate_freq=60
# http://symfony.com/doc/current/performance.html
; Duration of time, in seconds for which to cache realpath information for a given
; file or directory. For systems with rarely changing files, consider increasing this
; value.
; http://php.net/realpath-cache-ttl
;realpath_cache_ttl = 120
realpath_cache_ttl = 600
; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
upload_max_filesize = 8M

View File

@@ -1,83 +0,0 @@
ARG PHP_VERSION=7.2
ARG BAK_STORAGE_PATH=/var/www/app/docker-backup-storage/
ARG BAK_PUBLIC_PATH=/var/www/app/docker-backup-public/
FROM php:${PHP_VERSION}-fpm-alpine
LABEL maintainer="David Bomba <turbo124@gmail.com>"
#####
# SYSTEM REQUIREMENT
#####
ARG INVOICENINJA_VERSION
ARG BAK_STORAGE_PATH
ARG BAK_PUBLIC_PATH
ENV BAK_STORAGE_PATH $BAK_STORAGE_PATH
ENV BAK_PUBLIC_PATH $BAK_PUBLIC_PATH
WORKDIR /var/www/app
COPY entrypoint.sh /usr/local/bin/docker-entrypoint
RUN chmod +x /usr/local/bin/docker-entrypoint
RUN set -eux; \
apk add --no-cache \
gmp-dev \
freetype-dev \
libarchive-tools \
libjpeg-turbo-dev \
libpng-dev \
libwebp-dev\
libzip-dev
RUN docker-php-ext-configure gd --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include --with-webp-dir=/usr/include --with-freetype-dir=/usr/include/; \
docker-php-ext-configure zip --with-libzip; \
docker-php-ext-install -j$(nproc) \
iconv \
gd \
gmp \
mbstring \
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 --gid=1500 -S "$INVOICENINJA_USER" && \
adduser --uid=1500 \
--disabled-password \
--gecos "" \
--home "$(pwd)" \
--ingroup "$INVOICENINJA_USER" \
--no-create-home \
"$INVOICENINJA_USER"; \
addgroup "$INVOICENINJA_USER" www-data; \
chown -R "$INVOICENINJA_USER":"$INVOICENINJA_USER" .
USER $INVOICENINJA_USER
# Download and install IN
ENV INVOICENINJA_VERSION="${INVOICENINJA_VERSION}"
RUN curl -s -o /tmp/ninja.zip -SL https://download.invoiceninja.com/ninja-v${INVOICENINJA_VERSION}.zip \
&& bsdtar --strip-components=1 -C /var/www/app -xf /tmp/ninja.zip \
&& rm /tmp/ninja.zip \
&& mv /var/www/app/storage $BAK_STORAGE_PATH \
&& mv /var/www/app/public $BAK_PUBLIC_PATH \
&& mkdir -p /var/www/app/public/logo /var/www/app/storage \
&& chmod -R 755 /var/www/app/storage \
&& rm -rf /var/www/app/docs /var/www/app/tests
# Override the environment settings from projects .env file
ENV LOG errorlog
ENV SELF_UPDATER_SOURCE ''
# Use to be mounted into nginx
VOLUME /var/www/app/public
ENTRYPOINT ["docker-entrypoint"]
CMD ["php-fpm"]

View File

@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

View File

@@ -0,0 +1,15 @@
dependencies:
- name: common
repository: https://charts.bitnami.com/bitnami
version: 1.4.3
- name: nginx
repository: https://charts.bitnami.com/bitnami
version: 8.8.5
- name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 9.3.11
- name: redis
repository: https://charts.bitnami.com/bitnami
version: 12.9.2
digest: sha256:4255a558312b033e820635f491b0960bd4ec8e716164025212af06adafbd4cb9
generated: "2021-05-11T09:31:45.433+08:00"

View File

@@ -0,0 +1,46 @@
apiVersion: v2
name: invoiceninja
description: A Helm chart to install Invoice Ninja
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.5.1
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
appVersion: 5.1.64
keywords:
- invoiceninja
home: https://invoiceninja.github.io/dockerfiles
sources:
- https://github.com/invoiceninja/invoiceninja
- https://github.com/invoiceninja/dockerfiles
dependencies:
- name: common
repository: https://charts.bitnami.com/bitnami
tags:
- bitnami-common
version: 1.x.x
- name: nginx
repository: https://charts.bitnami.com/bitnami
version: 8.8.x
- condition: mariadb.enabled
name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 9.3.x
- condition: redis.enabled
name: redis
repository: https://charts.bitnami.com/bitnami
version: 12.9.x
maintainers:
- email: lwj5@hotmail.com
name: lwj5

View File

@@ -0,0 +1,289 @@
# Invoice Ninja Helm Chart
This helm chart installs Invoice Ninja (IN) and its dependencies into a running
Kubernetes cluster.
The chart installs the [Invoice Ninja](https://hub.docker.com/r/invoiceninja/invoiceninja) docker image.
Please read [Upgrading](#upgrading) section before upgrading MAJOR versions.
## Dependencies
- The Bitnami [common](https://github.com/bitnami/charts/tree/master/bitnami/common) helm chart
- The Bitnami [mariadb](https://github.com/bitnami/charts/tree/master/bitnami/mariadb) helm chart
- The Bitnami [nginx](https://github.com/bitnami/charts/tree/master/bitnami/nginx) helm chart
- The Bitnami [redis](https://github.com/bitnami/charts/tree/master/bitnami/redis) helm chart
- Tested on Kubernetes 1.17+
## Installing the Chart
To install the chart with the release name `invoiceninja`:
```bash
helm repo add invoiceninja https://invoiceninja.github.io/dockerfiles
helm install invoiceninja invoiceninja/invoiceninja
```
The command deploys Invoice Ninja on the Kubernetes cluster in the default namespace. The [Parameters](#parameters) section lists the parameters that can be configured during installation.
> **Tip**: List all releases using `helm list`
## Uninstalling the Chart
To uninstall/delete the `invoiceninja` deployment:
```bash
helm delete invoiceninja
```
The command removes all the Kubernetes components associated with the chart and deletes the release.
## Parameters
The following table lists the configurable parameters of the Invoice Ninja chart and their default values.
> NOTE: You MUST set any values that default to random or risk losing access after an upgrade. See how [here](#installing-with-arguments)
### Global Configuration
The following table shows the configuration options for the Invoice Ninja helm chart:
### Global parameters
| Parameter | Description | Default |
| ------------------------- | ----------------------------------------------- | ------------------------------------------------------- |
| `global.imageRegistry` | Global Docker image registry | `nil` |
| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) |
| `global.storageClass` | Global storage class for dynamic provisioning | `nil` |
### Common parameters
| Parameter | Description | Default |
| ------------------- | -------------------------------------------------------------------- | ------------------------------ |
| `nameOverride` | String to partially override common.names.fullname | `nil` |
| `fullnameOverride` | String to fully override common.names.fullname | `nil` |
| `clusterDomain` | Default Kubernetes cluster domain | `cluster.local` |
| `commonLabels` | Labels to add to all deployed objects | `{}` |
| `commonAnnotations` | Annotations to add to all deployed objects | `{}` |
| `kubeVersion` | Force target Kubernetes version (using Helm capabilities if not set) | `nil` |
| `extraDeploy` | Array of extra objects to deploy with the release | `[]` (evaluated as a template) |
### Invoice Ninja parameters
| Parameter | Description | Default |
| -------------------- | ---------------------------------------------------------------- | ------------------------------------------------------- |
| `image.registry` | Invoice Ninja image registry | `docker.io` |
| `image.repository` | Invoice Ninja image name | `invoiceninja/invoiceninja` |
| `image.tag` | Invoice Ninja image tag | Check `values.yaml` file |
| `image.pullPolicy` | Invoice Ninja image pull policy | `IfNotPresent` |
| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) |
| `image.debug` | Specify if debug logs should be enabled | `false` |
| `serviceAccountName` | Name of a service account for the Invoice Ninja pods | `default` |
| `debug` | Turn on debug mode on Invoice Ninja | `false` |
| `appKey` | Laravel Application Key | _random 32 character alphanumeric string_ |
| `userEmail` | Initial user email address | `admin@example.com` |
| `userPassword` | Initial user password | `changeme!` |
| `logChannel` | Name of log channel to use | `nil` |
| `broadcastDriver` | Name of broadcast driver to use | `nil` |
| `cacheDriver` | Name of cache driver to use | `nil` |
| `sessionDriver` | Name of session driver to use | `nil` |
| `queueConnection` | Name of queue connection to use | `nil` |
| `snappdf` | Use snappdf instead of Phantom JS PDF generation | `true` |
| `mailer` | Name of the mailer to use (log, smtp, etc.) | `log` |
| `requireHttps` | Force HTTPS for internal connections to Invoice Ninja (see #349) | `false` |
| `extraEnvVars` | Extra environment variables to be set on Invoice Ninja container | `{}` |
| `extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars | `nil` |
| `extraEnvVarsSecret` | Name of existing Secret containing extra env vars | `nil` |
| `trustedProxy` | List of trusted proxies for Invoice Ninja to communicate with the nginx proxy | `'*'` |
### Invoice Ninja deployment parameters
| Parameter | Description | Default |
| --------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------ |
| `replicaCount` | Number of Invoice Ninja Pods to run | `1` |
| `containerPorts.fastcgi` | FastCGI port to expose at container level | `9000` |
| `podSecurityContext` | Invoice Ninja pods' Security Context | Check `values.yaml` file |
| `containerSecurityContext` | Invoice Ninja containers' Security Context | Check `values.yaml` file |
| `resources` | The resources for the Invoice Ninja container | `{}` |
| `livenessProbe` | Liveness probe configuration for Invoice Ninja | Check `values.yaml` file |
| `readinessProbe` | Readiness probe configuration for Invoice Ninja | Check `values.yaml` file |
| `updateStrategy` | Set up update strategy | `RollingUpdate` |
| `podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` |
| `nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` |
| `nodeAffinityPreset.key` | Node label key to match. Ignored if `affinity` is set. | `""` |
| `nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set. | `[]` |
| `affinity` | Affinity for pod assignment | `{}` (evaluated as a template) |
| `nodeSelector` | Node labels for pod assignment | `{}` (evaluated as a template) |
| `tolerations` | Tolerations for pod assignment | `[]` (evaluated as a template) |
| `podLabels` | Extra labels for Invoice Ninja pods | `{}` |
| `podAnnotations` | Annotations for Invoice Ninja pods | `{}` |
| `extraVolumeMounts` | Additional volume mounts | `[]` |
| `extraVolumes` | Additional volumes | `[]` |
### Volume Permissions parameters
| Parameter | Description | Default |
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` | `false` |
| `volumePermissions.image.registry` | Init container volume-permissions image registry | `docker.io` |
| `volumePermissions.image.repository` | Init container volume-permissions image name | `bitnami/bitnami-shell` |
| `volumePermissions.image.tag` | Init container volume-permissions image tag | `"10"` |
| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `Always` |
| `volumePermissions.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) |
| `volumePermissions.resources` | Init container volume-permissions resource | `{}` |
### Exposure parameters
| Parameter | Description | Default |
| ---------------------------------- | -------------------------------------------------------------------------- | ------------------------------ |
| `service.type` | Kubernetes Service type | `ClusterIP` |
| `service.port` | Service FastCGI port | `9000` |
| `service.nodePort` | Kubernetes FastCGI node port | `""` |
| `service.clusterIP` | Invoice Ninja service clusterIP IP | `None` |
| `service.loadBalancerSourceRanges` | Restricts access for LoadBalancer (only with `service.type: LoadBalancer`) | `[]` |
| `service.loadBalancerIP` | loadBalancerIP if service type is `LoadBalancer` | `nil` |
| `service.externalTrafficPolicy` | Enable client source IP preservation | `Cluster` |
| `service.annotations` | Service annotations | `{}` (evaluated as a template) |
### Ingress parameters
| Parameter | Description | Default |
| ------------------------------------------------------- | ------------------------------------- | ------------------------ |
| `nginx.service.type` | Kubernetes Service type | `ClusterIP` |
| `nginx.ingress.enabled` | Enable ingress controller resource | `true` |
| `nginx.ingress.hostname` | Default host for the ingress resource | `invoiceninja.local` |
| `nginx.serverBlock` | Custom NGINX server block | `nil` |
| `nginx.extraVolumes` | Array to add extra volumes | Check `values.yaml` file |
| `nginx.extraVolumes[0].persistentVolumeClaim.claimName` | Name of Invoice Ninja public PVC | `invoiceninja-public` |
| `nginx.extraVolumeMounts` | Array to add extra mount | Check `values.yaml` file |
> See [Dependencies](#dependencies) for more.
### Persistence parameters
| Parameter | Description | Default |
| ----------------------------------- | ---------------------------------------- | ----------------- |
| `persistence.public.enabled` | Enable persistence using PVC | `true` |
| `persistence.public.existingClaim` | Enable persistence using an existing PVC | `nil` |
| `persistence.public.storageClass` | PVC Storage Class | `nil` |
| `persistence.public.accessModes` | PVC Access Modes | `[ReadWriteMany]` |
| `persistence.public.size` | PVC Storage Request | `1Gi` |
| `persistence.public.dataSource` | PVC data source | `{}` |
| `persistence.storage.enabled` | Enable persistence using PVC | `true` |
| `persistence.storage.existingClaim` | Enable persistence using an existing PVC | `nil` |
| `persistence.storage.storageClass` | PVC Storage Class | `nil` |
| `persistence.storage.accessModes` | PVC Access Modes | `[ReadWriteMany]` |
| `persistence.storage.size` | PVC Storage Request | `5Gi` |
| `persistence.storage.dataSource` | PVC data source | `{}` |
### Redis parameters
| Parameter | Description | Default |
| --------------------------------- | -------------------------------------------- | ----------------------------------------- |
| `redis.enabled` | If external redis is used, set it to `false` | `true` |
| `redis.password` | Redis password | _random 10 character alphanumeric string_ |
| `redis.sentinel.enabled` | Enable sentinel containers | `true` |
| `redis.sentinel.usePassword` | Use password for sentinel containers | `false` |
| `externalRedis.host` | Host of the external redis | `nil` |
| `externalRedis.port` | Port of the external redis | `6379` |
| `externalRedis.password` | Password for the external redis | `nil` |
| `externalRedis.sentinel` | Using sentinels | `false` |
| `externalRedis.databases.default` | Database to use by default | `0` |
| `externalRedis.databases.cache` | Database to use by cache | `1` |
> See [Dependencies](#dependencies) for more.
### Database parameters
| Parameter | Description | Default |
| --------------------------------- | ------------------------------------------- | ----------------------------------------- |
| `mariadb.enabled` | Deploy MariaDB container(s) | `true` |
| `mariadb.auth.rootPassword` | Password for the MariaDB `root` user | _random 10 character alphanumeric string_ |
| `mariadb.auth.database` | Database name to create | `invoiceninja` |
| `mariadb.auth.username` | Database user to create | `invoiceninja` |
| `mariadb.auth.password` | Password for the database | _random 10 character alphanumeric string_ |
| `externalDatabase.host` | Host of the external database | `nil` |
| `externalDatabase.user` | Existing username in the external db | `invoiceninja` |
| `externalDatabase.password` | Password for the above username | `nil` |
| `externalDatabase.database` | Name of the existing database | `invoiceninja` |
| `externalDatabase.port` | Database port number | `3306` |
| `externalDatabase.existingSecret` | Name of the database existing Secret Object | `nil` |
> See [Dependencies](#dependencies) for more.
### Other parameters
| Parameter | Description | Default |
| -------------------------- | ---------------------------------------- | ------- |
| `autoscaling.enabled` | Enable autoscaling for Invoice Ninja | `false` |
| `autoscaling.minReplicas` | Minimum number of Invoice Ninja replicas | `1` |
| `autoscaling.maxReplicas` | Maximum number of Invoice Ninja replicas | `11` |
| `autoscaling.targetCPU` | Target CPU utilization percentage | `nil` |
| `autoscaling.targetMemory` | Target Memory utilization percentage | `nil` |
## Installing with Arguments
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
```bash
helm install invoiceninja \
--set appKey=changeit \
--set replicaCount=3 \
--set nginx.replicaCount=3 \
--set redis.cluster.slaveCount=3 \
--set redis.password=changeit \
--set mariadb.auth.rootPassword=changeit \
--set mariadb.auth.password=changeit \
invoiceninja/invoiceninja
```
The above command sets the number of replicas to 3 for a highly available (HA) setup. Note that you would need to use an external DB such as MariaDB Galera for a full HA production setup.
Alternatively, a YAML file that specifies the values for the parameters can be provided while [installing](https://helm.sh/docs/helm/helm_install/) the chart. For example,
```yaml
# values.yaml
appKey: changeit
replicaCount: 3
nginx:
replicaCount: 3
redis:
cluster:
slaveCount: 3
password: changeit
mariadb:
auth:
rootPassword: changeit
password: changeit
```
```bash
helm install invoiceninja -f values.yaml invoiceninja/invoiceninja
```
## Setting Environment Variables
Should you need to inject any environment variables such as those in [here](https://github.com/invoiceninja/dockerfiles/blob/master/env) into the `invoiceninja` container, you can use the `extraEnvVars` option:
```yaml
# ... values.yaml file
# In this example, we are setting the SMTP MAIL_HOST to be 'smtp.mailtrap.io'
extraEnvVars:
- name: MAIL_HOST
value: 'smtp.mailtrap.io' # all values must be strings, so other types must be surrounded in quotes
```
Alternatively you can provide the name of an existing `configmap` or `secret` object:
```bash
kubectl create configmap examplemap --from-literal=MAIL_HOST='smtp.mailtrap.io'
```
```yaml
# ... values.yaml file
extraEnvVarsCM: examplemap
```
## Upgrading
Nothing yet.

View File

@@ -0,0 +1,34 @@
** Please be patient while the chart is being deployed **
Your controller can be accessed through the following DNS name from within your cluster:
http://{{ include "invoiceninja.nginx.fullname" . }}.{{ .Release.Namespace }}.svc
To access your controller from outside the cluster follow the steps below:
{{- if or .Values.nginx.ingress.enabled }}
Externally through the following DNS name:
http://{{ .Values.nginx.ingress.hostname }}
-- OR --
{{ end }}
{{- if contains "NodePort" .Values.nginx.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "invoiceninja.nginx.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.nginx.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "invoiceninja.nginx.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "invoiceninja.nginx.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.nginx.service.type }}
export SVC_NAME=$(kubectl get svc --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name=nginx,app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
export SVC_PORT=$(kubectl get svc --namespace {{ .Release.Namespace }} $SVC_NAME -o jsonpath="{.spec.ports[0].port}")
echo "Add the line '127.0.0.1 {{ .Values.nginx.ingress.hostname }}' to your hosts file"
echo "Visit http://{{ .Values.nginx.ingress.hostname }} to use your application"
kubectl -n {{ .Release.Namespace }} port-forward svc/$SVC_NAME 80:$SVC_PORT
{{- end }}

View File

@@ -0,0 +1,250 @@
{{/*
Return the proper image name
*/}}
{{- define "invoiceninja.image" -}}
{{- include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) -}}
{{- end -}}
{{/*
Return the proper Docker Image Registry Secret Names
*/}}
{{- define "invoiceninja.imagePullSecrets" -}}
{{- include "common.images.pullSecrets" (dict "images" (list .Values.image .Values.volumePermissions.image) "global" .Values.global) -}}
{{- end -}}
{{/*
Return the proper image name (for the init container volume-permissions image)
*/}}
{{- define "invoiceninja.volumePermissions.image" -}}
{{ include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "invoiceninja.mariadb.fullname" -}}
{{- printf "%s-%s" .Release.Name "mariadb" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "invoiceninja.nginx.fullname" -}}
{{- printf "%s-%s" .Release.Name "nginx" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "invoiceninja.redis.fullname" -}}
{{- printf "%s-%s" .Release.Name "redis" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create the name of the service account to use
*/}}
{{- define "invoiceninja.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "common.names.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
{{- default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}
{{/*
Return the proper Storage Class
*/}}
{{- define "invoiceninja.public.storageClass" -}}
{{- include "common.storage.class" (dict "persistence" .Values.persistence.public "global" .Values.global) -}}
{{- end -}}
{{/*
Return the proper Storage Class
*/}}
{{- define "invoiceninja.storage.storageClass" -}}
{{- include "common.storage.class" (dict "persistence" .Values.persistence.storage "global" .Values.global) -}}
{{- end -}}
{{/*
Return the proper Storage Name
*/}}
{{- define "invoiceninja.public.storageName" -}}
{{- printf "%s-%s" .Release.Name "public" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Return the proper Storage Name
*/}}
{{- define "invoiceninja.storage.storageName" -}}
{{- printf "%s-%s" .Release.Name "storage" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Return the MariaDB Hostname
*/}}
{{- define "invoiceninja.databaseHost" -}}
{{- if .Values.mariadb.enabled }}
{{- if eq .Values.mariadb.architecture "replication" }}
{{- printf "%s-%s" (include "invoiceninja.mariadb.fullname" .) "primary" | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s" (include "invoiceninja.mariadb.fullname" .) -}}
{{- end -}}
{{- else -}}
{{- printf "%s" .Values.externalDatabase.host -}}
{{- end -}}
{{- end -}}
{{/*
Return the MariaDB Port
*/}}
{{- define "invoiceninja.databasePort" -}}
{{- if .Values.mariadb.enabled }}
{{- printf "3306" -}}
{{- else -}}
{{- printf "%d" (.Values.externalDatabase.port | int ) -}}
{{- end -}}
{{- end -}}
{{/*
Return the MariaDB Database Name
*/}}
{{- define "invoiceninja.databaseName" -}}
{{- if .Values.mariadb.enabled }}
{{- printf "%s" .Values.mariadb.auth.database -}}
{{- else -}}
{{- printf "%s" .Values.externalDatabase.database -}}
{{- end -}}
{{- end -}}
{{/*
Return the MariaDB User
*/}}
{{- define "invoiceninja.databaseUser" -}}
{{- if .Values.mariadb.enabled }}
{{- printf "%s" .Values.mariadb.auth.username -}}
{{- else -}}
{{- printf "%s" .Values.externalDatabase.user -}}
{{- end -}}
{{- end -}}
{{/*
Return the MariaDB Secret Name
*/}}
{{- define "invoiceninja.databaseSecretName" -}}
{{- if .Values.externalDatabase.existingSecret -}}
{{- printf "%s" .Values.externalDatabase.existingSecret -}}
{{- else -}}
{{- printf "%s" (include "invoiceninja.mariadb.fullname" .) -}}
{{- end -}}
{{- end -}}
{{/*
Return the Redis Hostname
*/}}
{{- define "invoiceninja.redisHost" -}}
{{- if .Values.redis.enabled }}
{{- if .Values.redis.sentinel.enabled }}
{{- printf "%s-%s" (include "invoiceninja.redis.fullname" .) "headless" | trunc 63 | trimSuffix "-" -}}
{{- else }}
{{- printf "%s-%s" (include "invoiceninja.redis.fullname" .) "master" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- else -}}
{{- printf "%s" .Values.externalRedis.host -}}
{{- end -}}
{{- end -}}
{{/*
Return the Redis Port
*/}}
{{- define "invoiceninja.redisPort" -}}
{{- if .Values.redis.enabled }}
{{- if .Values.redis.sentinel.enabled }}
{{- printf "26379" -}}
{{- else }}
{{- printf "6379" -}}
{{- end -}}
{{- else -}}
{{- printf "%d" (.Values.externalRedis.port | int ) -}}
{{- end -}}
{{- end -}}
{{/*
Return the Redis Database
*/}}
{{- define "invoiceninja.redisDatabase" -}}
{{- if .Values.redis.enabled }}
{{- printf "0" -}}
{{- else -}}
{{- printf "%s" .Values.externalRedis.databases.default -}}
{{- end -}}
{{- end -}}
{{/*
Return the Redis Database
*/}}
{{- define "invoiceninja.redisCacheDatabase" -}}
{{- if .Values.redis.enabled }}
{{- printf "1" -}}
{{- else -}}
{{- printf "%s" .Values.externalRedis.databases.cache -}}
{{- end -}}
{{- end -}}
{{/*
Return the Redis Secret Name
*/}}
{{- define "invoiceninja.redisSecretName" -}}
{{- if .Values.externalRedis.existingSecret -}}
{{- printf "%s" .Values.externalRedis.existingSecret -}}
{{- else -}}
{{- printf "%s" (include "invoiceninja.redis.fullname" .) -}}
{{- end -}}
{{- end -}}
{{/*
Return the Broadcast Connection Name
*/}}
{{- define "invoiceninja.redisBroadcastConnection" -}}
{{- if or (and .Values.redis.enabled .Values.redis.sentinel.enabled) (and .Values.externalRedis.host .Values.externalRedis.sentinel) }}
{{- printf "sentinel-default" -}}
{{- else -}}
{{- printf "default" -}}
{{- end -}}
{{- end -}}
{{/*
Return the Cache Connection Name
*/}}
{{- define "invoiceninja.redisCacheConnection" -}}
{{- if or (and .Values.redis.enabled .Values.redis.sentinel.enabled) (and .Values.externalRedis.host .Values.externalRedis.sentinel) }}
{{- printf "sentinel-cache" -}}
{{- else -}}
{{- printf "cache" -}}
{{- end -}}
{{- end -}}
{{/*
Return the Queue Connection Name
*/}}
{{- define "invoiceninja.redisQueueConnection" -}}
{{- if or (and .Values.redis.enabled .Values.redis.sentinel.enabled) (and .Values.externalRedis.host .Values.externalRedis.sentinel) }}
{{- printf "sentinel-default" -}}
{{- else -}}
{{- printf "default" -}}
{{- end -}}
{{- end -}}
{{/*
Return the Session Connection Name
*/}}
{{- define "invoiceninja.redisSessionConnection" -}}
{{- if or (and .Values.redis.enabled .Values.redis.sentinel.enabled) (and .Values.externalRedis.host .Values.externalRedis.sentinel) }}
{{- printf "sentinel-default" -}}
{{- else -}}
{{- printf "default" -}}
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,65 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "common.names.fullname" . }}
labels:
{{- include "common.labels.standard" $ | nindent 4 }}
{{- if .Values.commonLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- end }}
{{- if .Values.commonAnnotations }}
annotations:
{{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
data:
{{- if .Values.nginx.ingress.enabled }}
{{- if .Values.nginx.ingress.tls }}
APP_URL: "https://{{ .Values.nginx.ingress.hostname }}"
{{- else }}
APP_URL: "http://{{ .Values.nginx.ingress.hostname }}"
{{- end }}
{{- else }}
APP_URL: "http://{{ include "common.names.fullname" . }}"
{{- end }}
APP_DEBUG: {{ .Values.debug | quote }}
DB_HOST: {{ include "invoiceninja.databaseHost" . | quote }}
DB_PORT: {{ include "invoiceninja.databasePort" . | quote }}
DB_USERNAME: {{ include "invoiceninja.databaseUser" . | quote }}
DB_DATABASE: {{ include "invoiceninja.databaseName" . | quote }}
{{- if .Values.logChannel }}
LOG_CHANNEL: {{ .Values.logChannel | quote }}
{{- else }}
LOG_CHANNEL: stderr
{{- end }}
MAIL_MAILER: {{ .Values.mailer | quote }}
{{- if .Values.broadcastDriver }}
BROADCAST_DRIVER: {{ .Values.broadcastDriver | quote }}
{{- else if or .Values.redis.enabled .Values.externalRedis.host }}
BROADCAST_DRIVER: redis
{{- end }}
{{- if .Values.cacheDriver }}
CACHE_DRIVER: {{ .Values.cacheDriver | quote }}
{{- else if or .Values.redis.enabled .Values.externalRedis.host }}
CACHE_DRIVER: redis
{{- end }}
{{- if .Values.sessionDriver }}
SESSION_DRIVER: {{ .Values.sessionDriver | quote }}
{{- else if or .Values.redis.enabled .Values.externalRedis.host }}
SESSION_DRIVER: redis
{{- end }}
{{- if .Values.queueConnection }}
QUEUE_CONNECTION: {{ .Values.queueConnection | quote }}
{{- else if or .Values.redis.enabled .Values.externalRedis.host }}
QUEUE_CONNECTION: redis
{{- end }}
PHANTOMJS_PDF_GENERATION: {{ not .Values.snappdf | quote}}
REDIS_HOST: {{ include "invoiceninja.redisHost" . | quote }}
REDIS_PORT: {{ include "invoiceninja.redisPort" . | quote }}
REDIS_DB: {{ include "invoiceninja.redisDatabase" . | quote }}
REDIS_CACHE_DB: {{ include "invoiceninja.redisCacheDatabase" . | quote }}
REDIS_BROADCAST_CONNECTION: {{ include "invoiceninja.redisBroadcastConnection" . | quote }}
REDIS_CACHE_CONNECTION: {{ include "invoiceninja.redisCacheConnection" . | quote }}
REDIS_QUEUE_CONNECTION: {{ include "invoiceninja.redisQueueConnection" . | quote }}
SESSION_CONNECTION: {{ include "invoiceninja.redisSessionConnection" . | quote }}
REQUIRE_HTTPS: {{ .Values.requireHttps | quote }}
TRUSTED_PROXIES: {{ .Values.trustedProxies | quote }}

View File

@@ -0,0 +1,211 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "common.names.fullname" . }}
labels:
{{- include "common.labels.standard" $ | nindent 4 }}
app.kubernetes.io/component: server
{{- if .Values.commonLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- end }}
{{- if .Values.commonAnnotations }}
annotations:
{{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
{{- if .Values.updateStrategy }}
strategy: {{- toYaml .Values.updateStrategy | nindent 4 }}
{{- end }}
selector:
matchLabels:
{{- include "common.labels.matchLabels" $ | nindent 6 }}
app.kubernetes.io/component: server
template:
metadata:
{{- if .Values.podAnnotations }}
annotations:
{{- include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }}
{{- end }}
labels:
{{- include "common.labels.standard" $ | nindent 8 }}
app.kubernetes.io/component: server
{{- if .Values.podLabels }}
{{- include "common.tplvalues.render" (dict "value" .Values.podLabels "context" $) | nindent 8 }}
{{- end }}
spec:
{{- include "invoiceninja.imagePullSecrets" . | nindent 6 }}
serviceAccountName: {{ include "invoiceninja.serviceAccountName" . }}
{{- if .Values.affinity }}
affinity: {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }}
{{- else }}
affinity:
podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "context" $) | nindent 10 }}
podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "context" $) | nindent 10 }}
nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }}
{{- end }}
{{- if .Values.nodeSelector }}
nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }}
{{- end }}
{{- if .Values.tolerations }}
tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" $) | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
initContainers:
- name: wait-db
image: {{ include "invoiceninja.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command:
- /bin/sh
- -cx
- |
COUNTER=0;
[[ -z "${DB_HOST1}" ]] || DB_HOST="${DB_HOST1}";
[[ -z "${DB_PORT1}" ]] || DB_PORT="${DB_PORT1}";
while [ $COUNTER -lt 120 ]; do
if mysqladmin ping -h "$DB_HOST" -P $DB_PORT --silent; then
exit 0;
fi;
let COUNTER=COUNTER+1;
echo "Waiting for DB... Trying again in 2s";
sleep 2;
done;
echo "Did NOT see a database after 240 secs!";
exit 1;
securityContext:
{{- toYaml .Values.containerSecurityContext | nindent 12 }}
{{- if .Values.resources }}
resources: {{- toYaml .Values.resources | nindent 12 }}
{{- end }}
envFrom:
- configMapRef:
name: {{ include "common.names.fullname" . }}
{{- if .Values.extraEnvVarsCM }}
- configMapRef:
name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsCM "context" $) }}
{{- end }}
{{- if .Values.extraEnvVarsSecret }}
- secretRef:
name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsSecret "context" $) }}
{{- end }}
env:
{{- if .Values.extraEnvVars }}
{{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }}
{{- end }}
{{- if and .Values.podSecurityContext .Values.volumePermissions.enabled (or .Values.persistence.public.enabled .Values.persistence.storage.enabled) }}
- name: volume-permissions
image: {{ include "invoiceninja.volumePermissions.image" . }}
imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }}
command:
- /bin/bash
- -ec
- |
chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} /var/www/app/{public,storage}
securityContext:
runAsUser: 0
{{- if .Values.volumePermissions.resources }}
resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }}
{{- end }}
volumeMounts:
- mountPath: /var/www/app/public
name: public
- mountPath: /var/www/app/storage
name: storage
{{- end }}
{{- if .Values.initContainers }}
{{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.containerSecurityContext | nindent 12 }}
image: {{ include "invoiceninja.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: fastcgi
containerPort: {{ .Values.containerPorts.fastcgi }}
protocol: TCP
{{- if .Values.livenessProbe.enabled }}
livenessProbe:
initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
timeoutSeconds: {{ $.Values.livenessProbe.timeoutSeconds }}
successThreshold: {{ $.Values.livenessProbe.successThreshold }}
failureThreshold: {{ $.Values.livenessProbe.failureThreshold }}
tcpSocket:
port: {{ .Values.livenessProbe.port }}
{{- end }}
{{- if .Values.readinessProbe.enabled }}
readinessProbe:
initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
timeoutSeconds: {{ $.Values.readinessProbe.timeoutSeconds }}
successThreshold: {{ $.Values.readinessProbe.successThreshold }}
failureThreshold: {{ $.Values.readinessProbe.failureThreshold }}
tcpSocket:
port: {{ .Values.readinessProbe.port }}
{{- end }}
envFrom:
- configMapRef:
name: {{ include "common.names.fullname" . }}
- secretRef:
name: {{ include "common.names.fullname" . }}
{{- if .Values.extraEnvVarsCM }}
- configMapRef:
name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsCM "context" $) }}
{{- end }}
{{- if .Values.extraEnvVarsSecret }}
- secretRef:
name: {{ include "common.tplvalues.render" (dict "value" .Values.extraEnvVarsSecret "context" $) }}
{{- end }}
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "invoiceninja.databaseSecretName" . }}
key: mariadb-password
{{- if or (and .Values.redis.enabled .Values.redis.usePassword) (or .Values.externalRedis.password .Values.externalRedis.existingSecret) }}
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "invoiceninja.redisSecretName" . }}
key: redis-password
{{- end }}
{{- if .Values.userEmail }}
- name: IN_USER_EMAIL
value: {{ .Values.userEmail | quote }}
{{- end }}
{{- if .Values.extraEnvVars }}
{{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumeMounts:
- mountPath: /var/www/app/public
name: public
- mountPath: /var/www/app/storage
name: storage
{{- if .Values.extraVolumeMounts }}
{{- include "common.tplvalues.render" (dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }}
{{- end }}
volumes:
- name: public
{{- if .Values.persistence.public.enabled }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.public.existingClaim | default (include "invoiceninja.public.storageName" .) }}
{{- else }}
emptyDir: {}
{{ end }}
- name: storage
{{- if .Values.persistence.storage.enabled }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.storage.existingClaim | default (include "invoiceninja.storage.storageName" .) }}
{{- else }}
emptyDir: {}
{{ end }}
{{- if .Values.extraVolumes }}
{{- include "common.tplvalues.render" (dict "value" .Values.extraVolumes "context" $) | nindent 8 }}
{{- end }}

View File

@@ -0,0 +1,35 @@
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "common.names.fullname" . }}
labels:
{{- include "common.labels.standard" $ | nindent 4 }}
{{- if .Values.commonLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- end }}
{{- if .Values.commonAnnotations }}
annotations:
{{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "common.names.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
- type: Resource
resource:
name: cpu
targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
- type: Resource
resource:
name: memory
targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,52 @@
{{- if and .Values.persistence.public.enabled (not .Values.persistence.public.existingClaim) }}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: {{ include "invoiceninja.public.storageName" . }}
labels:
{{- include "common.labels.standard" . | nindent 4 }}
{{- if .Values.commonLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- end }}
{{- if .Values.commonAnnotations }}
annotations:
{{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
spec:
accessModes:
- {{ .Values.persistence.public.accessMode | quote }}
resources:
requests:
storage: {{ .Values.persistence.public.size | quote }}
{{- include "invoiceninja.public.storageClass" . | nindent 2 }}
{{- if .Values.persistence.public.dataSource }}
dataSource: {{- include "common.tplvalues.render" ( dict "value" .Values.persistence.public.dataSource "context" $ ) | nindent 4 }}
{{- end }}
{{- end }}
---
{{- if and .Values.persistence.storage.enabled (not .Values.persistence.storage.existingClaim) }}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: {{ include "invoiceninja.storage.storageName" . }}
labels:
{{- include "common.labels.standard" . | nindent 4 }}
{{- if .Values.commonLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- end }}
{{- if .Values.commonAnnotations }}
annotations:
{{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
spec:
accessModes:
- {{ .Values.persistence.storage.accessMode | quote }}
resources:
requests:
storage: {{ .Values.persistence.storage.size | quote }}
{{- include "invoiceninja.storage.storageClass" . | nindent 2 }}
{{- if .Values.persistence.storage.dataSource }}
dataSource: {{- include "common.tplvalues.render" ( dict "value" .Values.persistence.storage.dataSource "context" $ ) | nindent 4 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,63 @@
{{- if not (or .Values.mariadb.enabled .Values.externalDatabase.existingSecret) }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "invoiceninja.mariadb.fullname" . }}
labels:
{{- include "common.labels.standard" $ | nindent 4 }}
{{- if .Values.commonLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- end }}
{{- if .Values.commonAnnotations }}
annotations:
{{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
type: Opaque
data:
mariadb-password: {{ .Values.externalDatabase.password | b64enc | quote }}
{{- end }}
---
{{- if not (or .Values.redis.enabled .Values.externalDatabase.existingSecret) }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "invoiceninja.redis.fullname" . }}
labels:
{{- include "common.labels.standard" $ | nindent 4 }}
{{- if .Values.commonLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- end }}
{{- if .Values.commonAnnotations }}
annotations:
{{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
type: Opaque
data:
redis-password: {{ .Values.externalRedis.password | b64enc | quote }}
{{- end }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ include "common.names.fullname" . }}
labels:
{{- include "common.labels.standard" $ | nindent 4 }}
{{- if .Values.commonLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- end }}
{{- if .Values.commonAnnotations }}
annotations:
{{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
type: Opaque
data:
{{- if not (empty .Values.appKey) }}
APP_KEY: {{ .Values.appKey | b64enc | quote }}
{{- else }}
APP_KEY: {{ randAlphaNum 32 | b64enc | quote }}
{{- end }}
{{- if .Values.userPassword }}
IN_PASSWORD: {{ .Values.userPassword | b64enc | quote }}
{{- end }}

View File

@@ -0,0 +1,47 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "common.names.fullname" . }}
labels:
{{- include "common.labels.standard" $ | nindent 4 }}
{{- if .Values.commonLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- end }}
{{- if or .Values.service.annotations .Values.commonAnnotations }}
annotations:
{{- if .Values.service.annotations }}
{{- include "common.tplvalues.render" ( dict "value" .Values.service.annotations "context" $ ) | nindent 4 }}
{{- end }}
{{- if .Values.commonAnnotations }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
{{- end }}
spec:
type: {{ .Values.service.type }}
{{- if and .Values.service.clusterIP (eq .Values.service.type "ClusterIP") }}
clusterIP: {{ .Values.service.clusterIP }}
{{- end }}
{{- if (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort")) }}
externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }}
{{- end }}
{{- if (and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges) }}
loadBalancerSourceRanges: {{- toYaml . | nindent 4 }}
{{- end }}
{{- if (and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP))) }}
loadBalancerIP: {{ .Values.service.loadBalancerIP }}
{{- end }}
ports:
{{- if not (empty .Values.service.port) }}
- name: fastcgi
port: {{ .Values.service.port }}
protocol: TCP
targetPort: fastcgi
{{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePort))) }}
nodePort: {{ .Values.service.nodePort }}
{{- else if eq .Values.service.type "ClusterIP" }}
nodePort: null
{{- end }}
{{- end }}
selector:
{{- include "common.labels.matchLabels" . | nindent 4 }}
app.kubernetes.io/component: server

View File

@@ -0,0 +1,20 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "invoiceninja.serviceAccountName" . }}
labels:
{{- include "common.labels.standard" $ | nindent 4 }}
{{- if .Values.commonLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- end }}
{{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }}
annotations:
{{- if .Values.serviceAccount.annotations }}
{{- include "common.tplvalues.render" ( dict "value" .Values.serviceAccount.annotations "context" $ ) | nindent 4 }}
{{- end }}
{{- if .Values.commonAnnotations }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,511 @@
# Default values for invoiceninja.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
## Global Docker image parameters
## Please, note that this will override the image parameters, including dependencies, configured to use the global value
## Current available global Docker image parameters: imageRegistry, imagePullSecrets and storageClass
##
# global:
# imageRegistry: myRegistryName
# imagePullSecrets:
# - myRegistryKeySecretName
# storageClass: myStorageClass
## Invoice Ninja image version
## ref: https://github.com/invoiceninja/dockerfiles
##
image:
registry: docker.io
repository: invoiceninja/invoiceninja
tag: 5.1.64
## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent'
## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images
##
pullPolicy: IfNotPresent
## Optionally specify an array of imagePullSecrets.
## Secrets must be manually created in the namespace.
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
##
# pullSecrets:
# - myRegistryKeySecretName
## String to turn on debug mode in Invoice Ninja
##
debug: false
## A 32 character long Application Key
##
appKey: ""
## Email of user to create first run
## If not specified, default user email will be "admin@example.com"
##
userEmail: ""
## Password of user to create on first run
## If not specified, default user password will be "changeme!"
##
userPassword: ""
## Name of log channel to use
##
logChannel: ""
## Name of broadcast driver to use
##
broadcastDriver: ""
## Name of cache driver to use
##
cacheDriver: ""
## Name of session driver to use
##
sessionDriver: ""
## Name of queue connection to use
##
queueConnection: ""
## List of trusted proxies for Invoice Ninja to communicate with the nginx proxy
##
trustedProxies: "*"
## Use local or Phantom JS PDF generation
##
snappdf: true
## Name of queue connection to use (use "log" for debug)
## Please check the ref below for any other env you may need to define
## ref: https://github.com/invoiceninja/invoiceninja/blob/v5-stable/config/mail.php
##
mailer: log
## Force HTTPS for all connections to Invoice Ninja
##
requireHttps: false
## String to partially override fullname template (will maintain the release name)
##
# nameOverride:
## String to fully override fullname template
##
# fullnameOverride:
## Add labels to all the deployed resources
##
commonLabels: {}
## Add annotations to all the deployed resources
##
commonAnnotations: {}
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
## Pod Labels
## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
##
podLabels: {}
## Pod annotations
## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
##
podAnnotations: {}
## Pod affinity preset
## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity
## Allowed values: soft, hard
##
podAffinityPreset: ""
## Pod anti-affinity preset
## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity
## Allowed values: soft, hard
##
podAntiAffinityPreset: soft
## Node affinity preset
## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity
## Allowed values: soft, hard
##
nodeAffinityPreset:
## Node affinity type
## Allowed values: soft, hard
##
type: ""
## Node label key to match
## E.g.
## key: "kubernetes.io/e2e-az-name"
##
key: ""
## Node label values to match
## E.g.
## values:
## - e2e-az1
## - e2e-az2
##
values: []
## Affinity for pod assignment. Evaluated as a template.
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set
##
affinity: {}
## Node labels for pod assignment. Evaluated as a template.
## ref: https://kubernetes.io/docs/user-guide/node-selection/
##
nodeSelector: {}
## Tolerations for pod assignment. Evaluated as a template.
## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
##
tolerations: []
## Configure Pods Security Context
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod
##
podSecurityContext:
fsGroup: 1500
## Configure Container Security Context (only main container)
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container
##
containerSecurityContext:
runAsNonRoot: true
runAsUser: 1500
# runAsGroup: 1500
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
## Init containers parameters:
## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup values from the securityContext section.
##
volumePermissions:
enabled: false
image:
registry: docker.io
repository: bitnami/bitnami-shell
tag: "10"
pullPolicy: Always
## Optionally specify an array of imagePullSecrets.
## Secrets must be manually created in the namespace.
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
##
# pullSecrets:
# - myRegistryKeySecretName
resources: {}
## Number of replicas (requires ReadWriteMany PVC support)
##
replicaCount: 1
## Set up update strategy for Invoice Ninja installation. Set to Recreate if you use persistent volume that cannot be mounted by more than one pods to makesure the pods is destroyed first.
## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy
## Example:
## updateStrategy:
## type: RollingUpdate
## rollingUpdate:
## maxSurge: 25%
## maxUnavailable: 25%
##
updateStrategy:
type: RollingUpdate
## Container ports
##
containerPorts:
fastcgi: 9000
## An array to add extra env vars
## Example:
## extraEnvVars:
## - name: FOO
## value: "bar"
##
extraEnvVars: []
## ConfigMap with extra environment variables
##
extraEnvVarsCM:
## Secret with extra environment variables
##
extraEnvVarsSecret:
## Extra volumes to add to the deployment
##
extraVolumes: []
## Extra volume mounts to add to the container
##
extraVolumeMounts: []
## Kubernetes service type
## ref: https://kubernetes.io/docs/concepts/services-networking/service/
## Set this to NodePort, LoadBalancer or ClusterIP
##
service:
## Service type
## ref: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
##
type: ClusterIP
## Service ports
##
port: 9000
## Specify the nodePort value for the LoadBalancer and NodePort service types.
## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport
##
nodePort: ""
## Service clusterIP.
##
# clusterIP: None
## Specify the loadBalancerIP value for LoadBalancer service types.
## ref: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer
##
# loadBalancerIP:
## Specify the loadBalancerSourceRanges value for LoadBalancer service types.
## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service
##
loadBalancerSourceRanges: []
## Enable client source IP preservation
## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip
##
externalTrafficPolicy: Cluster
## Additional service annotations (evaluate as a template)
## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
##
annotations: {}
## Configure extra options for liveness and readiness probes
## This applies to all the Invoice Ninja in the sharded cluster
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes)
##
livenessProbe:
enabled: true
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
successThreshold: 1
port: fastcgi
readinessProbe:
enabled: true
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
successThreshold: 1
port: fastcgi
resources:
{}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
## Enable persistence using Persistent Volume Claims
## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
##
persistence:
public:
enabled: true
## Invoice Ninja data Persistent Volume Storage Class
## If defined, storageClassName: <storageClass>
## If set to "-", storageClassName: "", which disables dynamic provisioning
## If undefined (the default) or set to null, no storageClassName spec is
## set, choosing the default provisioner. (gp2 on AWS, standard on
## GKE, AWS & OpenStack)
##
# storageClass: "-"
##
## If you want to reuse an existing claim, you can pass the name of the PVC using
## the existingClaim variable
# existingClaim: your-claim
accessMode: ReadWriteMany
size: 1Gi
## Custom dataSource
##
dataSource: {}
storage:
enabled: true
## Invoice Ninja data Persistent Volume Storage Class
## If defined, storageClassName: <storageClass>
## If set to "-", storageClassName: "", which disables dynamic provisioning
## If undefined (the default) or set to null, no storageClassName spec is
## set, choosing the default provisioner. (gp2 on AWS, standard on
## GKE, AWS & OpenStack)
##
# storageClass: "-"
##
## If you want to reuse an existing claim, you can pass the name of the PVC using
## the existingClaim variable
# existingClaim: your-claim
accessMode: ReadWriteMany
size: 10Gi
## Custom dataSource
##
dataSource: {}
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 10
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80
## Redis chart configuration
## ref: https://github.com/bitnami/charts/blob/master/bitnami/redis/values.yaml
##
redis:
enabled: true
sentinel:
enabled: true
usePassword: false
## External Redis Configuration
##
## All of these values are only used when redis.enabled is set to false
##
externalRedis:
## Redis/Sentinel host
##
host: ""
## Redis/Sentinel port number
##
port: 6379
## Redis password
##
password: ""
## Use existing secret (ignores previous password)
## must contain key `redis-password`
## NOTE: When it's set, the `externalRedis.password` parameter is ignored
##
# existingSecret:
## Whether Redis Sentinel are used
sentinel: false
## Redis databases
##
databases:
default: "0"
cache: "1"
## MariaDB chart configuration
## ref: https://github.com/bitnami/charts/blob/master/bitnami/mariadb/values.yaml
##
mariadb:
## Whether to deploy a MariaDB server to satisfy the applications database requirements.
## To use an external database set this to false and configure the externaldb parameters
##
enabled: true
## MariaDB Authentication parameters
##
auth:
## MariaDB root password
##
# rootPassword: changeit
## MariaDB custom user and database
##
username: invoiceninja
database: invoiceninja
# password: changeit
## External Database Configuration
##
## All of these values are only used when mariadb.enabled is set to false
##
externalDatabase:
## Database host
##
host: ""
## non-root Username for Invoice Ninja Database
##
user: invoiceninja
## Database password
##
password: ""
## Database name
##
database: invoiceninja
## Database port number
##
port: 3306
## Use existing secret (ignores previous password)
## must contain key `mariadb-password`
## NOTE: When it's set, the `externalDatabase.password` parameter is ignored
##
# existingSecret:
## Nginx chart configuration
## ref: https://github.com/bitnami/charts/blob/master/bitnami/nginx/values.yaml
##
nginx:
service:
## Service type
## ref: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
##
type: ClusterIP
## Configure the ingress resource that allows you to access the Invoice Ninja
## ref: http://kubernetes.io/docs/user-guide/ingress/
##
ingress:
enabled: true
hostname: invoiceninja.local
## Configure the serverblock for Invoice Ninja
## Note: you may need to replace the fastcgi_pass value if the release name is different
##
serverBlock: |
server {
listen 8080 default_server;
server_name _;
root /var/www/app/public/;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass invoiceninja:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors off;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
}
}
## Configure the extraVolumes and extraVolumeMounts for Invoice Ninja
## Note: you may need to replace the claimName if the release name is different
##
extraVolumes:
- name: public
persistentVolumeClaim:
claimName: invoiceninja-public
extraVolumeMounts:
- mountPath: /var/www/app/public
name: public
readOnly: true

View File

@@ -1,16 +0,0 @@
#!/bin/sh
echo "Early Entry"
cleanup ()
{
kill -s SIGTERM $!
exit 0
}
trap cleanup SIGINT SIGTERM
while :
do
sleep 60 ; cd /var/www/app/ && php artisan schedule:run;
done

12
config/mysql/Dockerfile Normal file
View File

@@ -0,0 +1,12 @@
FROM mysql:5
# When running on ARM64 use MariaDB instead of MySQL
#FROM mariadb:10.4
ENV force_color_prompt yes
RUN apt-get update;
RUN apt-get install -y cron;
ENTRYPOINT \
service cron start; \
printenv | grep -v "no_proxy" >> /etc/environment; \
docker-entrypoint.sh mysqld

View File

@@ -0,0 +1,28 @@
#!/bin/sh
FREQUENTY=`basename "$0"`
TIMESTAMP=$(date +"%Y-%m-%d")
case $FREQUENTY in
daily)
DAYS=6
;;
weekly)
DAYS=30
find /backups -type f -name $TIMESTAMP-daily.sql.gz -delete
;;
monthly)
DAYS=122
find /backups -type f -name $TIMESTAMP-weekly.sql.gz -delete
;;
esac
mysqldump -u ${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_DATABASE} | gzip > /backups/$TIMESTAMP-$FREQUENTY.sql.gz
# Remove old backups
find /backups -mtime +${DAYS} -type f -name *-$FREQUENTY.sql.gz -delete
exit 0;

View File

@@ -2,6 +2,8 @@ server {
listen 80 default_server;
server_name _;
client_max_body_size 100M;
root /var/www/app/public/;
index index.php;

View File

@@ -1,18 +0,0 @@
session.auto_start = Off
short_open_tag = Off
error_reporting = E_ALL & ~E_NOTICE & ~E_WARNING & ~E_STRICT & ~E_DEPRECATED
opcache.enable_cli=1
opcache.fast_shutdown=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
# http://symfony.com/doc/current/performance.html
realpath_cache_size = 4096K
realpath_cache_ttl = 600
memory_limit = 2G
post_max_size = 6M
upload_max_filesize = 5M

View File

@@ -1,17 +0,0 @@
session.auto_start = Off
short_open_tag = Off
error_reporting = E_ALL & ~E_NOTICE & ~E_WARNING & ~E_STRICT & ~E_DEPRECATED
opcache.enable_cli=1
opcache.fast_shutdown=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
# http://symfony.com/doc/current/performance.html
realpath_cache_size = 4096K
realpath_cache_ttl = 600
post_max_size = 6M
upload_max_filesize = 5M

View File

@@ -9,14 +9,12 @@ services:
# Vhost configuration
#- ./config/caddy/Caddyfile:/etc/caddy/Caddyfiledocker-com
- ./config/nginx/in-vhost.conf:/etc/nginx/conf.d/in-vhost.conf:ro
# you may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
- ./docker/app/public:/var/www/app/public:rw,delegated
- ./docker/app/storage:/var/www/app/storage:rw,delegated
- ./docker/app/public:/var/www/app/public:ro
depends_on:
- app
# Run webserver nginx on port 80
# Feel free to modify depending what port is already occupied
ports:
ports:
- "80:80"
#- "443:443"
networks:
@@ -28,51 +26,36 @@ services:
image: invoiceninja/invoiceninja:5
env_file: env
restart: always
cap_add:
- SYS_ADMIN
volumes:
# you may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
- ./config/hosts:/etc/hosts:ro
- ./docker/app/public:/var/www/app/public:rw,delegated
- ./docker/app/storage:/var/www/app/storage:rw,delegated
depends_on:
- db
networks:
- invoiceninja
extra_hosts:
- "in5.localhost:192.168.0.124 " #host and ip
db:
image: mysql:5
ports:
- "3305:3306"
restart: always
environment:
- MYSQL_ROOT_PASSWORD=ninjaAdm1nPassword
- MYSQL_USER=ninja
- MYSQL_PASSWORD=ninja
- MYSQL_DATABASE=ninja
volumes:
# you may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
- ./docker/mysql/data:/var/lib/mysql:rw,delegated
networks:
- invoiceninja
extra_hosts:
- "in5.localhost:192.168.0.124 " #host and ip
# THIS IS ONLY A VALID CONFIGURATION FOR IN 5. DO NOT USE FOR IN 4.
cron:
image: invoiceninja/invoiceninja:5
db:
image: mysql:5
# When running on ARM64 use MariaDB instead of MySQL
# image: mariadb:10.4
# For auto DB backups comment out image and use the build block below
# build:
# context: ./config/mysql
ports:
- "3305:3306"
restart: always
env_file: env
volumes:
- ./config/cron.sh:/usr/local/bin/cron.sh
- ./config/hosts:/etc/hosts:ro
- ./docker/app/public:/var/www/app/public:rw,delegated
- ./docker/app/storage:/var/www/app/storage:rw,delegated
command:
- cron.sh
depends_on:
- app
- ./docker/mysql/data:/var/lib/mysql:rw,delegated
# remove comments for next 4 lines if you want auto sql backups
#- ./docker/mysql/bak:/backups:rw
#- ./config/mysql/backup-script:/etc/cron.daily/daily:ro
#- ./config/mysql/backup-script:/etc/cron.weekly/weekly:ro
#- ./config/mysql/backup-script:/etc/cron.monthly/monthly:ro
networks:
- invoiceninja
extra_hosts:
@@ -97,7 +80,7 @@ services:
# EOF'
# networks:
# - invoiceninja
#
#
networks:
invoiceninja:
invoiceninja:

42
env
View File

@@ -1,17 +1,41 @@
APP_URL=http://in.localhost:8003/
# IN application vars
APP_URL=http://in.localhost:8003
APP_KEY=<insert your generated key in here>
APP_DEBUG=true
MULTI_DB_ENABLED=false
DB_HOST1=db
DB_USERNAME1=ninja
DB_PASSWORD1=ninja
DB_DATABASE1=ninja
REQUIRE_HTTPS=false
PHANTOMJS_PDF_GENERATION=false
QUEUE_CONNECTION=database
#V4 env vars
DB_STRICT=false
# DB connection
DB_HOST=db
DB_PORT=3306
DB_DATABASE=ninja
DB_USERNAME=ninja
DB_PASSWORD=ninja
APP_CIPHER=AES-256-CBC
# Create initial user
# Default to these values if empty
# IN_USER_EMAIL=admin@example.com
# IN_PASSWORD=changeme!
IN_USER_EMAIL=
IN_PASSWORD=
# Mail options
MAIL_MAILER=log
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS='user@example.com'
MAIL_FROM_NAME='Self Hosted User'
# MySQL
MYSQL_ROOT_PASSWORD=ninjaAdm1nPassword
MYSQL_USER=ninja
MYSQL_PASSWORD=ninja
MYSQL_DATABASE=ninja
# V4 env vars
# DB_STRICT=false
# APP_CIPHER=AES-256-CBC

View File

@@ -0,0 +1,13 @@
FROM invoiceninja/invoiceninja:5
USER root
RUN apk add --no-cache supervisor \
&& mkdir /var/log/supervisord /var/run/supervisord \
&& chown $INVOICENINJA_USER:www-data /var/log/supervisord /var/run/supervisord
COPY supervisord.conf /
USER $INVOICENINJA_USER
CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf"]

View File

@@ -0,0 +1,29 @@
[supervisord]
nodaemon=true
user=invoiceninja
pidfile=/var/run/supervisord/supervisord.pid
logfile=/dev/null ; nodaemon will cause logs to go to stdout
logfile_maxbytes=0
loglevel=error
[program:php-fpm]
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
command=php-fpm
[program:scheduler]
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
command=php artisan schedule:work
[program:queue-worker]
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
numprocs=2
command=php artisan queue:work --sleep=3 --tries=1 --memory=1024 --timeout=3600 --daemon