diff --git a/.gitignore b/.gitignore index 4d67604d..502c3673 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,7 @@ *.code-workspace + +# Environment Variables +.env + +# mounted volume +sites diff --git a/.travis.yml b/.travis.yml index de8802ae..f3724041 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,30 +1,192 @@ +sudo: required + dist: xenial -env: - - DOCKER_COMPOSE_VERSION: 1.23.1 - - services: - docker before_install: - - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - - - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" - - sudo apt-get update - - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce - - sudo rm /usr/local/bin/docker-compose - - curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose - - chmod +x docker-compose - - sudo mv docker-compose /usr/local/bin + - if [[ "$BUILD" -ne "development" ]]; then + echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin; + sudo apt-get update && sudo apt-get -y install git; + fi + - if [[ $BUILD == "development" ]];then + sudo apt-get update && sudo apt-get -y install docker-compose; + fi install: - - chmod ugo+x ./dbench - - chmod ugo+x ./test.sh - - ./dbench setup docker - - ./dbench init frappe-bench - - ./dbench new-site site1.local - - ./dbench setup hosts + - if [[ $BUILD == "development" ]];then + chmod ugo+x ./dbench; + chmod ugo+x ./test.sh; + ./dbench setup docker; + ./dbench init frappe-bench; + ./dbench new-site site1.local; + ./dbench setup hosts; + fi -script: - - ./test.sh - - ./dbench setup docker stop +after_success: + - docker --version + +matrix: + include: + - name: "Test Frappe / ERPNext development" + env: BUILD=development + script: + - ./test.sh + - ./dbench setup docker stop + - name: "Build Frappe python environment (edge)" + if: branch = develop AND type != pull_request + script: + - docker build -t frappe-worker -f build/frappe-worker/Dockerfile . + - docker tag frappe-worker frappe/frappe-worker:edge + - docker tag frappe-worker frappe/frappe-worker:develop + - docker push frappe/frappe-worker:edge + - name: "Build Frappe nginx + static assets (edge)" + if: branch = develop AND type != pull_request + script: + - docker build -t frappe-assets -f build/frappe-assets/Dockerfile . + - docker tag frappe-assets frappe/frappe-assets:edge + - docker tag frappe-assets frappe/frappe-assets:develop + - docker push frappe/frappe-assets:edge + - name: "Build ERPNext python environment (edge)" + if: branch = develop AND type != pull_request + script: + - docker build -t erpnext-worker -f build/erpnext-worker/Dockerfile . + - docker tag erpnext-worker frappe/erpnext-worker:edge + - docker tag erpnext-worker frappe/erpnext-worker:develop + - docker push frappe/erpnext-worker:edge + - name: "Build ERPNext nginx + static assets (edge)" + if: branch = develop AND type != pull_request + script: + - docker build -t erpnext-assets -f build/erpnext-assets/Dockerfile . + - docker tag erpnext-assets frappe/erpnext-assets:edge + - docker tag erpnext-assets frappe/erpnext-assets:develop + - docker push frappe/erpnext-assets:edge + - name: "Build Frappe socketio service (edge)" + if: branch = develop AND type != pull_request + script: + - docker build -t frappe-socketio -f build/frappe-socketio/Dockerfile . + - docker tag frappe-socketio frappe/frappe-socketio:edge + - docker tag frappe-socketio frappe/frappe-socketio:develop + - docker push frappe/frappe-socketio:edge + - name: "Build Frappe python environment (v12)" + if: branch = master AND type != pull_request + script: + - git clone https://github.com/frappe/frappe --branch version-12 + - cd frappe + - git fetch --tags + - export VERSION=$(git tag --list --sort=-version:refname "v12*" | sed -n 1p | sed -e 's#.*@\(\)#\1#') + - cd .. + - docker build -t frappe/frappe-worker:$VERSION -f build/frappe-worker/v12.Dockerfile . + - docker tag frappe/frappe-worker:$VERSION frappe/frappe-worker:version-12 + - docker tag frappe/frappe-worker:$VERSION frappe/frappe-worker:v12 + - docker tag frappe/frappe-worker:$VERSION frappe/frappe-worker:$VERSION + - docker push frappe/frappe-worker:$VERSION + - name: "Build Frappe nginx + static assets (v12)" + if: branch = master AND type != pull_request + script: + - git clone https://github.com/frappe/frappe --branch version-12 + - cd frappe + - git fetch --tags + - export VERSION=$(git tag --list --sort=-version:refname "v12*" | sed -n 1p | sed -e 's#.*@\(\)#\1#') + - cd .. + - docker build -t frappe/frappe-assets:$VERSION -f build/frappe-assets/v12.Dockerfile . + - docker tag frappe/frappe-assets:$VERSION frappe/frappe-assets:version-12 + - docker tag frappe/frappe-assets:$VERSION frappe/frappe-assets:v12 + - docker push frappe/frappe-assets:$VERSION + - name: "Build ERPNext python environment (v12)" + if: branch = master AND type != pull_request + script: + - git clone https://github.com/frappe/erpnext --branch version-12 + - cd erpnext + - git fetch --tags + - export VERSION=$(git tag --list --sort=-version:refname "v12*" | sed -n 1p | sed -e 's#.*@\(\)#\1#') + - cd .. + - docker build -t frappe/erpnext-worker:$VERSION -f build/erpnext-worker/v12.Dockerfile . + - docker tag frappe/erpnext-worker:$VERSION frappe/erpnext-worker:version-12 + - docker tag frappe/erpnext-worker:$VERSION frappe/erpnext-worker:v12 + - docker push frappe/erpnext-worker:$VERSION + - name: "Build ERPNext nginx + static assets (v12)" + if: branch = master AND type != pull_request + script: + - git clone https://github.com/frappe/erpnext --branch version-12 + - cd erpnext + - git fetch --tags + - export VERSION=$(git tag --list --sort=-version:refname "v12*" | sed -n 1p | sed -e 's#.*@\(\)#\1#') + - cd .. + - docker build -t frappe/erpnext-assets:$VERSION -f build/erpnext-assets/v12.Dockerfile . + - docker tag frappe/erpnext-assets:$VERSION frappe/erpnext-assets:version-12 + - docker tag frappe/erpnext-assets:$VERSION frappe/erpnext-assets:v12 + - docker push frappe/erpnext-assets:$VERSION + - name: "Build Frappe socketio service (v12)" + if: branch = master AND type != pull_request + script: + - git clone https://github.com/frappe/frappe --branch version-12 + - cd frappe + - git fetch --tags + - export VERSION=$(git tag --list --sort=-version:refname "v12*" | sed -n 1p | sed -e 's#.*@\(\)#\1#') + - cd .. + - docker build -t frappe/frappe-socketio:$VERSION -f build/frappe-socketio/v12.Dockerfile . + - docker tag frappe/frappe-socketio:$VERSION frappe/frappe-socketio:version-12 + - docker tag frappe/frappe-socketio:$VERSION frappe/frappe-socketio:v12 + - docker push frappe/frappe-socketio:$VERSION + - name: "Build Frappe python environment (v11)" + if: branch = master AND type != pull_request + script: + - git clone https://github.com/frappe/frappe --branch version-11 + - cd frappe + - git fetch --tags + - export VERSION=$(git tag --list --sort=-version:refname "v11*" | sed -n 1p | sed -e 's#.*@\(\)#\1#') + - cd .. + - docker build -t frappe/frappe-worker:$VERSION -f build/frappe-worker/v11.Dockerfile . + - docker tag frappe/frappe-worker:$VERSION frappe/frappe-worker:version-11 + - docker tag frappe/frappe-worker:$VERSION frappe/frappe-worker:v11 + - docker push frappe/frappe-worker:$VERSION + - name: "Build Frappe nginx + static assets (v11)" + if: branch = master AND type != pull_request + script: + - git clone https://github.com/frappe/frappe --branch version-11 + - cd frappe + - git fetch --tags + - export VERSION=$(git tag --list --sort=-version:refname "v11*" | sed -n 1p | sed -e 's#.*@\(\)#\1#') + - cd .. + - docker build -t frappe/frappe-assets:$VERSION -f build/frappe-assets/v11.Dockerfile . + - docker tag frappe/frappe-assets:$VERSION frappe/frappe-assets:version-11 + - docker tag frappe/frappe-assets:$VERSION frappe/frappe-assets:v11 + - docker push frappe/frappe-assets:$VERSION + - name: "Build ERPNext python environment (v11)" + if: branch = master AND type != pull_request + script: + - git clone https://github.com/frappe/erpnext --branch version-11 + - cd erpnext + - git fetch --tags + - export VERSION=$(git tag --list --sort=-version:refname "v11*" | sed -n 1p | sed -e 's#.*@\(\)#\1#') + - cd .. + - docker build -t frappe/erpnext-worker:$VERSION -f build/erpnext-worker/v11.Dockerfile . + - docker tag frappe/erpnext-worker:$VERSION frappe/erpnext-worker:version-11 + - docker tag frappe/erpnext-worker:$VERSION frappe/erpnext-worker:v11 + - docker push frappe/erpnext-worker:$VERSION + - name: "Build ERPNext nginx + static assets (v11)" + if: branch = master AND type != pull_request + script: + - git clone https://github.com/frappe/erpnext --branch version-11 + - cd erpnext + - git fetch --tags + - export VERSION=$(git tag --list --sort=-version:refname "v11*" | sed -n 1p | sed -e 's#.*@\(\)#\1#') + - cd .. + - docker build -t frappe/erpnext-assets:$VERSION -f build/erpnext-assets/v11.Dockerfile . + - docker tag frappe/erpnext-assets:$VERSION frappe/erpnext-assets:version-11 + - docker tag frappe/erpnext-assets:$VERSION frappe/erpnext-assets:v11 + - docker push frappe/erpnext-assets:$VERSION + - name: "Build Frappe socketio service (v11)" + if: branch = master AND type != pull_request + script: + - git clone https://github.com/frappe/frappe --branch version-11 + - cd frappe + - git fetch --tags + - export VERSION=$(git tag --list --sort=-version:refname "v11*" | sed -n 1p | sed -e 's#.*@\(\)#\1#') + - cd .. + - docker build -t frappe/frappe-socketio:$VERSION -f build/frappe-socketio/v11.Dockerfile . + - docker tag frappe/frappe-socketio:$VERSION frappe/frappe-socketio:version-11 + - docker tag frappe/frappe-socketio:$VERSION frappe/frappe-socketio:v11 + - docker push frappe/frappe-socketio:$VERSION diff --git a/README.md b/README.md index b51b0885..611cde45 100644 --- a/README.md +++ b/README.md @@ -1,73 +1,232 @@ -# Frappe on Docker +### Getting Started -[![Build Status](https://travis-ci.com/frappe/frappe_docker.svg)](https://travis-ci.com/frappe/frappe_docker) +The templates in this repository will help deploy Frappe/ERPNext docker in a production environment. -This is a repo designed to aide setting up frappe/ERPNext on docker. +This docker installation takes care of the following: -## Getting Started +* Setting up the desired version of Frappe/ERPNext. +* Setting up all the system requirements: eg. MariaDB, Node, Redis. +* [OPTIONAL] Configuring networking for remote access and setting up LetsEncrypt -These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. +### Installation Process -Unfortunately, this container is not currently suited for a production environment (but we're working towards that goal!). +#### Setting up Pre-requisites -### Build the container and initialize the bench +This repository requires Docker and Git to be setup on the instance to be used. -**Note:** These instructions assume you have both [Docker](https://docs.docker.com/engine/installation) and [Docker Compose](https://docs.docker.com/compose/install/) installed on your system. +#### Setup Letsencrypt Nginx Proxy Companion -1. Clone this repo and change your working directory to it: +This is an optional first step. This step is only required if you want to have SSL setup on your docker instance. - ```bash - git clone https://github.com/frappe/frappe_docker.git - cd frappe_docker/ - ``` +This step also assumes that the DNS is preconfigured since it automatically handles setup and renewal of SSL certificates. -2. Build and start the container, and initialize the bench: +For more details, see: https://github.com/evertramos/docker-compose-letsencrypt-nginx-proxy-companion - ```bash - ./dbench setup docker - ./dbench init - ``` +To setup the proxy companion, run the following steps: - **Note:** This will take a while, as docker will now build the container. +```sh +cd $HOME +git clone https://github.com/evertramos/docker-compose-letsencrypt-nginx-proxy-companion.git +cd docker-compose-letsencrypt-nginx-proxy-companion +cp .env.sample .env +./start.sh +``` -3. Add a new site and start Frappe: +#### Setting up Frappe/ERPNext Docker - ```bash - ./dbench new-site site1.local - ./dbench setup hosts - ./dbench start - ``` +Clone this repository somewhere in your system: -4. Use Frappe: - Open your browser to `localhost:8000/login`. Then log in using the username `Administrator` and the password `admin`. +```sh +git clone https://github.com/frappe/frappe_docker.git +cd frappe_docker +``` -### Basic Usage of `./dbench` +Copy the example docker environment file to `.env`: -**IMPORTANT: Always make sure that your current directory is the root directory of the repo (i.e. `frappe_docker/`)** +``` +cp installation/env-example installation/.env +``` -- `./dbench`: Launches you into an interactive shell in the container as the user `frappe`. +Make a directory for sites: -- `./dbench setup docker [ stop | down ]`: Starts and builds the docker containers using `docker-compose up -d`. - - `stop`: Stops the containers with `docker-compose stop`. - - `down`: Deletes the containers and the corresponding volumes with `docker-compose down`. +```sh +mkdir installation/sites +``` -- `./dbench setup hosts`: Adds all sites to the containers hosts file. - **Note:** Run this after you've added a new site to avoid errors. +#### Setup Environment Variables -- `./dbench -c frappe | root `: Runs a command in the container, as the selected user. +Docker allows passing an environment file to aide in setting up containers, which is used by this repository to pass secret and variable data. -- `./dbench -h`: Shows this help message. +To get started, copy the existing `env-example` file to `.env` inside the `installation` directory. By default, the file will contain the following variables: -- `./dbench `: Runs a command in bench (i.e. Running `./dbench new-site site1.local`, will run `bench new-site site1.local` in the container). +- `VERSION=edge` + - In this case, `edge` corresponds to `develop`. To setup any other version, you may use the branch name or version specific tags. (eg. version-12, v11.1.15, v11) +- `MYSQL_ROOT_PASSWORD=admin` + - Bootstraps a MariaDB container with this value set as the root password. If a managed MariaDB instance is to be used, there is no need to set the password here. +- `MARIADB_HOST=mariadb` + - Sets the hostname to `mariadb`. This is required if the database is managed with the containerized MariaDB instance. + - In case of a separately managed database setup, set the value to the database's hostname/IP/domain. +- `SITES=site1.domain.com,site2.domain.com` + - List of sites that are part of the deployment "bench". Each site is separated by a comma(,). + - If LetsEncrypt is being setup, make sure that the DNS for all the site domains are pointing to the current instance. +- `LETSENCRYPT_EMAIL=your.email@your.domain.com` + - Email for LetsEncrypt expiry notification. This is only required if you are setting up the nginx proxy companion. -## For More Info +#### Start Frappe/ERPNext Services -For more info on building this docker container refer to this [Wiki](https://github.com/frappe/frappe_docker/wiki/Hitchhiker's-guide-to-building-this-frappe_docker-image) +To start the Frappe/ERPNext services, run the following command: -## Contributing +```sh +docker-compose \ + --project-name \ + -f installation/docker-compose-common.yml \ + -f installation/docker-compose-erpnext.yml \ + -f installation/docker-compose-networks.yml \ + --project-directory installation up -d +``` -Feel free to contribute to this project and make it better. +Make sure to replace `` with any desired name you wish to set for the project. -## License +Note: use `docker-compose-frappe.yml` in case you need bench with just frappe installed. -This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details +#### Setup New Sites + +Note: + +- Wait for the mariadb service to start before trying to create a new site. + - If new site creation fails, retry after the mariadb container is up and running. + - If you're using a managed database instance, make sure that the database is running before setting up a new site. +- Use `.env` file or environment variables instead of passing secrets as command arguments. + +```sh +# Create ERPNext site +docker exec -it \ + -e "SITE_NAME=$SITE_NAME" \ + -e "DB_ROOT_USER=$DB_ROOT_USER" \ + -e "MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD" \ + -e "ADMIN_PASSWORD=$ADMIN_PASSWORD" \ + -e "INSTALL_ERPNEXT=1" \ + _erpnext-python_1 docker-entrypoint.sh new +``` + +Environment Variables needed: + +- `SITE_NAME`: name of the new site to create. +- `DB_ROOT_USER`: MariaDB Root user. The user that can create databases. +- `MYSQL_ROOT_PASSWORD`: In case of mariadb docker container use the one set in `MYSQL_ROOT_PASSWORD` in previous steps. In case of managed database use appropriate password. +- `ADMIN_PASSWORD`: set the administrator password for new site. +- `INSTALL_ERPNEXT=1`: available only in erpnext-worker and erpnext containers. Installs ERPNext on this new site. +- `FORCE=1`: is optional variable which force installs the same site. + +#### Backup Sites + +Environment Variables + +- `SITES` is list of sites separated by (:) colon to migrate. e.g. `SITES=site1.domain.com` or `SITES=site1.domain.com:site2.domain.com` By default all sites in bench will be backed up. +- `WITH_FILES` if set to 1, it will backup user uploaded files for the sites. + +```sh +docker exec -it \ + -e "SITES=site1.domain.com:site2.domain.com" \ + -e "WITH_FILES=1" \ + _erpnext-python_1 docker-entrypoint.sh backup +``` + +Backup will be available in the `sites` mounted volume. + +#### Updating and Migrating Sites + +Switch to the root of the `frappe_docker` directory before running the following commands: + +```sh +# Update environment variable VERSION +nano .env + +# Pull new images +docker-compose \ + -f installation/docker-compose-common.yml \ + -f installation/docker-compose-erpnext.yml \ + pull + +# Restart containers +docker-compose \ + --project-name \ + -f installation/docker-compose-common.yml \ + -f installation/docker-compose-erpnext.yml \ + -f installation/docker-compose-networks.yml \ + --project-directory installation up -d + +docker exec -it \ + -e "MAINTENANCE_MODE=1" \ + _erpnext-python_1 docker-entrypoint.sh migrate +``` + +### Troubleshoot + +1. Remove containers and volumes, and clear redis cache: + +This can be used when existing images are upgraded and migration fails. + +``` +# change to repo root +cd $HOME/frappe_docker + +# Stop all bench containers +docker-compose \ + --project-name \ + -f installation/docker-compose-common.yml \ + -f installation/docker-compose-erpnext.yml \ + -f installation/docker-compose-networks.yml \ + --project-directory installation stop + +# Remove redis containers +docker-compose \ + --project-name \ + -f installation/docker-compose-common.yml \ + -f installation/docker-compose-erpnext.yml \ + -f installation/docker-compose-networks.yml \ + --project-directory installation rm redis-cache redis-queue redis-socketio + +# Clean redis volumes +docker volume rm \ + _redis-cache-vol \ + _redis-queue-vol \ + _redis-socketio-vol + +# Restart project +docker-compose \ + --project-name \ + -f installation/docker-compose-common.yml \ + -f installation/docker-compose-erpnext.yml \ + -f installation/docker-compose-networks.yml \ + --project-directory installation up -d +``` + +2. Clear redis cache using `docker exec` command: + +In case of following error during container restarts: + +``` +frappe-worker-short_1 | Traceback (most recent call last): +frappe-worker-short_1 | File "/home/frappe/frappe-bench/commands/worker.py", line 5, in +frappe-worker-short_1 | start_worker(queue, False) +frappe-worker-short_1 | File "/home/frappe/frappe-bench/apps/frappe/frappe/utils/background_jobs.py", line 147, in start_worker +frappe-worker-short_1 | Worker(queues, name=get_worker_name(queue)).work(logging_level = logging_level) +frappe-worker-short_1 | File "/home/frappe/frappe-bench/env/lib/python3.7/site-packages/rq/worker.py", line 474, in work +frappe-worker-short_1 | self.register_birth() +frappe-worker-short_1 | File "/home/frappe/frappe-bench/env/lib/python3.7/site-packages/rq/worker.py", line 261, in register_birth +frappe-worker-short_1 | raise ValueError(msg.format(self.name)) +frappe-worker-short_1 | ValueError: There exists an active worker named '8dfe5c234085.10.short' already +``` + +Use commands : + +```sh +# Clear the cache which is causing problem. + +docker exec -it _redis-cache_1 redis-cli FLUSHALL +docker exec -it _redis-queue_1 redis-cli FLUSHALL +docker exec -it _redis-socketio_1 redis-cli FLUSHALL +``` + +Note: Environment variables from `.env` file located at current working directory will be used. diff --git a/build/common/commands/background.py b/build/common/commands/background.py new file mode 100644 index 00000000..7065efd9 --- /dev/null +++ b/build/common/commands/background.py @@ -0,0 +1,7 @@ +import frappe +from frappe.utils.scheduler import start_scheduler + +print("Starting background scheduler . . .") +start_scheduler() + +exit(0) diff --git a/build/common/commands/backup.py b/build/common/commands/backup.py new file mode 100644 index 00000000..e6fbcbb6 --- /dev/null +++ b/build/common/commands/backup.py @@ -0,0 +1,29 @@ +import os, frappe, compileall, re +from frappe.utils.backups import scheduled_backup +from frappe.utils import now +from frappe.utils import get_sites + +def backup(sites, with_files=False): + for site in sites: + frappe.init(site) + frappe.connect() + odb = scheduled_backup( + ignore_files=not with_files, + backup_path_db=None, + backup_path_files=None, + backup_path_private_files=None, + force=True + ) + print("database backup taken -", odb.backup_path_db, "- on", now()) + if with_files: + print("files backup taken -", odb.backup_path_files, "- on", now()) + print("private files backup taken -", odb.backup_path_private_files, "- on", now()) + frappe.destroy() + +installed_sites = ":".join(get_sites()) +sites = os.environ.get("SITES", installed_sites).split(":") +with_files=True if os.environ.get("WITH_FILES") else False + +backup(sites, with_files) + +exit(0) diff --git a/build/common/commands/check_connection.py b/build/common/commands/check_connection.py new file mode 100644 index 00000000..abe17199 --- /dev/null +++ b/build/common/commands/check_connection.py @@ -0,0 +1,67 @@ +import socket, os, json, time +from six.moves.urllib.parse import urlparse + +def is_open(ip, port, timeout=30): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(timeout) + try: + s.connect((ip, int(port))) + s.shutdown(socket.SHUT_RDWR) + return True + except: + return False + finally: + s.close() + +def check_host(ip, port, retry=10, delay=3): + ipup = False + for i in range(retry): + print("Attempt {i} to connect to {ip}:{port}".format(ip=ip,port=port,i=i+1)) + if is_open(ip, port): + ipup = True + break + else: + time.sleep(delay) + return ipup + +# Check connection to servers +config = None +try: + with open('common_site_config.json') as config_file: + config = json.load(config_file) +except FileNotFoundError: + raise FileNotFoundError("common_site_config.json missing") +except: + raise ValueError("common_site_config.json is not valid") + +# Check mariadb +check_mariadb = False +check_mariadb = check_host(config.get('db_host', 'mariadb'), 3306) +if not check_mariadb: + raise ConnectionError("Connection to mariadb timed out") + +# Check redis queue +check_redis_queue = False +redis_queue_url = urlparse(config.get("redis_queue","redis://redis:6379")).netloc +redis_queue, redis_queue_port = redis_queue_url.split(":") +check_redis_queue = check_host(redis_queue, redis_queue_port) +if not check_redis_queue: + raise ConnectionError("Connection to redis queue timed out") + +# Check redis cache +check_redis_cache = False +redis_cache_url = urlparse(config.get("redis_cache","redis://redis:6379")).netloc +redis_cache, redis_cache_port = redis_cache_url.split(":") +check_redis_cache = check_host(redis_cache, redis_cache_port) +if not check_redis_cache: + raise ConnectionError("Connection to redis cache timed out") + +# Check redis socketio +check_redis_socketio = False +redis_socketio_url = urlparse(config.get("redis_socketio","redis://redis:6379")).netloc +redis_socketio, redis_socketio_port = redis_socketio_url.split(":") +check_redis_socketio = check_host(redis_socketio, redis_socketio_port) +if not check_redis_socketio: + raise ConnectionError("Connection to redis socketio timed out") + +print('Connections OK') diff --git a/build/common/commands/console.py b/build/common/commands/console.py new file mode 100644 index 00000000..20b3fd34 --- /dev/null +++ b/build/common/commands/console.py @@ -0,0 +1,25 @@ +import sys +import frappe +import IPython + +from frappe.utils import get_sites + + +def console(site): + "Start ipython console for a site" + if site not in get_sites(): + print("Site {0} does not exist on the current bench".format(site)) + return + + frappe.init(site=site) + frappe.connect() + frappe.local.lang = frappe.db.get_default("lang") + all_apps = frappe.get_installed_apps() + for app in all_apps: + locals()[app] = __import__(app) + print("Apps in this namespace:\n{}".format(", ".join(all_apps))) + IPython.embed(display_banner="", header="") + + +site = sys.argv[-1] +console(site) diff --git a/build/common/commands/doctor.py b/build/common/commands/doctor.py new file mode 100644 index 00000000..54f508fb --- /dev/null +++ b/build/common/commands/doctor.py @@ -0,0 +1,4 @@ +import frappe +from frappe.utils.doctor import doctor + +doctor() diff --git a/build/common/commands/migrate.py b/build/common/commands/migrate.py new file mode 100644 index 00000000..be382bea --- /dev/null +++ b/build/common/commands/migrate.py @@ -0,0 +1,47 @@ +import os, frappe, compileall, re, json + +from frappe.migrate import migrate +from frappe.utils import get_sites + +def get_config(): + config = None + with open('common_site_config.json') as config_file: + config = json.load(config_file) + return config + +def save_config(config): + with open('common_site_config.json', 'w') as f: + return json.dump(config, f, indent=1, sort_keys=True) + +def set_maintenance_mode(enable=True): + conf = get_config() + + if enable: + conf.update({ "maintenance_mode": 1, "pause_scheduler": 1 }) + save_config(conf) + + if not enable: + conf.update({ "maintenance_mode": 0, "pause_scheduler": 0 }) + save_config(conf) + + +installed_sites = ":".join(get_sites()) +sites = os.environ.get("SITES", installed_sites).split(":") +maintenance_mode = True if os.environ.get("MAINTENANCE_MODE") else False + +if maintenance_mode: + set_maintenance_mode(True) + +for site in sites: + print('Migrating', site) + frappe.init(site=site) + frappe.connect() + try: + migrate() + finally: + frappe.destroy() + +if maintenance_mode: + set_maintenance_mode(False) + +exit(0) diff --git a/build/common/commands/new.py b/build/common/commands/new.py new file mode 100644 index 00000000..b87641db --- /dev/null +++ b/build/common/commands/new.py @@ -0,0 +1,67 @@ +import os, frappe, json + +from frappe.commands.site import _new_site + +site_name = os.environ.get("SITE_NAME", 'site1.localhost') +mariadb_root_username = os.environ.get("DB_ROOT_USER", 'root') +mariadb_root_password = os.environ.get("MYSQL_ROOT_PASSWORD", 'admin') +force = True if os.environ.get("FORCE", None) else False +install_apps = ['erpnext'] if os.environ.get("INSTALL_ERPNEXT", None) else False +frappe.init(site_name, new_site=True) + +_new_site( + None, + site_name, + mariadb_root_username=mariadb_root_username, + mariadb_root_password=mariadb_root_password, + admin_password=os.environ.get("ADMIN_PASSWORD", 'admin'), + verbose=True, + install_apps=install_apps, + source_sql=None, + force=force, + reinstall=False, +) + +config = None +with open('common_site_config.json') as config_file: + config = json.load(config_file) + +site_config = None +with open('{site_name}/site_config.json'.format(site_name=site_name)) as site_config_file: + site_config = json.load(site_config_file) + +# update User's host to '%' required to connect from any container +command = 'mysql -h{db_host} -u{mariadb_root_username} -p{mariadb_root_password} -e '.format( + db_host=config.get('db_host'), + mariadb_root_username=mariadb_root_username, + mariadb_root_password=mariadb_root_password +) +command += "\"UPDATE mysql.user SET Host = '%' where User = '{db_name}'; FLUSH PRIVILEGES;\"".format( + db_name=site_config.get('db_name') +) +os.system(command) + +# Set db password +command = 'mysql -h{db_host} -u{mariadb_root_username} -p{mariadb_root_password} -e '.format( + db_host=config.get('db_host'), + mariadb_root_username=mariadb_root_username, + mariadb_root_password=mariadb_root_password +) +command += "\"SET PASSWORD FOR '{db_name}'@'%' = PASSWORD('{db_password}'); FLUSH PRIVILEGES;\"".format( + db_name=site_config.get('db_name'), + db_password=site_config.get('db_password') +) +os.system(command) + +# Grant permission to database +command = 'mysql -h{db_host} -u{mariadb_root_username} -p{mariadb_root_password} -e '.format( + db_host=config.get('db_host'), + mariadb_root_username=mariadb_root_username, + mariadb_root_password=mariadb_root_password +) +command += "\"GRANT ALL PRIVILEGES ON \`{db_name}\`.* TO '{db_name}'@'%'; FLUSH PRIVILEGES;\"".format( + db_name=site_config.get('db_name') +) +os.system(command) + +exit(0) diff --git a/build/common/commands/worker.py b/build/common/commands/worker.py new file mode 100644 index 00000000..6ec0bcbf --- /dev/null +++ b/build/common/commands/worker.py @@ -0,0 +1,7 @@ +import os, frappe +from frappe.utils.background_jobs import start_worker + +queue = os.environ.get("WORKER_TYPE", "default") +start_worker(queue, False) + +exit(0) diff --git a/build/common/common_site_config.json.template b/build/common/common_site_config.json.template new file mode 100755 index 00000000..27593289 --- /dev/null +++ b/build/common/common_site_config.json.template @@ -0,0 +1,7 @@ +{ + "db_host": "${MARIADB_HOST}", + "redis_cache": "redis://${REDIS_CACHE}", + "redis_queue": "redis://${REDIS_QUEUE}", + "redis_socketio": "redis://${REDIS_SOCKETIO}", + "socketio_port": ${SOCKETIO_PORT} +} diff --git a/build/common/nginx-default.conf.template b/build/common/nginx-default.conf.template new file mode 100644 index 00000000..b9fc161a --- /dev/null +++ b/build/common/nginx-default.conf.template @@ -0,0 +1,90 @@ +upstream frappe-server { + server ${FRAPPE_PY}:${FRAPPE_PY_PORT} fail_timeout=0; +} + +upstream socketio-server { + server ${FRAPPE_SOCKETIO}:${SOCKETIO_PORT} fail_timeout=0; +} + +server { + listen 80; + server_name $http_host; + root /var/www/html; + + location /assets { + try_files $uri =404; + } + + location ~ ^/protected/(.*) { + internal; + try_files /sites/$http_host/$1 =404; + } + + location /socket.io { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header X-Frappe-Site-Name $http_host; + proxy_set_header Origin $scheme://$http_host; + proxy_set_header Host $host; + + proxy_pass http://socketio-server; + } + + location / { + try_files /sites/$http_host/public/$uri @webserver; + } + + location @webserver { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Frappe-Site-Name $http_host; + proxy_set_header Host $host; + proxy_set_header X-Use-X-Accel-Redirect True; + proxy_read_timeout 120; + proxy_redirect off; + + proxy_pass http://frappe-server; + } + + # error pages + error_page 502 /502.html; + location /502.html { + root /var/www/templates; + internal; + } + + # optimizations + sendfile on; + keepalive_timeout 15; + client_max_body_size 50m; + client_body_buffer_size 16K; + client_header_buffer_size 1k; + + # enable gzip compresion + # based on https://mattstauffer.co/blog/enabling-gzip-on-nginx-servers-including-laravel-forge + gzip on; + gzip_http_version 1.1; + gzip_comp_level 5; + gzip_min_length 256; + gzip_proxied any; + gzip_vary on; + gzip_types + application/atom+xml + application/javascript + application/json + application/rss+xml + application/vnd.ms-fontobject + application/x-font-ttf + application/font-woff + application/x-web-app-manifest+json + application/xhtml+xml + application/xml + font/opentype + image/svg+xml + image/x-icon + text/css + text/plain + text/x-component; + # text/html is always compressed by HttpGzipModule +} diff --git a/build/common/worker/docker-entrypoint.sh b/build/common/worker/docker-entrypoint.sh new file mode 100755 index 00000000..bf8a90c2 --- /dev/null +++ b/build/common/worker/docker-entrypoint.sh @@ -0,0 +1,178 @@ +#!/bin/bash + +function configureEnv() { + if [ ! -f /home/frappe/frappe-bench/sites/common_site_config.json ]; then + + if [[ -z "$MARIADB_HOST" ]]; then + echo "MARIADB_HOST is not set" + exit 1 + fi + + if [[ -z "$REDIS_CACHE" ]]; then + echo "REDIS_CACHE is not set" + exit 1 + fi + + if [[ -z "$REDIS_QUEUE" ]]; then + echo "REDIS_QUEUE is not set" + exit 1 + fi + + if [[ -z "$REDIS_SOCKETIO" ]]; then + echo "REDIS_SOCKETIO is not set" + exit 1 + fi + + if [[ -z "$SOCKETIO_PORT" ]]; then + echo "SOCKETIO_PORT is not set" + exit 1 + fi + + envsubst '${MARIADB_HOST} + ${REDIS_CACHE} + ${REDIS_QUEUE} + ${REDIS_SOCKETIO} + ${SOCKETIO_PORT}' < /opt/frappe/common_site_config.json.template > /home/frappe/frappe-bench/sites/common_site_config.json + fi +} + +function checkConnection() { + su frappe -c ". /home/frappe/frappe-bench/env/bin/activate \ + && python /home/frappe/frappe-bench/commands/check_connection.py" +} + +function checkConfigExists() { + COUNTER=0 + while [[ ! -e /home/frappe/frappe-bench/sites/common_site_config.json ]] && [[ $COUNTER -le 30 ]] ; do + sleep 1 + (( COUNTER=COUNTER+1 )) + echo "config file not created, retry $COUNTER" + done + + if [[ ! -e /home/frappe/frappe-bench/sites/common_site_config.json ]]; then + echo "timeout: config file not created" + exit 1 + fi +} + +if [[ ! -e /home/frappe/frappe-bench/sites/apps.txt ]]; then + find /home/frappe/frappe-bench/apps -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | sort -r > /home/frappe/frappe-bench/sites/apps.txt +fi + +# Allow user process to create files in logs directory +chown -R frappe:frappe /home/frappe/frappe-bench/logs + +if [ "$1" = 'start' ]; then + configureEnv + checkConnection + + chown frappe:frappe /home/frappe/frappe-bench/sites/common_site_config.json + + if [[ -z "$WORKERS" ]]; then + export WORKERS=2 + fi + + if [[ -z "$FRAPPE_PORT" ]]; then + export FRAPPE_PORT=8000 + fi + + + if [[ -z "$RUN_AS_ROOT" ]]; then + su frappe -c ". /home/frappe/frappe-bench/env/bin/activate \ + && gunicorn -b 0.0.0.0:$FRAPPE_PORT \ + --worker-tmp-dir /dev/shm \ + --threads=4 \ + --workers $WORKERS \ + --worker-class=gthread \ + --log-file=- \ + -t 120 frappe.app:application --preload" + else + . /home/frappe/frappe-bench/env/bin/activate + gunicorn -b 0.0.0.0:$FRAPPE_PORT \ + --worker-tmp-dir /dev/shm \ + --threads=4 \ + --workers $WORKERS \ + --worker-class=gthread \ + --log-file=- \ + -t 120 frappe.app:application --preload + fi + +elif [ "$1" = 'worker' ]; then + checkConfigExists + checkConnection + # default WORKER_TYPE=default + if [[ -z "$RUN_AS_ROOT" ]]; then + su frappe -c ". /home/frappe/frappe-bench/env/bin/activate \ + && python /home/frappe/frappe-bench/commands/worker.py" + else + . /home/frappe/frappe-bench/env/bin/activate + python /home/frappe/frappe-bench/commands/worker.py + fi + +elif [ "$1" = 'schedule' ]; then + checkConfigExists + checkConnection + if [[ -z "$RUN_AS_ROOT" ]]; then + su frappe -c ". /home/frappe/frappe-bench/env/bin/activate \ + && python /home/frappe/frappe-bench/commands/background.py" + else + . /home/frappe/frappe-bench/env/bin/activate + python /home/frappe/frappe-bench/commands/background.py + fi + +elif [ "$1" = 'new' ]; then + + if [[ -z "$RUN_AS_ROOT" ]]; then + su frappe -c ". /home/frappe/frappe-bench/env/bin/activate \ + && python /home/frappe/frappe-bench/commands/new.py" + exit + else + . /home/frappe/frappe-bench/env/bin/activate + python /home/frappe/frappe-bench/commands/new.py + fi + +elif [ "$1" = 'migrate' ]; then + + su frappe -c ". /home/frappe/frappe-bench/env/bin/activate \ + && python /home/frappe/frappe-bench/commands/migrate.py" + exit + +elif [ "$1" = 'doctor' ]; then + + su frappe -c ". /home/frappe/frappe-bench/env/bin/activate \ + && python /home/frappe/frappe-bench/commands/doctor.py" + exit + +elif [ "$1" = 'backup' ]; then + + if [[ -z "$RUN_AS_ROOT" ]]; then + su frappe -c ". /home/frappe/frappe-bench/env/bin/activate \ + && python /home/frappe/frappe-bench/commands/backup.py" + exit + else + . /home/frappe/frappe-bench/env/bin/activate + python /home/frappe/frappe-bench/commands/backup.py + fi + +elif [ "$1" = 'console' ]; then + + if [[ -z "$2" ]]; then + echo "Need to specify a sitename with the command:" + echo "console " + exit 1 + fi + + if [[ -z "$RUN_AS_ROOT" ]]; then + su frappe -c ". /home/frappe/frappe-bench/env/bin/activate \ + && python /home/frappe/frappe-bench/commands/console.py $2" + exit + else + . /home/frappe/frappe-bench/env/bin/activate + python /home/frappe/frappe-bench/commands/console.py "$2" + fi + +else + + exec su frappe -c "$@" + +fi diff --git a/build/erpnext-assets/Dockerfile b/build/erpnext-assets/Dockerfile new file mode 100644 index 00000000..7fcb2b20 --- /dev/null +++ b/build/erpnext-assets/Dockerfile @@ -0,0 +1,40 @@ +FROM bitnami/node:12-prod + +WORKDIR /home/frappe/frappe-bench +RUN mkdir -p /home/frappe/frappe-bench/sites \ + && echo "frappe\nerpnext" > /home/frappe/frappe-bench/sites/apps.txt + +RUN install_packages git python2 + +RUN mkdir -p apps sites/assets \ + && cd apps \ + && git clone --depth 1 https://github.com/frappe/frappe \ + && git clone --depth 1 https://github.com/frappe/erpnext + +RUN cd /home/frappe/frappe-bench/apps/frappe \ + && yarn \ + && yarn run production \ + && rm -fr node_modules \ + && yarn install --production=true + +RUN git clone --depth 1 https://github.com/frappe/bench /tmp/bench \ + && mkdir -p /var/www/error_pages \ + && cp -r /tmp/bench/bench/config/templates/502.html /var/www/error_pages + +RUN cp -R /home/frappe/frappe-bench/apps/frappe/frappe/public/* /home/frappe/frappe-bench/sites/assets/frappe \ + && cp -R /home/frappe/frappe-bench/apps/frappe/node_modules /home/frappe/frappe-bench/sites/assets/frappe/ \ + && mkdir -p /home/frappe/frappe-bench/sites/assets/erpnext \ + && cp -R /home/frappe/frappe-bench/apps/erpnext/erpnext/public/* /home/frappe/frappe-bench/sites/assets/erpnext + +FROM nginx:latest +COPY --from=0 /home/frappe/frappe-bench/sites /var/www/html/ +COPY --from=0 /var/www/error_pages /var/www/ +COPY build/common/nginx-default.conf.template /etc/nginx/conf.d/default.conf.template +COPY build/erpnext-assets/docker-entrypoint.sh / + +RUN apt-get update && apt-get install -y rsync && apt-get clean + +VOLUME [ "/assets" ] + +ENTRYPOINT ["/docker-entrypoint.sh"] +CMD ["nginx", "-g", "daemon off;"] diff --git a/build/erpnext-assets/docker-entrypoint.sh b/build/erpnext-assets/docker-entrypoint.sh new file mode 100755 index 00000000..4919fb34 --- /dev/null +++ b/build/erpnext-assets/docker-entrypoint.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +## Thanks +# https://serverfault.com/a/919212 +## + +set -e + +rsync -a --delete /var/www/html/assets/js /assets +rsync -a --delete /var/www/html/assets/css /assets +rsync -a --delete /var/www/html/assets/frappe /assets +rsync -a --delete /var/www/html/assets/erpnext /assets + +chmod -R 755 /assets + +if [[ -z "$FRAPPE_PY" ]]; then + export FRAPPE_PY=0.0.0.0 +fi + +if [[ -z "$FRAPPE_PY_PORT" ]]; then + export FRAPPE_PY_PORT=8000 +fi + +if [[ -z "$FRAPPE_SOCKETIO" ]]; then + export FRAPPE_SOCKETIO=0.0.0.0 +fi + +if [[ -z "$SOCKETIO_PORT" ]]; then + export SOCKETIO_PORT=9000 +fi + +envsubst '${API_HOST} + ${API_PORT} + ${FRAPPE_PY} + ${FRAPPE_PY_PORT} + ${FRAPPE_SOCKETIO} + ${SOCKETIO_PORT}' \ + < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf + +exec "$@" diff --git a/build/erpnext-assets/v11.Dockerfile b/build/erpnext-assets/v11.Dockerfile new file mode 100644 index 00000000..6db3b415 --- /dev/null +++ b/build/erpnext-assets/v11.Dockerfile @@ -0,0 +1,40 @@ +FROM bitnami/node:10-prod + +WORKDIR /home/frappe/frappe-bench +RUN mkdir -p /home/frappe/frappe-bench/sites \ + && echo "frappe\nerpnext" > /home/frappe/frappe-bench/sites/apps.txt + +RUN install_packages git python2 + +RUN mkdir -p apps sites/assets \ + && cd apps \ + && git clone --depth 1 https://github.com/frappe/frappe --branch version-11 \ + && git clone --depth 1 https://github.com/frappe/erpnext --branch version-11 + +RUN cd /home/frappe/frappe-bench/apps/frappe \ + && yarn \ + && yarn run production \ + && rm -fr node_modules \ + && yarn install --production=true + +RUN git clone --depth 1 https://github.com/frappe/bench /tmp/bench \ + && mkdir -p /var/www/error_pages \ + && cp -r /tmp/bench/bench/config/templates/502.html /var/www/error_pages + +RUN cp -R /home/frappe/frappe-bench/apps/frappe/frappe/public/* /home/frappe/frappe-bench/sites/assets/frappe \ + && cp -R /home/frappe/frappe-bench/apps/frappe/node_modules /home/frappe/frappe-bench/sites/assets/frappe/ \ + && mkdir -p /home/frappe/frappe-bench/sites/assets/erpnext \ + && cp -R /home/frappe/frappe-bench/apps/erpnext/erpnext/public/* /home/frappe/frappe-bench/sites/assets/erpnext + +FROM nginx:latest +COPY --from=0 /home/frappe/frappe-bench/sites /var/www/html/ +COPY --from=0 /var/www/error_pages /var/www/ +COPY build/common/nginx-default.conf.template /etc/nginx/conf.d/default.conf.template +COPY build/erpnext-assets/docker-entrypoint.sh / + +RUN apt-get update && apt-get install -y rsync && apt-get clean + +VOLUME [ "/assets" ] + +ENTRYPOINT ["/docker-entrypoint.sh"] +CMD ["nginx", "-g", "daemon off;"] diff --git a/build/erpnext-assets/v12.Dockerfile b/build/erpnext-assets/v12.Dockerfile new file mode 100644 index 00000000..85dac5ac --- /dev/null +++ b/build/erpnext-assets/v12.Dockerfile @@ -0,0 +1,40 @@ +FROM bitnami/node:12-prod + +WORKDIR /home/frappe/frappe-bench +RUN mkdir -p /home/frappe/frappe-bench/sites \ + && echo "frappe\nerpnext" > /home/frappe/frappe-bench/sites/apps.txt + +RUN install_packages git python2 + +RUN mkdir -p apps sites/assets \ + && cd apps \ + && git clone --depth 1 https://github.com/frappe/frappe --branch version-12 \ + && git clone --depth 1 https://github.com/frappe/erpnext --branch version-12 + +RUN cd /home/frappe/frappe-bench/apps/frappe \ + && yarn \ + && yarn run production \ + && rm -fr node_modules \ + && yarn install --production=true + +RUN git clone --depth 1 https://github.com/frappe/bench /tmp/bench \ + && mkdir -p /var/www/error_pages \ + && cp -r /tmp/bench/bench/config/templates/502.html /var/www/error_pages + +RUN cp -R /home/frappe/frappe-bench/apps/frappe/frappe/public/* /home/frappe/frappe-bench/sites/assets/frappe \ + && cp -R /home/frappe/frappe-bench/apps/frappe/node_modules /home/frappe/frappe-bench/sites/assets/frappe/ \ + && mkdir -p /home/frappe/frappe-bench/sites/assets/erpnext \ + && cp -R /home/frappe/frappe-bench/apps/erpnext/erpnext/public/* /home/frappe/frappe-bench/sites/assets/erpnext + +FROM nginx:latest +COPY --from=0 /home/frappe/frappe-bench/sites /var/www/html/ +COPY --from=0 /var/www/error_pages /var/www/ +COPY build/erpnext-assets/nginx-default.conf.template /etc/nginx/conf.d/default.conf.template +COPY build/common/docker-entrypoint.sh / + +RUN apt-get update && apt-get install -y rsync && apt-get clean + +VOLUME [ "/assets" ] + +ENTRYPOINT ["/docker-entrypoint.sh"] +CMD ["nginx", "-g", "daemon off;"] diff --git a/build/erpnext-worker/Dockerfile b/build/erpnext-worker/Dockerfile new file mode 100644 index 00000000..6d145d8c --- /dev/null +++ b/build/erpnext-worker/Dockerfile @@ -0,0 +1,44 @@ +FROM bitnami/python:latest-prod + +RUN useradd -ms /bin/bash frappe +WORKDIR /home/frappe/frappe-bench +RUN install_packages \ + git \ + wkhtmltopdf \ + mariadb-client \ + gettext-base \ + wget \ + # for PDF + libssl-dev \ + fonts-cantarell \ + xfonts-75dpi \ + xfonts-base \ + # For psycopg2 + libpq-dev \ + build-essential + +# Install wkhtmltox correctly +RUN wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.stretch_amd64.deb +RUN dpkg -i wkhtmltox_0.12.5-1.stretch_amd64.deb && rm wkhtmltox_0.12.5-1.stretch_amd64.deb + +RUN mkdir -p apps logs commands + +RUN virtualenv env \ + && . env/bin/activate \ + && cd apps \ + && git clone --depth 1 -o upstream https://github.com/frappe/frappe \ + && git clone --depth 1 -o upstream https://github.com/frappe/erpnext \ + && pip3 install --no-cache-dir -e /home/frappe/frappe-bench/apps/frappe \ + && pip3 install --no-cache-dir -e /home/frappe/frappe-bench/apps/erpnext + +COPY build/common/commands/* /home/frappe/frappe-bench/commands/ +COPY build/common/common_site_config.json.template /opt/frappe/common_site_config.json.template + +# Setup docker-entrypoint +COPY build/common/worker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN ln -s /usr/local/bin/docker-entrypoint.sh / # backwards compat + +WORKDIR /home/frappe/frappe-bench/sites + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["start"] diff --git a/build/erpnext-worker/v11.Dockerfile b/build/erpnext-worker/v11.Dockerfile new file mode 100644 index 00000000..81a59b63 --- /dev/null +++ b/build/erpnext-worker/v11.Dockerfile @@ -0,0 +1,41 @@ +FROM bitnami/python:latest-prod + +RUN useradd -ms /bin/bash frappe +WORKDIR /home/frappe/frappe-bench +RUN install_packages \ + git \ + wkhtmltopdf \ + mariadb-client \ + gettext-base \ + wget \ + # for PDF + libssl-dev \ + fonts-cantarell \ + xfonts-75dpi \ + xfonts-base + +# Install wkhtmltox correctly +RUN wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.stretch_amd64.deb +RUN dpkg -i wkhtmltox_0.12.5-1.stretch_amd64.deb && rm wkhtmltox_0.12.5-1.stretch_amd64.deb + +RUN mkdir -p apps logs commands + +RUN virtualenv env \ + && . env/bin/activate \ + && cd apps \ + && git clone --depth 1 -o upstream https://github.com/frappe/frappe --branch version-11 \ + && git clone --depth 1 -o upstream https://github.com/frappe/erpnext --branch version-11 \ + && pip3 install --no-cache-dir -e /home/frappe/frappe-bench/apps/frappe \ + && pip3 install --no-cache-dir -e /home/frappe/frappe-bench/apps/erpnext + +COPY build/common/commands/* /home/frappe/frappe-bench/commands/ +COPY build/common/common_site_config.json.template /opt/frappe/common_site_config.json.template + +# Setup docker-entrypoint +COPY build/common/worker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN ln -s /usr/local/bin/docker-entrypoint.sh / # backwards compat + +WORKDIR /home/frappe/frappe-bench/sites + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["start"] diff --git a/build/erpnext-worker/v12.Dockerfile b/build/erpnext-worker/v12.Dockerfile new file mode 100644 index 00000000..3945142a --- /dev/null +++ b/build/erpnext-worker/v12.Dockerfile @@ -0,0 +1,44 @@ +FROM bitnami/python:latest-prod + +RUN useradd -ms /bin/bash frappe +WORKDIR /home/frappe/frappe-bench +RUN install_packages \ + git \ + wkhtmltopdf \ + mariadb-client \ + gettext-base \ + wget \ + # for PDF + libssl-dev \ + fonts-cantarell \ + xfonts-75dpi \ + xfonts-base \ + # For psycopg2 + libpq-dev \ + build-essential + +# Install wkhtmltox correctly +RUN wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.stretch_amd64.deb +RUN dpkg -i wkhtmltox_0.12.5-1.stretch_amd64.deb && rm wkhtmltox_0.12.5-1.stretch_amd64.deb + +RUN mkdir -p apps logs commands + +RUN virtualenv env \ + && . env/bin/activate \ + && cd apps \ + && git clone --depth 1 -o upstream https://github.com/frappe/frappe --branch version-12 \ + && git clone --depth 1 -o upstream https://github.com/frappe/erpnext --branch version-12 \ + && pip3 install --no-cache-dir -e /home/frappe/frappe-bench/apps/frappe \ + && pip3 install --no-cache-dir -e /home/frappe/frappe-bench/apps/erpnext + +COPY build/common/commands/* /home/frappe/frappe-bench/commands/ +COPY build/common/common_site_config.json.template /opt/frappe/common_site_config.json.template + +# Setup docker-entrypoint +COPY build/common/worker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN ln -s /usr/local/bin/docker-entrypoint.sh / # backwards compat + +WORKDIR /home/frappe/frappe-bench/sites + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["start"] diff --git a/build/frappe-assets/Dockerfile b/build/frappe-assets/Dockerfile new file mode 100644 index 00000000..762e74d1 --- /dev/null +++ b/build/frappe-assets/Dockerfile @@ -0,0 +1,37 @@ +FROM bitnami/node:12-prod + +WORKDIR /home/frappe/frappe-bench +RUN mkdir -p /home/frappe/frappe-bench/sites \ + && echo "frappe" > /home/frappe/frappe-bench/sites/apps.txt + +RUN install_packages git + +RUN mkdir -p apps sites/assets \ + && cd apps \ + && git clone --depth 1 https://github.com/frappe/frappe + +RUN cd /home/frappe/frappe-bench/apps/frappe \ + && yarn \ + && yarn run production \ + && rm -fr node_modules \ + && yarn install --production=true + +RUN git clone --depth 1 https://github.com/frappe/bench /tmp/bench \ + && mkdir -p /var/www/error_pages \ + && cp -r /tmp/bench/bench/config/templates /var/www/error_pages + +RUN cp -R /home/frappe/frappe-bench/apps/frappe/frappe/public/* /home/frappe/frappe-bench/sites/assets/frappe \ + && cp -R /home/frappe/frappe-bench/apps/frappe/node_modules /home/frappe/frappe-bench/sites/assets/frappe/ + +FROM nginx:latest +COPY --from=0 /home/frappe/frappe-bench/sites /var/www/html/ +COPY --from=0 /var/www/error_pages /var/www/ +COPY build/common/nginx-default.conf.template /etc/nginx/conf.d/default.conf.template +COPY build/frappe-assets/docker-entrypoint.sh / + +RUN apt-get update && apt-get install -y rsync && apt-get clean + +VOLUME [ "/assets" ] + +ENTRYPOINT ["/docker-entrypoint.sh"] +CMD ["nginx", "-g", "daemon off;"] diff --git a/build/frappe-assets/docker-entrypoint.sh b/build/frappe-assets/docker-entrypoint.sh new file mode 100755 index 00000000..f68e7fd3 --- /dev/null +++ b/build/frappe-assets/docker-entrypoint.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +## Thanks +# https://serverfault.com/a/919212 +## + +set -e + +rsync -a --delete /var/www/html/assets/js /assets +rsync -a --delete /var/www/html/assets/css /assets +rsync -a --delete /var/www/html/assets/frappe /assets + +chmod -R 755 /assets + +if [[ -z "$FRAPPE_PY" ]]; then + export FRAPPE_PY=0.0.0.0 +fi + +if [[ -z "$FRAPPE_PY_PORT" ]]; then + export FRAPPE_PY_PORT=8000 +fi + +if [[ -z "$FRAPPE_SOCKETIO" ]]; then + export FRAPPE_SOCKETIO=0.0.0.0 +fi + +if [[ -z "$SOCKETIO_PORT" ]]; then + export SOCKETIO_PORT=9000 +fi + +envsubst '${API_HOST} + ${API_PORT} + ${FRAPPE_PY} + ${FRAPPE_PY_PORT} + ${FRAPPE_SOCKETIO} + ${SOCKETIO_PORT}' \ + < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf + +exec "$@" diff --git a/build/frappe-assets/v11.Dockerfile b/build/frappe-assets/v11.Dockerfile new file mode 100644 index 00000000..225243d2 --- /dev/null +++ b/build/frappe-assets/v11.Dockerfile @@ -0,0 +1,37 @@ +FROM bitnami/node:10-prod + +WORKDIR /home/frappe/frappe-bench +RUN mkdir -p /home/frappe/frappe-bench/sites \ + && echo "frappe" > /home/frappe/frappe-bench/sites/apps.txt + +RUN install_packages git + +RUN mkdir -p apps sites/assets \ + && cd apps \ + && git clone --depth 1 https://github.com/frappe/frappe --branch version-11 + +RUN cd /home/frappe/frappe-bench/apps/frappe \ + && yarn \ + && yarn run production \ + && rm -fr node_modules \ + && yarn install --production=true + +RUN git clone --depth 1 https://github.com/frappe/bench /tmp/bench \ + && mkdir -p /var/www/error_pages \ + && cp -r /tmp/bench/bench/config/templates /var/www/error_pages + +RUN cp -R /home/frappe/frappe-bench/apps/frappe/frappe/public/* /home/frappe/frappe-bench/sites/assets/frappe \ + && cp -R /home/frappe/frappe-bench/apps/frappe/node_modules /home/frappe/frappe-bench/sites/assets/frappe/ + +FROM nginx:latest +COPY --from=0 /home/frappe/frappe-bench/sites /var/www/html/ +COPY --from=0 /var/www/error_pages /var/www/ +COPY build/common/nginx-default.conf.template /etc/nginx/conf.d/default.conf.template +COPY build/frappe-assets/docker-entrypoint.sh / + +RUN apt-get update && apt-get install -y rsync && apt-get clean + +VOLUME [ "/assets" ] + +ENTRYPOINT ["/docker-entrypoint.sh"] +CMD ["nginx", "-g", "daemon off;"] diff --git a/build/frappe-assets/v12.Dockerfile b/build/frappe-assets/v12.Dockerfile new file mode 100644 index 00000000..cbbac49b --- /dev/null +++ b/build/frappe-assets/v12.Dockerfile @@ -0,0 +1,37 @@ +FROM bitnami/node:12-prod + +WORKDIR /home/frappe/frappe-bench +RUN mkdir -p /home/frappe/frappe-bench/sites \ + && echo "frappe" > /home/frappe/frappe-bench/sites/apps.txt + +RUN install_packages git + +RUN mkdir -p apps sites/assets \ + && cd apps \ + && git clone --depth 1 https://github.com/frappe/frappe --branch version-12 + +RUN cd /home/frappe/frappe-bench/apps/frappe \ + && yarn \ + && yarn run production \ + && rm -fr node_modules \ + && yarn install --production=true + +RUN git clone --depth 1 https://github.com/frappe/bench /tmp/bench \ + && mkdir -p /var/www/error_pages \ + && cp -r /tmp/bench/bench/config/templates /var/www/error_pages + +RUN cp -R /home/frappe/frappe-bench/apps/frappe/frappe/public/* /home/frappe/frappe-bench/sites/assets/frappe \ + && cp -R /home/frappe/frappe-bench/apps/frappe/node_modules /home/frappe/frappe-bench/sites/assets/frappe/ + +FROM nginx:latest +COPY --from=0 /home/frappe/frappe-bench/sites /var/www/html/ +COPY --from=0 /var/www/error_pages /var/www/ +COPY build/common/nginx-default.conf.template /etc/nginx/conf.d/default.conf.template +COPY build/frappe-assets/docker-entrypoint.sh / + +RUN apt-get update && apt-get install -y rsync && apt-get clean + +VOLUME [ "/assets" ] + +ENTRYPOINT ["/docker-entrypoint.sh"] +CMD ["nginx", "-g", "daemon off;"] diff --git a/build/frappe-socketio/Dockerfile b/build/frappe-socketio/Dockerfile new file mode 100644 index 00000000..a74b0d3e --- /dev/null +++ b/build/frappe-socketio/Dockerfile @@ -0,0 +1,34 @@ +FROM node:slim + +# Install needed packages +RUN apt-get update && apt-get install -y curl && apt-get clean + +RUN useradd -ms /bin/bash frappe + +# Make bench directories +RUN mkdir -p /home/frappe/frappe-bench/sites /home/frappe/frappe-bench/apps/frappe + +COPY build/frappe-socketio/package.json /home/frappe/frappe-bench/apps/frappe + + +# get socketio +RUN cd /home/frappe/frappe-bench/apps/frappe \ + && curl https://raw.githubusercontent.com/frappe/frappe/develop/socketio.js \ + --output /home/frappe/frappe-bench/apps/frappe/socketio.js \ + && curl https://raw.githubusercontent.com/frappe/frappe/develop/node_utils.js \ + --output /home/frappe/frappe-bench/apps/frappe/node_utils.js + +RUN cd /home/frappe/frappe-bench/apps/frappe \ + && npm install --only=production + +COPY build/frappe-socketio/health.js /home/frappe/frappe-bench/apps/frappe/health.js +RUN chown -R frappe:frappe /home/frappe + +# Setup docker-entrypoint +COPY build/frappe-socketio/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN ln -s /usr/local/bin/docker-entrypoint.sh / # backwards compat + +WORKDIR /home/frappe/frappe-bench/sites + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["start"] diff --git a/build/frappe-socketio/docker-entrypoint.sh b/build/frappe-socketio/docker-entrypoint.sh new file mode 100755 index 00000000..600a744c --- /dev/null +++ b/build/frappe-socketio/docker-entrypoint.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +function checkConfigExists() { + COUNTER=0 + while [[ ! -e /home/frappe/frappe-bench/sites/common_site_config.json ]] && [[ $COUNTER -le 30 ]] ; do + sleep 1 + let COUNTER=COUNTER+1 + echo "config file not created, retry $COUNTER" + done + + if [[ ! -e /home/frappe/frappe-bench/sites/common_site_config.json ]]; then + echo "timeout: config file not created" + exit 1 + fi +} + +if [ "$1" = 'start' ]; then + checkConfigExists + su frappe -c "node /home/frappe/frappe-bench/apps/frappe/socketio.js" + +elif [ "$1" = 'doctor' ]; then + + su frappe -c "node /home/frappe/frappe-bench/apps/frappe/health.js" + +else + + exec su frappe -c "$@" + +fi diff --git a/build/frappe-socketio/health.js b/build/frappe-socketio/health.js new file mode 100644 index 00000000..b85981bd --- /dev/null +++ b/build/frappe-socketio/health.js @@ -0,0 +1,19 @@ +var net = require('net'); +var { get_conf } = require('./node_utils'); + +var conf = get_conf(); +var server = ['localhost', conf.socketio_port || 9000]; + +var sock = new net.Socket(); +sock.setTimeout(2500); +sock.on('connect', function() { + console.info(server[0]+':'+server[1]+' is up.'); + sock.destroy(); + process.exit(); +}).on('error', function(e) { + console.error(server[0]+':'+server[1]+' is down: ' + e.message); + process.exit(1); +}).on('timeout', function(e) { + console.error(server[0]+':'+server[1]+' is down: timeout'); + process.exit(1); +}).connect(server[1], server[0]); diff --git a/build/frappe-socketio/package.json b/build/frappe-socketio/package.json new file mode 100644 index 00000000..4f8572d5 --- /dev/null +++ b/build/frappe-socketio/package.json @@ -0,0 +1,17 @@ +{ + "name": "frappe-socketio", + "version": "1.0.0", + "description": "Frappe SocketIO Server", + "main": "socketio.js", + "scripts": { + "start": "node socketio.js" + }, + "author": "Revant Nandgaonkar", + "license": "MIT", + "dependencies": { + "express": "^4.17.1", + "redis": "^2.8.0", + "socket.io": "^2.3.0", + "superagent": "^5.1.0" + } +} diff --git a/build/frappe-socketio/v11.Dockerfile b/build/frappe-socketio/v11.Dockerfile new file mode 100644 index 00000000..fcaac8ac --- /dev/null +++ b/build/frappe-socketio/v11.Dockerfile @@ -0,0 +1,34 @@ +FROM node:slim + +# Install needed packages +RUN apt-get update && apt-get install -y curl && apt-get clean + +RUN useradd -ms /bin/bash frappe + +# Make bench directories +RUN mkdir -p /home/frappe/frappe-bench/sites /home/frappe/frappe-bench/apps/frappe + +COPY build/frappe-socketio/package.json /home/frappe/frappe-bench/apps/frappe + + +# get socketio +RUN cd /home/frappe/frappe-bench/apps/frappe \ + && curl https://raw.githubusercontent.com/frappe/frappe/version-11/socketio.js \ + --output /home/frappe/frappe-bench/apps/frappe/socketio.js \ + && curl https://raw.githubusercontent.com/frappe/frappe/version-11/node_utils.js \ + --output /home/frappe/frappe-bench/apps/frappe/node_utils.js + +RUN cd /home/frappe/frappe-bench/apps/frappe \ + && npm install --only=production + +COPY build/frappe-socketio/health.js /home/frappe/frappe-bench/apps/frappe/health.js +RUN chown -R frappe:frappe /home/frappe + +# Setup docker-entrypoint +COPY build/frappe-socketio/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN ln -s /usr/local/bin/docker-entrypoint.sh / # backwards compat + +WORKDIR /home/frappe/frappe-bench/sites + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["start"] diff --git a/build/frappe-socketio/v12.Dockerfile b/build/frappe-socketio/v12.Dockerfile new file mode 100644 index 00000000..adf536bd --- /dev/null +++ b/build/frappe-socketio/v12.Dockerfile @@ -0,0 +1,34 @@ +FROM node:slim + +# Install needed packages +RUN apt-get update && apt-get install -y curl && apt-get clean + +RUN useradd -ms /bin/bash frappe + +# Make bench directories +RUN mkdir -p /home/frappe/frappe-bench/sites /home/frappe/frappe-bench/apps/frappe + +COPY build/frappe-socketio/package.json /home/frappe/frappe-bench/apps/frappe + + +# get socketio +RUN cd /home/frappe/frappe-bench/apps/frappe \ + && curl https://raw.githubusercontent.com/frappe/frappe/version-12/socketio.js \ + --output /home/frappe/frappe-bench/apps/frappe/socketio.js \ + && curl https://raw.githubusercontent.com/frappe/frappe/version-12/node_utils.js \ + --output /home/frappe/frappe-bench/apps/frappe/node_utils.js + +RUN cd /home/frappe/frappe-bench/apps/frappe \ + && npm install --only=production + +COPY build/frappe-socketio/health.js /home/frappe/frappe-bench/apps/frappe/health.js +RUN chown -R frappe:frappe /home/frappe + +# Setup docker-entrypoint +COPY build/frappe-socketio/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN ln -s /usr/local/bin/docker-entrypoint.sh / # backwards compat + +WORKDIR /home/frappe/frappe-bench/sites + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["start"] diff --git a/build/frappe-worker/Dockerfile b/build/frappe-worker/Dockerfile new file mode 100644 index 00000000..41310b0d --- /dev/null +++ b/build/frappe-worker/Dockerfile @@ -0,0 +1,42 @@ +FROM bitnami/python:latest-prod + +RUN useradd -ms /bin/bash frappe +WORKDIR /home/frappe/frappe-bench +RUN install_packages \ + git \ + wkhtmltopdf \ + mariadb-client \ + gettext-base \ + wget \ + # for PDF + libssl-dev \ + fonts-cantarell \ + xfonts-75dpi \ + xfonts-base \ + # For psycopg2 + libpq-dev \ + build-essential + +# Install wkhtmltox correctly +RUN wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.stretch_amd64.deb +RUN dpkg -i wkhtmltox_0.12.5-1.stretch_amd64.deb && rm wkhtmltox_0.12.5-1.stretch_amd64.deb + +RUN mkdir -p apps logs commands + +RUN virtualenv env \ + && . env/bin/activate \ + && cd apps \ + && git clone --depth 1 -o upstream https://github.com/frappe/frappe \ + && pip3 install --no-cache-dir -e /home/frappe/frappe-bench/apps/frappe + +COPY build/common/commands/* /home/frappe/frappe-bench/commands/ +COPY build/common/common_site_config.json.template /opt/frappe/common_site_config.json.template + +# Setup docker-entrypoint +COPY build/common/worker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN ln -s /usr/local/bin/docker-entrypoint.sh / # backwards compat + +WORKDIR /home/frappe/frappe-bench/sites + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["start"] diff --git a/build/frappe-worker/v11.Dockerfile b/build/frappe-worker/v11.Dockerfile new file mode 100644 index 00000000..fa2f01c5 --- /dev/null +++ b/build/frappe-worker/v11.Dockerfile @@ -0,0 +1,39 @@ +FROM bitnami/python:latest-prod + +RUN useradd -ms /bin/bash frappe +WORKDIR /home/frappe/frappe-bench +RUN install_packages \ + git \ + wkhtmltopdf \ + mariadb-client \ + gettext-base \ + wget \ + # for PDF + libssl-dev \ + fonts-cantarell \ + xfonts-75dpi \ + xfonts-base + +# Install wkhtmltox correctly +RUN wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.stretch_amd64.deb +RUN dpkg -i wkhtmltox_0.12.5-1.stretch_amd64.deb && rm wkhtmltox_0.12.5-1.stretch_amd64.deb + +RUN mkdir -p apps logs commands + +RUN virtualenv env \ + && . env/bin/activate \ + && cd apps \ + && git clone --depth 1 -o upstream https://github.com/frappe/frappe --branch version-11 \ + && pip3 install --no-cache-dir -e /home/frappe/frappe-bench/apps/frappe + +COPY build/common/commands/* /home/frappe/frappe-bench/commands/ +COPY build/common/common_site_config.json.template /opt/frappe/common_site_config.json.template + +# Setup docker-entrypoint +COPY build/common/worker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN ln -s /usr/local/bin/docker-entrypoint.sh / # backwards compat + +WORKDIR /home/frappe/frappe-bench/sites + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["start"] diff --git a/build/frappe-worker/v12.Dockerfile b/build/frappe-worker/v12.Dockerfile new file mode 100644 index 00000000..1eb6d60a --- /dev/null +++ b/build/frappe-worker/v12.Dockerfile @@ -0,0 +1,42 @@ +FROM bitnami/python:latest-prod + +RUN useradd -ms /bin/bash frappe +WORKDIR /home/frappe/frappe-bench +RUN install_packages \ + git \ + wkhtmltopdf \ + mariadb-client \ + gettext-base \ + wget \ + # for PDF + libssl-dev \ + fonts-cantarell \ + xfonts-75dpi \ + xfonts-base \ + # For psycopg2 + libpq-dev \ + build-essential + +# Install wkhtmltox correctly +RUN wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.stretch_amd64.deb +RUN dpkg -i wkhtmltox_0.12.5-1.stretch_amd64.deb && rm wkhtmltox_0.12.5-1.stretch_amd64.deb + +RUN mkdir -p apps logs commands + +RUN virtualenv env \ + && . env/bin/activate \ + && cd apps \ + && git clone --depth 1 -o upstream https://github.com/frappe/frappe --branch version-12 \ + && pip3 install --no-cache-dir -e /home/frappe/frappe-bench/apps/frappe + +COPY build/common/commands/* /home/frappe/frappe-bench/commands/ +COPY build/common/common_site_config.json.template /opt/frappe/common_site_config.json.template + +# Setup docker-entrypoint +COPY build/common/worker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN ln -s /usr/local/bin/docker-entrypoint.sh / # backwards compat + +WORKDIR /home/frappe/frappe-bench/sites + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["start"] diff --git a/installation/docker-compose-common.yml b/installation/docker-compose-common.yml new file mode 100644 index 00000000..ede3abe1 --- /dev/null +++ b/installation/docker-compose-common.yml @@ -0,0 +1,35 @@ +version: '3' + +services: + redis-cache: + image: redis:latest + restart: on-failure + volumes: + - redis-cache-vol:/data + + redis-queue: + image: redis:latest + restart: on-failure + volumes: + - redis-queue-vol:/data + + redis-socketio: + image: redis:latest + restart: on-failure + volumes: + - redis-socketio-vol:/data + + mariadb: + image: mariadb:10.3 + restart: on-failure + environment: + - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} + volumes: + - ./frappe-mariadb.cnf:/etc/mysql/conf.d/frappe.cnf + - mariadb-vol:/var/lib/mysql + +volumes: + mariadb-vol: + redis-cache-vol: + redis-queue-vol: + redis-socketio-vol: diff --git a/installation/docker-compose-erpnext.yml b/installation/docker-compose-erpnext.yml new file mode 100644 index 00000000..93b7c6a1 --- /dev/null +++ b/installation/docker-compose-erpnext.yml @@ -0,0 +1,111 @@ +version: '3' + +services: + erpnext-assets: + image: frappe/erpnext-assets:${VERSION} + restart: on-failure + environment: + - FRAPPE_PY=erpnext-python + - FRAPPE_PY_PORT=8000 + - FRAPPE_SOCKETIO=frappe-socketio + - SOCKETIO_PORT=9000 + - LETSENCRYPT_HOST=${SITES} + - VIRTUAL_HOST=${SITES} + - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL} + depends_on: + - erpnext-python + - frappe-socketio + - frappe-worker-default + - frappe-worker-long + - frappe-worker-short + links: + - erpnext-python + - frappe-socketio + - frappe-worker-default + - frappe-worker-long + - frappe-worker-short + volumes: + - ./sites:/var/www/html/sites:rw + - assets-vol:/assets:rw + + erpnext-python: + image: frappe/erpnext-worker:${VERSION} + restart: on-failure + environment: + - MARIADB_HOST=${MARIADB_HOST} + - REDIS_CACHE=redis-cache:6379 + - REDIS_QUEUE=redis-queue:6379 + - REDIS_SOCKETIO=redis-socketio:6379 + - SOCKETIO_PORT=9000 + volumes: + - ./sites:/home/frappe/frappe-bench/sites:rw + - assets-vol:/home/frappe/frappe-bench/sites/assets:rw + + frappe-socketio: + image: frappe/frappe-socketio:${VERSION} + restart: on-failure + depends_on: + - redis-socketio + links: + - redis-socketio + volumes: + - ./sites:/home/frappe/frappe-bench/sites:rw + + frappe-worker-default: + image: frappe/erpnext-worker:${VERSION} + restart: on-failure + command: worker + depends_on: + - redis-queue + - redis-cache + links: + - redis-queue + - redis-cache + volumes: + - ./sites:/home/frappe/frappe-bench/sites:rw + + frappe-worker-short: + image: frappe/erpnext-worker:${VERSION} + restart: on-failure + command: worker + environment: + - WORKER_TYPE=short + depends_on: + - redis-queue + - redis-cache + links: + - redis-queue + - redis-cache + volumes: + - ./sites:/home/frappe/frappe-bench/sites:rw + + frappe-worker-long: + image: frappe/erpnext-worker:${VERSION} + restart: on-failure + command: worker + environment: + - WORKER_TYPE=long + depends_on: + - redis-queue + - redis-cache + links: + - redis-queue + - redis-cache + volumes: + - ./sites:/home/frappe/frappe-bench/sites:rw + + frappe-schedule: + image: frappe/erpnext-worker:${VERSION} + restart: on-failure + command: schedule + depends_on: + - redis-queue + - redis-cache + links: + - redis-queue + - redis-cache + volumes: + - ./sites:/home/frappe/frappe-bench/sites:rw + +volumes: + assets-vol: diff --git a/installation/docker-compose-frappe.yml b/installation/docker-compose-frappe.yml new file mode 100644 index 00000000..869fb73c --- /dev/null +++ b/installation/docker-compose-frappe.yml @@ -0,0 +1,111 @@ +version: '3' + +services: + frappe-assets: + image: frappe/frappe-assets:${VERSION} + restart: on-failure + environment: + - FRAPPE_PY=frappe-python + - FRAPPE_PY_PORT=8000 + - FRAPPE_SOCKETIO=frappe-socketio + - SOCKETIO_PORT=9000 + - LETSENCRYPT_HOST=${SITES} + - VIRTUAL_HOST=${SITES} + - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL} + depends_on: + - frappe-python + - frappe-socketio + - frappe-worker-default + - frappe-worker-long + - frappe-worker-short + links: + - frappe-python + - frappe-socketio + - frappe-worker-default + - frappe-worker-long + - frappe-worker-short + volumes: + - ./sites:/var/www/html/sites:rw + - assets-vol:/assets:rw + + frappe-python: + image: frappe/frappe-worker:${VERSION} + restart: on-failure + environment: + - MARIADB_HOST=${MARIADB_HOST} + - REDIS_CACHE=redis-cache:6379 + - REDIS_QUEUE=redis-queue:6379 + - REDIS_SOCKETIO=redis-socketio:6379 + - SOCKETIO_PORT=9000 + volumes: + - ./sites:/home/frappe/frappe-bench/sites:rw + - assets-vol:/home/frappe/frappe-bench/sites/assets:rw + + frappe-socketio: + image: frappe/frappe-socketio:${VERSION} + restart: on-failure + depends_on: + - redis-socketio + links: + - redis-socketio + volumes: + - ./sites:/home/frappe/frappe-bench/sites:rw + + frappe-worker-default: + image: frappe/frappe-worker:${VERSION} + restart: on-failure + command: worker + depends_on: + - redis-queue + - redis-cache + links: + - redis-queue + - redis-cache + volumes: + - ./sites:/home/frappe/frappe-bench/sites:rw + + frappe-worker-short: + image: frappe/frappe-worker:${VERSION} + restart: on-failure + command: worker + environment: + - WORKER_TYPE=short + depends_on: + - redis-queue + - redis-cache + links: + - redis-queue + - redis-cache + volumes: + - ./sites:/home/frappe/frappe-bench/sites:rw + + frappe-worker-long: + image: frappe/frappe-worker:${VERSION} + restart: on-failure + command: worker + environment: + - WORKER_TYPE=long + depends_on: + - redis-queue + - redis-cache + links: + - redis-queue + - redis-cache + volumes: + - ./sites:/home/frappe/frappe-bench/sites:rw + + frappe-schedule: + image: frappe/frappe-worker:${VERSION} + restart: on-failure + command: schedule + depends_on: + - redis-queue + - redis-cache + links: + - redis-queue + - redis-cache + volumes: + - ./sites:/home/frappe/frappe-bench/sites:rw + +volumes: + assets-vol: diff --git a/installation/docker-compose-networks.yml b/installation/docker-compose-networks.yml new file mode 100644 index 00000000..377f01d2 --- /dev/null +++ b/installation/docker-compose-networks.yml @@ -0,0 +1,6 @@ +version: '3' + +networks: + default: + external: + name: webproxy diff --git a/installation/env-example b/installation/env-example new file mode 100644 index 00000000..0d12cca6 --- /dev/null +++ b/installation/env-example @@ -0,0 +1,5 @@ +VERSION=edge +MARIADB_HOST=mariadb +MYSQL_ROOT_PASSWORD=admin +SITES=your.domain.com +LETSENCRYPT_EMAIL=your.email@your.domain.com diff --git a/installation/frappe-mariadb.cnf b/installation/frappe-mariadb.cnf new file mode 100644 index 00000000..83b2c703 --- /dev/null +++ b/installation/frappe-mariadb.cnf @@ -0,0 +1,7 @@ +[mysqld] +character-set-client-handshake = FALSE +character-set-server = utf8mb4 +collation-server = utf8mb4_unicode_ci + +[mysql] +default-character-set = utf8mb4