├── .env ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── documentation_report.md │ └── feature_request.md └── workflows │ ├── mirror.yml │ └── templating.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── Notes.md ├── README-zh.md ├── README.md ├── docker-compose.yml ├── src ├── after_up.sh ├── compose.yaml ├── encrypt.sh ├── example.env ├── filelist ├── get_version.sh └── overrides │ ├── compose.erpnext.yaml │ ├── compose.mariadb.yaml │ ├── compose.noproxy.yaml │ └── compose.redis.yaml └── variables.json /.env: -------------------------------------------------------------------------------- 1 | POWER_PASSWORD=tfhdjX1vHiwGAi 2 | APP_HTTP_PORT=9001 3 | APP_NAME=erpnext 4 | # ERPNext version <= v12 is mariadb, ERPNext version > v12 is db 5 | APP_DB_PARAM=db 6 | APP_URL_REPLACE=true 7 | APP_URL=appname.example.com 8 | APP_USER=Administrator 9 | APP_PASSWORD=$POWER_PASSWORD 10 | # Support ERPNext version: v12,v13,v14 11 | APP_VERSION=v14 12 | APP_NETWORK=websoft9 13 | DB_MARIA_PASSWORD=$POWER_PASSWORD 14 | DB_MARIA_PORT=3306 15 | 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report a bug encountered while using websoft9's product 4 | labels: bug 5 | --- 6 | 7 | **Describe the bug** 8 | 9 | A clear and concise description of what the bug is. 10 | 11 | ## Deployment method 12 | 13 | - [ ] subscription image from MarketPlace of Cloud 14 | - [ ] All-in-one Installer 15 | - [ ] ansible-playbook cli 16 | - [ ] mcloud 17 | - [ ] create instance from private image 18 | 19 | ## Bug source 20 | 21 | - [ ] Bugs from installation 22 | - [ ] Bugs from first use 23 | - [ ] Other (You should describe it) 24 | 25 | ## System Environment 26 | 27 | **Application Version** 28 | 29 | e.g v4.5 30 | 31 | **OS** 32 | 33 | - [ ] Ubuntu18.x 34 | - [ ] Ubuntu20.x 35 | - [ ] CentOS7.x 36 | - [ ] CentOS8.x 37 | - [ ] AmazonLinux2 38 | - [ ] OracleLinux7.8 39 | - [ ] OracleLinux8.2 40 | - [ ] Other (You should describe it) 41 | 42 | **Cloud PlatForm** 43 | 44 | - [ ] Azure 45 | - [ ] Aws 46 | - [ ] 阿里云 47 | - [ ] 腾讯云 48 | - [ ] 华为云 49 | - [ ] AlibabaCloud 50 | - [ ] HUWEICloud 51 | - [ ] Other (You should describe it) 52 | 53 | 54 | ## Bug reproduce 55 | 56 | Steps to reproduce the behavior: 57 | 58 | 1. Go to '...' 59 | 2. Click on '....' 60 | 3. Scroll down to '....' 61 | 4. See error 62 | 63 | ## Bug reports 64 | 65 | ### Bug Context 66 | 67 | Bug context includes bug error, error logs and service status, it is very important for resolving issue 68 | 69 | ``` 70 | # bug error 71 | (paste here) 72 | 73 | # service status 74 | (paste here) 75 | 76 | # error logs 77 | (paste here) 78 | ``` 79 | 80 | ### Bug Screenshot 81 | 82 | paste screenshot here 83 | 84 | ## Your suggestion 85 | 86 | **The reason of Bug** 87 | 88 | You can describe the reason if you have found it 89 | 90 | **Your solution for Bug** 91 | 92 | You can describe your solution here 93 | 94 | **Additional context** 95 | 96 | You can add any other context about the problem here. 97 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Documentation report 3 | about: improve current Documentation 4 | labels: documentation 5 | --- 6 | 7 | 8 | ## Language 9 | 10 | - [ ] Chinese 11 | - [ ] English 12 | 13 | ## Content error 14 | 15 | Provide us with documentation errors, e.g spelling mistake, wrong screenshot, code syntax error. 16 | 17 | * URL: 18 | * Description: 19 | * Screenshot 20 | 21 | ## Content optimization 22 | 23 | Provide us with content optimization, e.g easy to read, simplify the steps, step by step, precise expression. 24 | 25 | * URL: 26 | * Description: 27 | 28 | ## New content 29 | 30 | Describe important content what do you think is important in this documentation. 31 | 32 | **What content do you want to add?** 33 | 34 | (describe here) 35 | 36 | **Steps for the content** 37 | 38 | 1. Go to '...' 39 | 2. Click on '....' 40 | 3. Scroll down to '....' 41 | 4. Modify file '....' 42 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: 'enhancement' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **What type of your feature request?** 11 | 12 | - [ ] Add new features 13 | - [ ] Improve current features 14 | 15 | **Is your feature request related to a problem? Please describe.** 16 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 17 | 18 | **Describe the solution you'd like** 19 | A clear and concise description of what you want to happen. 20 | 21 | **Describe alternatives you've considered** 22 | A clear and concise description of any alternative solutions or features you've considered. 23 | 24 | **Additional context** 25 | Add any other context or screenshots about the feature request here. 26 | -------------------------------------------------------------------------------- /.github/workflows/mirror.yml: -------------------------------------------------------------------------------- 1 | name: Mirror to Gitee Repo 2 | 3 | # on: [ push, delete, create ] 4 | on: 5 | push: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | git-mirror: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Configure Private Key 14 | env: 15 | SSH_PRIVATE_KEY: ${{ secrets.GITEE_PRIVATE_KEY }} 16 | run: | 17 | mkdir -p ~/.ssh 18 | echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa 19 | chmod 600 ~/.ssh/id_rsa 20 | echo "StrictHostKeyChecking no" >> ~/.ssh/config 21 | - name: Push Mirror 22 | env: 23 | # SOURCE_REPO: 'https://github.com/mgithubTestOrg/giteeMirror.git' 24 | SOURCE_REPO: 'https://github.com/${{ github.repository }}.git' 25 | # DESTINATION_REPO: 'git@gitee.com:mgithubTestOrg/giteeMirror.git' 26 | # DESTINATION_REPO: 'git@gitee.com:${{ github.repository }}.git' 27 | DESTINATION_REPO: 'git@gitee.com:websoft9/${{ github.event.repository.name }}.git' 28 | BASE_REPO: 'https://github.com/${{ github.repository }}' 29 | run: | 30 | git clone "$SOURCE_REPO" && cd `basename "$BASE_REPO"` 31 | git config --global user.name "${{ github.actor }}" 32 | git config --global user.email "xxx@websoft9.com" 33 | 34 | git remote set-url --push origin "$DESTINATION_REPO" 35 | git push origin main --force 36 | 37 | git checkout dev 38 | if [ -f "requirements.yml" ];then 39 | sed -i 's/github/gitee/g' requirements.yml 40 | git add requirements.yml 41 | git commit -m "Make requirements.yml compatible with gitee" 42 | fi 43 | git push origin dev --force 44 | 45 | git checkout main 46 | 47 | git fetch -p origin 48 | git for-each-ref --format 'delete %(refname)' refs/pull | git update-ref --stdin 49 | git push origin main --force 50 | 51 | if [ -f "requirements.yml" ];then 52 | sed -i 's/github/gitee/g' requirements.yml 53 | git add requirements.yml 54 | git commit -m "Make requirements.yml compatible with gitee" 55 | fi 56 | git push origin main --force -------------------------------------------------------------------------------- /.github/workflows/templating.yml: -------------------------------------------------------------------------------- 1 | name: Template README by variables.json 2 | 3 | on: 4 | repository_dispatch: 5 | push: 6 | paths: [variables.json, Notes.md, docker-compose.yml, CHANGELOG.md, .env] 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@master 13 | 14 | - name: npm install jinjia2-cli 15 | run: | 16 | wget -N https://raw.githubusercontent.com/Websoft9/docker-template/main/README.jinja2 -O template_README.jinja2 17 | wget -N https://raw.githubusercontent.com/Websoft9/docker-template/main/README-zh.jinja2 -O template_README-zh.jinja2 18 | pip install jinja2-cli 19 | jinja2 template_README-zh.jinja2 variables.json > README-zh.md 20 | jinja2 template_README.jinja2 variables.json > README.md 21 | rm -f template_README.jinja2 template_README-zh.jinja2 22 | 23 | - uses: stefanzweifel/git-auto-commit-action@v4 24 | with: 25 | commit_message: Templating README 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Websoft9test/docker-erpnext/b4a50fb00a6dc52af5d62d8bdb4ef5195688a906/.gitignore -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | ## Release 4 | ### Fixes and Enhancements 5 | 6 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | This program is released under LGPL-3.0 and with the additional Terms: 2 | It is not allowed to publish free or paid image based on this program in any Cloud platform's Marketplace. 3 | 4 | GNU LESSER GENERAL PUBLIC LICENSE 5 | Version 3, 29 June 2007 6 | 7 | Copyright (C) 2007 Free Software Foundation, Inc. 8 | Everyone is permitted to copy and distribute verbatim copies 9 | of this license document, but changing it is not allowed. 10 | 11 | 12 | This version of the GNU Lesser General Public License incorporates 13 | the terms and conditions of version 3 of the GNU General Public 14 | License, supplemented by the additional permissions listed below. 15 | 16 | 0. Additional Definitions. 17 | 18 | As used herein, "this License" refers to version 3 of the GNU Lesser 19 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 20 | General Public License. 21 | 22 | "The Library" refers to a covered work governed by this License, 23 | other than an Application or a Combined Work as defined below. 24 | 25 | An "Application" is any work that makes use of an interface provided 26 | by the Library, but which is not otherwise based on the Library. 27 | Defining a subclass of a class defined by the Library is deemed a mode 28 | of using an interface provided by the Library. 29 | 30 | A "Combined Work" is a work produced by combining or linking an 31 | Application with the Library. The particular version of the Library 32 | with which the Combined Work was made is also called the "Linked 33 | Version". 34 | 35 | The "Minimal Corresponding Source" for a Combined Work means the 36 | Corresponding Source for the Combined Work, excluding any source code 37 | for portions of the Combined Work that, considered in isolation, are 38 | based on the Application, and not on the Linked Version. 39 | 40 | The "Corresponding Application Code" for a Combined Work means the 41 | object code and/or source code for the Application, including any data 42 | and utility programs needed for reproducing the Combined Work from the 43 | Application, but excluding the System Libraries of the Combined Work. 44 | 45 | 1. Exception to Section 3 of the GNU GPL. 46 | 47 | You may convey a covered work under sections 3 and 4 of this License 48 | without being bound by section 3 of the GNU GPL. 49 | 50 | 2. Conveying Modified Versions. 51 | 52 | If you modify a copy of the Library, and, in your modifications, a 53 | facility refers to a function or data to be supplied by an Application 54 | that uses the facility (other than as an argument passed when the 55 | facility is invoked), then you may convey a copy of the modified 56 | version: 57 | 58 | a) under this License, provided that you make a good faith effort to 59 | ensure that, in the event an Application does not supply the 60 | function or data, the facility still operates, and performs 61 | whatever part of its purpose remains meaningful, or 62 | 63 | b) under the GNU GPL, with none of the additional permissions of 64 | this License applicable to that copy. 65 | 66 | 3. Object Code Incorporating Material from Library Header Files. 67 | 68 | The object code form of an Application may incorporate material from 69 | a header file that is part of the Library. You may convey such object 70 | code under terms of your choice, provided that, if the incorporated 71 | material is not limited to numerical parameters, data structure 72 | layouts and accessors, or small macros, inline functions and templates 73 | (ten or fewer lines in length), you do both of the following: 74 | 75 | a) Give prominent notice with each copy of the object code that the 76 | Library is used in it and that the Library and its use are 77 | covered by this License. 78 | 79 | b) Accompany the object code with a copy of the GNU GPL and this license 80 | document. 81 | 82 | 4. Combined Works. 83 | 84 | You may convey a Combined Work under terms of your choice that, 85 | taken together, effectively do not restrict modification of the 86 | portions of the Library contained in the Combined Work and reverse 87 | engineering for debugging such modifications, if you also do each of 88 | the following: 89 | 90 | a) Give prominent notice with each copy of the Combined Work that 91 | the Library is used in it and that the Library and its use are 92 | covered by this License. 93 | 94 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 95 | document. 96 | 97 | c) For a Combined Work that displays copyright notices during 98 | execution, include the copyright notice for the Library among 99 | these notices, as well as a reference directing the user to the 100 | copies of the GNU GPL and this license document. 101 | 102 | d) Do one of the following: 103 | 104 | 0) Convey the Minimal Corresponding Source under the terms of this 105 | License, and the Corresponding Application Code in a form 106 | suitable for, and under terms that permit, the user to 107 | recombine or relink the Application with a modified version of 108 | the Linked Version to produce a modified Combined Work, in the 109 | manner specified by section 6 of the GNU GPL for conveying 110 | Corresponding Source. 111 | 112 | 1) Use a suitable shared library mechanism for linking with the 113 | Library. A suitable mechanism is one that (a) uses at run time 114 | a copy of the Library already present on the user's computer 115 | system, and (b) will operate properly with a modified version 116 | of the Library that is interface-compatible with the Linked 117 | Version. 118 | 119 | e) Provide Installation Information, but only if you would otherwise 120 | be required to provide such information under section 6 of the 121 | GNU GPL, and only to the extent that such information is 122 | necessary to install and execute a modified version of the 123 | Combined Work produced by recombining or relinking the 124 | Application with a modified version of the Linked Version. (If 125 | you use option 4d0, the Installation Information must accompany 126 | the Minimal Corresponding Source and Corresponding Application 127 | Code. If you use option 4d1, you must provide the Installation 128 | Information in the manner specified by section 6 of the GNU GPL 129 | for conveying Corresponding Source.) 130 | 131 | 5. Combined Libraries. 132 | 133 | You may place library facilities that are a work based on the 134 | Library side by side in a single library together with other library 135 | facilities that are not Applications and are not covered by this 136 | License, and convey such a combined library under terms of your 137 | choice, if you do both of the following: 138 | 139 | a) Accompany the combined library with a copy of the same work based 140 | on the Library, uncombined with any other library facilities, 141 | conveyed under the terms of this License. 142 | 143 | b) Give prominent notice with the combined library that part of it 144 | is a work based on the Library, and explaining where to find the 145 | accompanying uncombined form of the same work. 146 | 147 | 6. Revised Versions of the GNU Lesser General Public License. 148 | 149 | The Free Software Foundation may publish revised and/or new versions 150 | of the GNU Lesser General Public License from time to time. Such new 151 | versions will be similar in spirit to the present version, but may 152 | differ in detail to address new problems or concerns. 153 | 154 | Each version is given a distinguishing version number. If the 155 | Library as you received it specifies that a certain numbered version 156 | of the GNU Lesser General Public License "or any later version" 157 | applies to it, you have the option of following the terms and 158 | conditions either of that published version or of any later version 159 | published by the Free Software Foundation. If the Library as you 160 | received it does not specify a version number of the GNU Lesser 161 | General Public License, you may choose any version of the GNU Lesser 162 | General Public License ever published by the Free Software Foundation. 163 | 164 | If the Library as you received it specifies that a proxy can decide 165 | whether future versions of the GNU Lesser General Public License shall 166 | apply, that proxy's public statement of acceptance of any version is 167 | permanent authorization for you to choose that version for the 168 | Library. 169 | -------------------------------------------------------------------------------- /Notes.md: -------------------------------------------------------------------------------- 1 | # ERPNext 2 | 3 | ## Install 4 | 5 | 官方非常及时的更新了安装所需的镜像,且提供了灵活多变的 docker compose 文件以供用户使用。 6 | 7 | 由于过于灵活,导致理解起来有些困难。 实际上 ERPNext 的安装比较简单: 8 | 9 | 1. 将 example.env 另存为根目录 .env 10 | 2. 将 compose.yaml 另存为根目录下 compose.yaml 或 docker-compose.yml,然后略加修改。接下来有两个可选方案: 11 | 3. 方案一:使用 compose convert 命令合并多个 compose 为一个完整的 compose 文件(环境变量会替换),然后启动容器 12 | ``` 13 | docker compose -f compose.yaml -f src/overrides/compose.erpnext.yaml -f src/overrides/compose.redis.yaml -f src/overrides/compose.mariadb.yaml convert > docker-compose.yml 14 | ``` 15 | 4. 方案二(推荐):启动时引入主 compose 文件以及有选择性的启动 overrides 文件夹下的 docker compose 文件 (多 compose 文件的用法) 16 | ``` 17 | docker compose -f docker-compose.yml -f src/overrides/compose.erpnext.yaml -f src/overrides/compose.redis.yaml -f src/overrides/compose.mariadb.yaml up -d 18 | ``` 19 | 20 | 5. 主服务 backend 中创建一个 erpnext 项目(此步骤是必须的,但很容易被忽略) 21 | ``` 22 | APP_URL=8.218.129.87 23 | docker compose exec backend bench new-site youurl --mariadb-root-password yourpassword --admin-password admin123 24 | 25 | or 26 | 27 | ``` 28 | 参考:https://github1s.com/frappe/frappe_docker/blob/HEAD/docs/site-operations.md 29 | 30 | ## FAQ 31 | 32 | #### 默认管理员账号密码? 33 | 34 | username: Administrator 35 | password: admin 36 | 37 | #### ERPNext 镜像与 Frappe 镜像有什么区别? 38 | 39 | 经过研究,ERPNext 是官方推出的新的镜像,感觉未来应该推荐使用它。 40 | 41 | 实验中发现 ERPNext 不会出现图片乱码问题 42 | 43 | #### 究竟如何部署 ERPNext? 44 | 45 | 从官方源码中发现,安装文档指南(单一服务器)中对安装写得过于繁琐,但实际上只需采用 overrides 中多个 compose 文件即可快速安装。 46 | 47 | 这是怎么回事呢?通过官方的论坛中研究,发现这是文档更新不及时导致,也就是说overrides中的安装在文档中还没有体现,虽然它更具有效率。 48 | 49 | 50 | #### 与URL有关的变量有那些? 51 | 52 | ``` 53 | echo "ROUTER=custom-one-example" > ~/gitops/custom-one-example.env 54 | echo "SITES=\`custom-one.example.com\`" >> ~/gitops/custom-one-example.env 55 | echo "BASE_SITE=one.example.com" >> ~/gitops/custom-one-example.env 56 | echo "BENCH_NETWORK=erpnext-one" >> ~/gitops/custom-one-example.env 57 | ``` 58 | 59 | https://github.com/frappe/frappe_docker/blob/main/docs/single-server-example.md#create-custom-domain-to-existing-site -------------------------------------------------------------------------------- /README-zh.md: -------------------------------------------------------------------------------- 1 | # ERPNext on Docker 2 | 3 | ![](https://libs.websoft9.com/common/websoft9-cloud-installer.png) 4 | 5 | ## 简介 6 | 7 | [简体中文](/README-zh.md) | [English](/README.md) 8 | 9 | 本项目是由 [Websoft9](https://www.websoft9.com) 研发的 **云原生程序** ,大大简化 ERPNext 复杂的安装及配置。 10 | 11 | ## 系统要求 12 | 13 | 安装本项目,确保符合如下的条件([详细参考](https://github.com/frappe/bench)): 14 | 15 | * **操作系统**: Red Hat, CentOS, Debian, Ubuntu 等主流 Linux等 操作系统 16 | * **公有云**: AWS, Azure, Google Cloud, 阿里云, 腾讯云, 华为云等20多个全球主流云 17 | * **私有云**: KVM, VMware, VirtualBox, OpenStack 等主流虚拟化架构 18 | * **CPU架构**: Linux x86-64, ARM 32/64, Windows x86-64, IBM POWER8, x86/i686 19 | * **内存**: 4GB以上 20 | * **CPU**: 2核以上 21 | * **存储**: 20GB以上 22 | * **Swap分区**: 2GB以上 23 | * **带宽**: 100M以上体验更流畅 24 | 25 | ## 安装使用 26 | 27 | ### 自动安装(推荐) 28 | 29 | 登录 Linux,运行下面的**自动化命令**即可启动安装并显示安装结果。 30 | 31 | ``` 32 | sudo wget -N https://raw.githubusercontent.com/Websoft9/StackHub/main/docker-installer.sh; sudo bash docker-installer.sh -r erpnext 33 | 34 | ``` 35 | 36 | ### package包安装 37 | 38 | 1.生成package包 39 | 登录 Linux,运行下面的**自动化命令**即可生成所需的package包。 40 | ``` 41 | sudo wget -N https://raw.githubusercontent.com/Websoft9/StackHub/main/docker-installer.sh; sudo bash docker-installer.sh -r erpnext -p 42 | ``` 43 | 2.复制package包后安装 44 | 45 | 将压缩的package包复制到想要安装的服务器或虚拟机,登录 Linux,运行下面的**自动化命令**即可启动安装并显示安装结果。 46 | ``` 47 | sudo bash install-erpnext 48 | ``` 49 | 50 | ### 手动安装 51 | 52 | 如果熟悉 Linux 以及 Docker,可以采用手动安装的方式 53 | 54 | #### 准备 Docker 环境 55 | 56 | 如果您的服务器尚未安装 Docker,请使用如下命令安装它: 57 | 58 | ``` 59 | curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh 60 | curl -L "https://github.com/docker/compose/releases/download/v2.1.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 61 | sudo chmod +x /usr/local/bin/docker-compose 62 | ln -sf /usr/local/bin/docker-compose /usr/bin 63 | sudo systemctl start docker 64 | ``` 65 | 66 | #### 安装 ERPNext 67 | 68 | 直接运行下面的命令快速安装应用。如果你熟悉 Docker,建议先修改 [docker-compose](docker-compose.yml) 文件以满足自己的需求 69 | 70 | ``` 71 | git clone --depth=1 https://github.com/Websoft9/docker-erpnext 72 | cd docker-erpnext 73 | public_ip=`wget -O - https://download.websoft9.com/ansible/get_ip.sh | bash` 74 | sudo sed -i s/erp.example.com/$public_ip/g ./.env 75 | sudo docker-compose up -d 76 | ``` 77 | 78 | ### 常见问题 79 | 80 | #### 安装 ERPNext 前需要更改密码吗? 81 | 82 | 是的, 在生产环境中,您应该在 docker-compose 文件中修改所有数据库密码和应用程序密码 83 | 84 | #### 端口冲突导致无法启动? 85 | 86 | 修改 [docker-compose](docker-compose.yml) 文件中冲突的端口,然后再启动容器 87 | 88 | #### 为什么ERPNext端口用8000,这违反了compose文件的编码规范? 89 | 因为使用9001或其他端口,将会导致部分容器发生错误,导致应用无法正常访问 90 | #### 默认启动的ERPNext是v12,我想运行其他版本该如何操作 91 | 如果您想运行ERPNext13,只需将ERPNEXT_VERSION、FRAPPE_VERSION修改成v13;修改前需要删除volumes文件夹 92 | ### 使用说明 93 | 94 | 启动应用后,本地浏览器访问 URL: *`http://服务器公网IP:端口`* 进入应用。 95 | 96 | 下面是使用过程中可能需要的信息 97 | 98 | #### 账号 99 | 100 | 本应用默认安装后的管理员用户名和密码如下: 101 | 102 | | 用户名 | 密码 | 103 | | ------- | -------- | 104 | | Administrator | admin | 105 | 106 | #### 服务和端口 107 | 108 | | 名称 | 端口号 | 用途 | 必要性 | 109 | | --- | --- | --- | --- | 110 | | erpnext | 8000 | 浏览器访问 ERPNext | Y | 111 | | mariadb | 3306 | TCP 访问MariaDB数据库 | Y | 112 | ## 文档 113 | 114 | [ERPNext 管理员手册](https://support.websoft9.com/docs/erpnext) 115 | 116 | ## 企业级支持 117 | 118 | 如果需要企业级支持,请订阅我们提供的 [ERPNext 企业级支持版](https://apps.websoft9.com/erpnext) 119 | 120 | 订阅企业级产品后,您可获得: 121 | 122 | * 精准知识:产品专家的解答和指导 123 | * 全面支持:技术支持所需的一切,例如启用HTTPS、升级指南 124 | * 安全顾问:安全服务和工具,可提高您软件的安全性 125 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ERPNext on Docker 2 | 3 | ![](https://libs.websoft9.com/common/websott9-cloud-installer.png) 4 | 5 | ## Introduction 6 | 7 | [English](/README.md) | [简体中文](/README-zh.md) 8 | 9 | This repository is an **Cloud Native solution** powered by [Websoft9](https://www.websoft9.com), it simplifies the complicated installation and initialization process. 10 | 11 | ## System Requirements 12 | 13 | The following are the minimal [recommended requirements](https://github.com/frappe/bench): 14 | 15 | * **OS**: Red Hat, CentOS, Debian, Ubuntu or other's Linux OS 16 | * **Public Cloud**: More than 20+ major Cloud such as AWS, Azure, Google Cloud, Alibaba Cloud, HUAWEIClOUD, Tencent Cloud 17 | * **Private Cloud**: KVM, VMware, VirtualBox, OpenStack 18 | * **ARCH**: Linux x86-64, ARM 32/64, Windows x86-64, IBM POWER8, x86/i686 19 | * **RAM**: 4 GB or more 20 | * **CPU**: 2 cores or higher 21 | * **HDD**: at least 20 GB of free space 22 | * **Swap file**: at least 2 GB 23 | * **bandwidth**: more fluent experience over 100M 24 | 25 | ## QuickStart 26 | 27 | ### All-in-one Installer 28 | 29 | Use SSH to connect your instance and run the automatic installation script below 30 | 31 | ``` 32 | sudo wget -N https://raw.githubusercontent.com/Websoft9/StackHub/main/docker-installer.sh; sudo bash docker-installer.sh -r erpnext 33 | ``` 34 | ### package install 35 | 36 | 1.Make package 37 | You can get the package as following script 38 | ``` 39 | sudo wget -N https://raw.githubusercontent.com/Websoft9/StackHub/main/docker-installer.sh; sudo bash docker-installer.sh -r erpnext -p 40 | ``` 41 | 42 | 2.Install by package 43 | Copy package to your server, Use SSH to connect your instance and run the automatic installation script below 44 | ``` 45 | sudo bash install-erpnext 46 | ``` 47 | 48 | ### Manual Installation 49 | 50 | #### Preparation 51 | 52 | If you have not install Docker and Docker-Compose, refer to the following commands to install it: 53 | 54 | ``` 55 | curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh 56 | curl -L "https://github.com/docker/compose/releases/download/v2.1.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 57 | sudo chmod +x /usr/local/bin/docker-compose 58 | ln -sf /usr/local/bin/docker-compose /usr/bin 59 | sudo systemctl start docker 60 | ``` 61 | 62 | #### Install ERPNext 63 | 64 | We assume that you are already familiar with Docker, and you can modify [docker-compose file](docker-compose.yml) by yourself 65 | 66 | ``` 67 | git clone --depth=1 https://github.com/Websoft9/docker-erpnext 68 | cd docker-erpnext 69 | public_ip=`wget -O - https://download.websoft9.com/ansible/get_ip.sh | bash` 70 | sudo sed -i s/erp.example.com/$public_ip/g ./.env 71 | docker-compose up -d 72 | ``` 73 | 74 | ### FAQ 75 | 76 | #### Do I need to change the password before docker-compose up? 77 | Yes, you should modify all database password and application password at docker-compose file for production 78 | 79 | #### Docker runing failed for the reason that port conflict? 80 | You should modify ports at [docker-compose file](docker-compose-production.yml) and docker-compose again 81 | 82 | #### Why does the erptext port use 8000, which violates the encoding specification of the compose file? 83 | The use of 9001 or other ports will lead to errors in some containers and make the application unable to access normally 84 | #### The default startup is erpnext12, What should I do if I want to run another version? 85 | If you want to run erpnext13, you only need to change ERPNEXT_VERSION/FRAPPE_VERSIO to V13;Please delete volumes before edit configure 86 | ### Usage instructions 87 | 88 | You can point your browser to: *`http://Instance's Internet IP:port`* 89 | 90 | The following is the information that may be needed during use 91 | 92 | #### Credentials 93 | 94 | By default, the available users are: 95 | 96 | | Username | Password | 97 | | ------- | -------- | 98 | | Administrator | admin | 99 | 100 | #### Services and Ports 101 | 102 | | Service | Port | Use | Necessity | 103 | | --- | --- | --- | --- | 104 | | erpnext | 8000 | Browser access to ERPNext by http | Y | 105 | | mariadb | 3306 | Accessing MySQL database with TCP | Y | 106 | ## Documentation 107 | 108 | [ERPNext Administrator Guide](https://support.websoft9.com/docs/erpnext) 109 | 110 | ## Enterprise Support 111 | 112 | If you want to get our Enterprise Support to ensure high availability of applications, you can subscribe our [ERPNext Enterprise Support](https://apps.websoft9.com/erpnext) 113 | 114 | What you get with a Enterprise Support subscription? 115 | 116 | * Knowledge: Answers and guidance from product experts 117 | * Support: Everything you need for technical support, e.g Enable HTTPS, Upgrade guide 118 | * Security: Security services and tools to protect your software 119 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | # image: https://registry.hub.docker.com/r/frappe/erpnext-worker 2 | # docs: https://github.com/frappe/frappe_docker/blob/main/pwd.yml 3 | 4 | version: "3.8" 5 | 6 | services: 7 | backend: 8 | image: frappe/erpnext-worker:${APP_VERSION} 9 | container_name: ${APP_NAME} 10 | deploy: 11 | restart_policy: 12 | condition: on-failure 13 | volumes: 14 | - sites:/home/frappe/frappe-bench/sites 15 | - assets:/home/frappe/frappe-bench/sites/assets 16 | 17 | configurator: 18 | image: frappe/erpnext-worker:${APP_VERSION} 19 | container_name: ${APP_NAME}-configurator 20 | command: 21 | - configure.py 22 | environment: 23 | DB_HOST: db 24 | DB_PORT: "3306" 25 | REDIS_CACHE: redis:6379/0 26 | REDIS_QUEUE: redis:6379/1 27 | REDIS_SOCKETIO: redis:6379/2 28 | SOCKETIO_PORT: "9000" 29 | volumes: 30 | - sites:/home/frappe/frappe-bench/sites 31 | 32 | create-site: 33 | image: frappe/erpnext-worker:${APP_VERSION} 34 | container_name: ${APP_NAME}-create-site 35 | deploy: 36 | restart_policy: 37 | condition: on-failure 38 | volumes: 39 | - sites:/home/frappe/frappe-bench/sites 40 | - assets:/home/frappe/frappe-bench/sites/assets 41 | entrypoint: 42 | - bash 43 | - -c 44 | command: 45 | - > 46 | wait-for-it -t 20 db:3306; 47 | wait-for-it -t 20 redis:6379; 48 | export start=`date +%s`; 49 | until [[ -n `grep -hs ^ common_site_config.json | jq -r ".db_host // empty"` ]] && \ 50 | [[ -n `grep -hs ^ common_site_config.json | jq -r ".redis_cache // empty"` ]] && \ 51 | [[ -n `grep -hs ^ common_site_config.json | jq -r ".redis_queue // empty"` ]]; 52 | do 53 | echo "Waiting for common_site_config.json to be created"; 54 | sleep 5; 55 | if (( `date +%s`-start > 20 )); then 56 | echo "could not find common_site_config.json with required keys"; 57 | exit 1 58 | fi 59 | done; 60 | echo "common_site_config.json found"; 61 | bench new-site frontend --admin-password=${APP_PASSWORD} --${APP_DB_PARAM}-root-password=${DB_MARIA_PASSWORD} --install-app erpnext; 62 | 63 | db: 64 | image: mariadb:10.6 65 | container_name: ${APP_NAME}-db 66 | healthcheck: 67 | test: mysqladmin ping -h localhost --password=${DB_MARIA_PASSWORD} 68 | interval: 1s 69 | retries: 15 70 | deploy: 71 | restart_policy: 72 | condition: on-failure 73 | command: 74 | - --character-set-server=utf8mb4 75 | - --collation-server=utf8mb4_unicode_ci 76 | - --skip-character-set-client-handshake 77 | - --skip-innodb-read-only-compressed # Temporary fix for MariaDB 10.6 78 | environment: 79 | MYSQL_ROOT_PASSWORD: ${DB_MARIA_PASSWORD} 80 | volumes: 81 | - db-data:/var/lib/mysql 82 | ports: 83 | - "${DB_MARIA_PORT}:3306" 84 | 85 | frontend: 86 | image: frappe/erpnext-nginx:${APP_VERSION} 87 | container_name: ${APP_NAME}-frontend 88 | deploy: 89 | restart_policy: 90 | condition: on-failure 91 | environment: 92 | BACKEND: backend:8000 93 | FRAPPE_SITE_NAME_HEADER: frontend 94 | SOCKETIO: websocket:9000 95 | UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1 96 | UPSTREAM_REAL_IP_HEADER: X-Forwarded-For 97 | UPSTREAM_REAL_IP_RECURSIVE: "off" 98 | volumes: 99 | - sites:/usr/share/nginx/html/sites 100 | - assets:/usr/share/nginx/html/assets 101 | ports: 102 | - "${APP_HTTP_PORT}:8080" 103 | 104 | queue-default: 105 | image: frappe/erpnext-worker:${APP_VERSION} 106 | container_name: ${APP_NAME}-queue-default 107 | deploy: 108 | restart_policy: 109 | condition: on-failure 110 | command: 111 | - bench 112 | - worker 113 | - --queue 114 | - default 115 | volumes: 116 | - sites:/home/frappe/frappe-bench/sites 117 | 118 | queue-long: 119 | image: frappe/erpnext-worker:${APP_VERSION} 120 | container_name: ${APP_NAME}-queue-long 121 | deploy: 122 | restart_policy: 123 | condition: on-failure 124 | command: 125 | - bench 126 | - worker 127 | - --queue 128 | - long 129 | volumes: 130 | - sites:/home/frappe/frappe-bench/sites 131 | 132 | queue-short: 133 | image: frappe/erpnext-worker:${APP_VERSION} 134 | container_name: ${APP_NAME}-queue-short 135 | deploy: 136 | restart_policy: 137 | condition: on-failure 138 | command: 139 | - bench 140 | - worker 141 | - --queue 142 | - short 143 | volumes: 144 | - sites:/home/frappe/frappe-bench/sites 145 | 146 | redis: 147 | image: redis:6.2-alpine 148 | container_name: ${APP_NAME}-redis 149 | deploy: 150 | restart_policy: 151 | condition: on-failure 152 | volumes: 153 | - redis-data:/data 154 | 155 | scheduler: 156 | image: frappe/erpnext-worker:${APP_VERSION} 157 | container_name: ${APP_NAME}-scheduler 158 | deploy: 159 | restart_policy: 160 | condition: on-failure 161 | command: 162 | - bench 163 | - schedule 164 | volumes: 165 | - sites:/home/frappe/frappe-bench/sites 166 | 167 | websocket: 168 | image: frappe/frappe-socketio:${APP_VERSION} 169 | container_name: ${APP_NAME}-websocket 170 | deploy: 171 | restart_policy: 172 | condition: on-failure 173 | volumes: 174 | - sites:/home/frappe/frappe-bench/sites 175 | 176 | volumes: 177 | assets: 178 | db-data: 179 | redis-data: 180 | sites: 181 | 182 | networks: 183 | default: 184 | name: ${APP_NETWORK} 185 | external: true 186 | -------------------------------------------------------------------------------- /src/after_up.sh: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/compose.yaml: -------------------------------------------------------------------------------- 1 | x-depends-on-configurator: &depends_on_configurator 2 | depends_on: 3 | configurator: 4 | condition: service_completed_successfully 5 | 6 | x-backend-defaults: &backend_defaults 7 | <<: *depends_on_configurator 8 | image: frappe/frappe-worker:${FRAPPE_VERSION:?No Frappe version set} 9 | volumes: 10 | - sites:/home/frappe/frappe-bench/sites 11 | 12 | services: 13 | configurator: 14 | <<: *backend_defaults 15 | command: configure.py 16 | environment: 17 | DB_HOST: ${DB_HOST} 18 | DB_PORT: ${DB_PORT} 19 | REDIS_CACHE: ${REDIS_CACHE} 20 | REDIS_QUEUE: ${REDIS_QUEUE} 21 | REDIS_SOCKETIO: ${REDIS_SOCKETIO} 22 | SOCKETIO_PORT: 9000 23 | depends_on: {} 24 | 25 | backend: 26 | <<: *backend_defaults 27 | volumes: 28 | - sites:/home/frappe/frappe-bench/sites 29 | - assets:/home/frappe/frappe-bench/sites/assets:ro 30 | 31 | frontend: 32 | image: frappe/frappe-nginx:${FRAPPE_VERSION} 33 | environment: 34 | BACKEND: backend:8000 35 | SOCKETIO: websocket:9000 36 | FRAPPE_SITE_NAME_HEADER: ${FRAPPE_SITE_NAME_HEADER:-$$host} 37 | UPSTREAM_REAL_IP_ADDRESS: ${UPSTREAM_REAL_IP_ADDRESS:-127.0.0.1} 38 | UPSTREAM_REAL_IP_HEADER: ${UPSTREAM_REAL_IP_HEADER:-X-Forwarded-For} 39 | UPSTREAM_REAL_IP_RECURSIVE: ${UPSTREAM_REAL_IP_RECURSIVE:-off} 40 | volumes: 41 | - sites:/usr/share/nginx/html/sites 42 | - assets:/usr/share/nginx/html/assets 43 | depends_on: 44 | - backend 45 | - websocket 46 | 47 | websocket: 48 | <<: *depends_on_configurator 49 | image: frappe/frappe-socketio:${FRAPPE_VERSION} 50 | volumes: 51 | - sites:/home/frappe/frappe-bench/sites 52 | 53 | queue-short: 54 | <<: *backend_defaults 55 | command: bench worker --queue short 56 | 57 | queue-default: 58 | <<: *backend_defaults 59 | command: bench worker --queue default 60 | 61 | queue-long: 62 | <<: *backend_defaults 63 | command: bench worker --queue long 64 | 65 | scheduler: 66 | <<: *backend_defaults 67 | command: bench schedule 68 | 69 | # ERPNext requires local assets access (Frappe does not) 70 | volumes: 71 | sites: 72 | assets: 73 | -------------------------------------------------------------------------------- /src/encrypt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin 3 | clear 4 | 5 | 6 | 7 | # Add encrypt script below if use APP_ENCRYPT_PASSWORD at .env file 8 | # ------------- start ------------------------- 9 | 10 | 11 | 12 | # ------------- end --------------------------- 13 | -------------------------------------------------------------------------------- /src/example.env: -------------------------------------------------------------------------------- 1 | # Reference: https://github.com/frappe/frappe_docker/blob/main/docs/images-and-compose-files.md 2 | 3 | FRAPPE_VERSION=v13.30.0 4 | 5 | # Only with ERPNext override 6 | ERPNEXT_VERSION=v13.31.1 7 | 8 | DB_PASSWORD=123 9 | 10 | # Only if you use external database 11 | DB_HOST= 12 | DB_PORT= 13 | 14 | # Only if you use external Redis 15 | REDIS_CACHE= 16 | REDIS_QUEUE= 17 | REDIS_SOCKETIO= 18 | 19 | # Only with HTTPS override 20 | LETSENCRYPT_EMAIL=mail@example.com 21 | 22 | # These environment variables are not required. 23 | 24 | # Default value is `$$host` which resolves site by host. For example, if your host is `example.com`, 25 | # site's name should be `example.com`, or if host is `127.0.0.1` (local debugging), it should be `127.0.0.1`. 26 | # This variable allows to override described behavior. Let's say you create site named `mysite` 27 | # and do want to access it by `127.0.0.1` host. Than you would set this variable to `mysite`. 28 | FRAPPE_SITE_NAME_HEADER= 29 | 30 | # Default value is `127.0.0.1`. Set IP address as our trusted upstream address. 31 | UPSTREAM_REAL_IP_ADDRESS= 32 | 33 | # Default value is `X-Forwarded-For`. Set request header field whose value will be used to replace the client address 34 | UPSTREAM_REAL_IP_HEADER= 35 | 36 | # Allowed values are on|off. Default value is `off`. If recursive search is disabled, 37 | # the original client address that matches one of the trusted addresses 38 | # is replaced by the last address sent in the request header field defined by the real_ip_header directive. 39 | # If recursive search is enabled, the original client address that matches one of the trusted addresses is replaced by the last non-trusted address sent in the request header field. 40 | UPSTREAM_REAL_IP_RECURSIVE= -------------------------------------------------------------------------------- /src/filelist: -------------------------------------------------------------------------------- 1 | # https://github.com/frappe/frappe_docker 2 | compose.yaml 3 | example.env 4 | overrides -------------------------------------------------------------------------------- /src/get_version.sh: -------------------------------------------------------------------------------- 1 | sudo echo "erpnext version:" $(cat /data/apps/erpnext/.env |grep "APP_VERSION" |awk -F"=" '{print $2}') 1>> /data/logs/install_version.txt 2 | -------------------------------------------------------------------------------- /src/overrides/compose.erpnext.yaml: -------------------------------------------------------------------------------- 1 | x-erpnext-backend-image: &erpnext_backend_image 2 | image: frappe/erpnext-worker:${ERPNEXT_VERSION:?No ERPNext version set} 3 | 4 | services: 5 | configurator: 6 | <<: *erpnext_backend_image 7 | 8 | backend: 9 | <<: *erpnext_backend_image 10 | 11 | frontend: 12 | image: frappe/erpnext-nginx:${ERPNEXT_VERSION} 13 | 14 | queue-short: 15 | <<: *erpnext_backend_image 16 | 17 | queue-default: 18 | <<: *erpnext_backend_image 19 | 20 | queue-long: 21 | <<: *erpnext_backend_image 22 | 23 | scheduler: 24 | <<: *erpnext_backend_image 25 | -------------------------------------------------------------------------------- /src/overrides/compose.mariadb.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | configurator: 3 | environment: 4 | DB_HOST: db 5 | DB_PORT: 3306 6 | depends_on: 7 | db: 8 | condition: service_healthy 9 | 10 | db: 11 | image: mariadb:10.6 12 | healthcheck: 13 | test: mysqladmin ping -h localhost --password=${DB_PASSWORD} 14 | interval: 1s 15 | retries: 15 16 | command: 17 | - --character-set-server=utf8mb4 18 | - --collation-server=utf8mb4_unicode_ci 19 | - --skip-character-set-client-handshake 20 | - --skip-innodb-read-only-compressed # Temporary fix for MariaDB 10.6 21 | environment: 22 | MYSQL_ROOT_PASSWORD: ${DB_PASSWORD:?No db password set} 23 | volumes: 24 | - db-data:/var/lib/mysql 25 | 26 | volumes: 27 | db-data: 28 | -------------------------------------------------------------------------------- /src/overrides/compose.noproxy.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | frontend: 3 | ports: 4 | - 8080:8080 5 | -------------------------------------------------------------------------------- /src/overrides/compose.redis.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | configurator: 3 | environment: 4 | REDIS_CACHE: redis:6379/0 5 | REDIS_QUEUE: redis:6379/1 6 | REDIS_SOCKETIO: redis:6379/2 7 | depends_on: 8 | - redis 9 | 10 | redis: 11 | image: redis:6.2-alpine 12 | volumes: 13 | - redis-data:/data 14 | 15 | volumes: 16 | redis-data: 17 | -------------------------------------------------------------------------------- /variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "erpnext", 3 | "trademark": "ERPNext", 4 | "compose_file": "docker-compose.yml", 5 | "env_file": ".env", 6 | "fork_url": "https://github.com/frappe/frappe_docker.git", 7 | "requirements":{ 8 | "cpu_arch": "Linux x86-64, ARM 32/64, Windows x86-64, IBM POWER8, x86/i686", 9 | "cpu": "2", 10 | "memory": "8", 11 | "disk": "20", 12 | "swap": "2", 13 | "url": "https://github.com/frappe/bench" 14 | }, 15 | 16 | "user": { 17 | "username": "Administrator", 18 | "password": "admin" 19 | }, 20 | "command_extra":[ 21 | { 22 | "cmd": "public_ip=`wget -O - https://download.websoft9.com/ansible/get_ip.sh | bash`" 23 | }, 24 | { 25 | "cmd": "sudo sed -i s/erp.example.com/$public_ip/g ./.env" 26 | } 27 | ] 28 | 29 | 30 | } 31 | --------------------------------------------------------------------------------