开源企业资源规划ERPNext的安装

往常节假日,都是呆在家里看别人堵,这回老苏也出门凑了个热闹,28号早上 7 点半出的门

2 点半往回走的

一天啥也没干,就开了 7 个小时的车去舅舅家蹭了顿饭。还别说,那个田园鸡味道是真不错。

车很久没开了,但这回起码两个月不用遛了。


本文是应网友 潇雨 的要求折腾的。

什么是 ERPNext ?

ERPNext 是一种免费的、开源的企业资源规划(ERP)软件,它提供了一套完整的企业解决方案,包括会计、采购、销售、库存、制造、CRM 等功能。ERPNext 旨在为中小型企业提供一种简单、易用、灵活的 ERP 系统,以帮助企业管理业务流程、优化运营效率、提高生产力和盈利能力。ERPNext 建立在 Frappe 框架之上,这是一个使用 PythonJavaScript 构建的全栈 web 应用程序框架。

前期准备

在网友提出要求之前,老苏也曾经尝试过安装 ERPNext,但都以失败告终。

首先尝试了英文版,但由于涉及多个容器,可能有些地方改漏了、改错了,导致出现了错误,因为工作原因,也没有太多的时间去深入研究。

之后又尝试了中文版,这是一个All in one 的版本,安装相对简单。但遗憾的是,老苏一直遇到数据库出错的问题。由于老苏的机器内存较小,初步怀疑这可能是导致问题的原因。此外,由于容器内反复启动,导致机器的 CPU 占用率也急剧上升,最终只能放弃了。

docker-compose.yml

这次老苏牺牲了几个晚上,认真把 docker-compose.yml 好好整理了一下👇。如果你不知道什么含义,不建议你直接改这个文件,老苏已经把需要修改的内容,单独拎了出来放在了env.txt

docker-compose.yml 是基于官网 https://github.com/frappe/frappe_docker/blob/main/pwd.yml 修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
version: "3"

services:
backend:
image: frappe/erpnext:${APP_VERSION}
container_name: ${APP_NAME}-backend
deploy:
restart_policy:
condition: on-failure
volumes:
- sites:/home/frappe/frappe-bench/sites
- logs:/home/frappe/frappe-bench/logs

configurator:
image: frappe/erpnext:${APP_VERSION}
container_name: ${APP_NAME}-configurator
deploy:
restart_policy:
condition: none
entrypoint:
- bash
- -c
depends_on:
- db
command:
- >
ls -1 apps > sites/apps.txt;
bench set-config -g db_host $$DB_HOST;
bench set-config -gp db_port $$DB_PORT;
bench set-config -g redis_cache "redis://$$REDIS_CACHE";
bench set-config -g redis_queue "redis://$$REDIS_QUEUE";
bench set-config -g redis_socketio "redis://$$REDIS_SOCKETIO";
bench set-config -gp socketio_port $$SOCKETIO_PORT;
environment:
DB_HOST: db
DB_PORT: "3306"
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
- logs:/home/frappe/frappe-bench/logs

create-site:
image: frappe/erpnext:${APP_VERSION}
container_name: ${APP_NAME}-create-site
depends_on:
- configurator
deploy:
restart_policy:
condition: none
volumes:
- sites:/home/frappe/frappe-bench/sites
- logs:/home/frappe/frappe-bench/logs
entrypoint:
- bash
- -c
command:
- >
wait-for-it -t 240 db:3306;
wait-for-it -t 120 redis-cache:6379;
wait-for-it -t 120 redis-queue:6379;
wait-for-it -t 120 redis-socketio:6379;
export start=`date +%s`;
until [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".db_host // empty"` ]] && \
[[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".redis_cache // empty"` ]] && \
[[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".redis_queue // empty"` ]];
do
echo "Waiting for sites/common_site_config.json to be created";
sleep 5;
if (( `date +%s`-start > 120 )); then
echo "could not find sites/common_site_config.json with required keys";
exit 1
fi
done;
echo "sites/common_site_config.json found";
bench new-site frontend --no-mariadb-socket --admin-password=${APP_PASSWORD} --db-root-password=${DB_ROOT_PASSWORD} --install-app erpnext --set-default;

db:
image: mariadb:10.6
container_name: ${APP_NAME}-db
healthcheck:
test: mysqladmin ping -h localhost --password=${DB_PASSWORD}
interval: 1s
retries: 15
deploy:
restart_policy:
condition: on-failure
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --skip-character-set-client-handshake
- --skip-innodb-read-only-compressed # Temporary fix for MariaDB 10.6
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
volumes:
- ./data:/var/lib/mysql
#ports:
# - "${DB_PORT}:3306"

frontend:
image: frappe/erpnext:${APP_VERSION}
container_name: ${APP_NAME}-frontend
deploy:
restart_policy:
condition: on-failure
command:
- nginx-entrypoint.sh
environment:
BACKEND: backend:8000
FRAPPE_SITE_NAME_HEADER: frontend
SOCKETIO: websocket:9000
UPSTREAM_REAL_IP_ADDRESS: ${APP_HTTP_IP}
UPSTREAM_REAL_IP_HEADER: X-Forwarded-For
UPSTREAM_REAL_IP_RECURSIVE: "off"
PROXY_READ_TIMOUT: 120
CLIENT_MAX_BODY_SIZE: 50m
volumes:
- sites:/home/frappe/frappe-bench/sites
- logs:/home/frappe/frappe-bench/logs
ports:
- "${APP_HTTP_PORT}:8080"

queue-default:
image: frappe/erpnext:${APP_VERSION}
container_name: ${APP_NAME}-queue-default
deploy:
restart_policy:
condition: on-failure
command:
- bench
- worker
- --queue
- default
volumes:
- sites:/home/frappe/frappe-bench/sites
- logs:/home/frappe/frappe-bench/logs

queue-long:
image: frappe/erpnext:${APP_VERSION}
container_name: ${APP_NAME}-queue-long
deploy:
restart_policy:
condition: on-failure
command:
- bench
- worker
- --queue
- long
volumes:
- sites:/home/frappe/frappe-bench/sites
- logs:/home/frappe/frappe-bench/logs

queue-short:
image: frappe/erpnext:${APP_VERSION}
container_name: ${APP_NAME}-queue-short
deploy:
restart_policy:
condition: on-failure
command:
- bench
- worker
- --queue
- short
volumes:
- sites:/home/frappe/frappe-bench/sites
- logs:/home/frappe/frappe-bench/logs

redis-queue:
image: redis:6.2-alpine
container_name: ${APP_NAME}-redis-queue
deploy:
restart_policy:
condition: on-failure
volumes:
- ./redis-queue-data:/data

redis-cache:
image: redis:6.2-alpine
container_name: ${APP_NAME}-redis-cache
deploy:
restart_policy:
condition: on-failure
volumes:
- ./redis-cache-data:/data

redis-socketio:
image: redis:6.2-alpine
container_name: ${APP_NAME}-redis-socketio
deploy:
restart_policy:
condition: on-failure
volumes:
- ./redis-socketio-data:/data

scheduler:
image: frappe/erpnext:${APP_VERSION}
container_name: ${APP_NAME}-scheduler
deploy:
restart_policy:
condition: on-failure
command:
- bench
- schedule
volumes:
- sites:/home/frappe/frappe-bench/sites
- logs:/home/frappe/frappe-bench/logs

websocket:
image: frappe/erpnext:${APP_VERSION}
container_name: ${APP_NAME}-websocket
deploy:
restart_policy:
condition: on-failure
command:
- node
- /home/frappe/frappe-bench/apps/frappe/socketio.js
volumes:
- sites:/home/frappe/frappe-bench/sites
- logs:/home/frappe/frappe-bench/logs

volumes:
logs:
sites:

env.txt

下面是 env.txt 的内容,之所以没用 .env 是为了方便在 File Station 中方便修改,但是带来的不方便之处是启动时需要指定 --env-file,当然在 docker-compose.yml 中指定也是可以的

1
2
3
4
5
6
7
8
9
10
11
12
# ERPNext config
APP_NAME=erp
APP_VERSION=v14.23.0
APP_HTTP_IP=192.168.0.197
APP_HTTP_PORT=6380
APP_PASSWORD=admin

# MariaDB config
DB_HOST=db
DB_PASSWORD=twj9nwyoutRei9C4VV
DB_ROOT_PASSWORD=4aixKdghP3j56hPB8k
DB_PORT=3336
  • APP_NAME: 主要影响生成的容器名称的前缀

  • APP_VERSIONERPNext 的版本, 老苏测试过v14.22.3v14.23.0,其他版本没试过;
  • APP_HTTP_IP:主机 IP,要根据你自己的群晖主机 IP 修改;
  • APP_HTTP_PORT:这是访问 ERPNext 服务的的本地端口,不冲突就行;
  • APP_PASSWORD:管理员密码,建议登录成功之后再改;
  • DB_HOST:数据库主机,不要改;
  • DB_PASSWORD:数据库密码,建议改;
  • DB_ROOT_PASSWORD:数据库管理员密码,建议改;
  • DB_PORT:数据库本地端口,不冲突就行,默认老苏在 docker-compose.yml 中已经注释掉了端口;

上面两个文件,老苏放在了 https://github.com/wbsu2003/synology/tree/main/ERPNext

安装

采用 docker-compose 方式运行

1
2
3
4
5
6
7
8
9
10
# 新建文件夹 erpnext 和 子目录
mkdir -p /volume2/docker/erpnext/{data,redis-cache-data,redis-queue-data,redis-socketio-data}

# 进入 erpnext 目录
cd /volume2/docker/erpnext

# 将 docker-compose.yml 和 env.txt 两个文件放入当前目录

# 一键运行
docker-compose --env-file env.txt up -d

如果一键启动总是超时,可以加个 timeout 参数

1
2
# 超时设置
docker-compose --env-file env.txt up -d --timeout 120

运行

如果你没有修改 APP_HTTP_PORT的值,你可以在浏览器中打开 http://群晖IP:6380来访问 ERPNext.

第一次启动的过程是比较长的,因为脚本中使用了 wait-for-it,好几处都是 -t 120,老苏甚至把数据库的改为了 wait-for-it -t 240 db:3306;,如果能看到登录界面,说明安装成功了

  • 默认的账号是 Administrator,密码就是前面设置的 APP_PASSWORD 的值,如果你没改的话,那就是 admin

软件启动后,正常情况下,erp-configuratorerp-create-site 会停掉,因为它们已经完成了自己的使命

但如果出现👇的错误

在老苏的机器上还是会有一定的几率发生,不要慌,我们还有补救措施,请往下看

则还需要执行一次下面的命令

参考文档:

  • https://github.com/frappe/frappe_docker/blob/main/docs/site-operations.md
  • https://github.com/frappe/frappe_docker/issues/711
1
2
3
4
5
# 设置新站点
docker-compose --env-file env.txt exec backend bench new-site <site-name> --no-mariadb-socket --admin-password=<管理员密码> --db-root-password=<数据库root账户的密码> --install-app erpnext --set-default

# 示例
docker-compose --env-file env.txt exec backend bench new-site frontend --no-mariadb-socket --admin-password=admin --db-root-password=4aixKdghP3j56hPB8k --install-app erpnext --set-default

其中:

  • <site-name> 对应于 docker-compose.yml 中前端的 service name 的名称 frontend,这个在 nginx 的设置中也用到了;
  • <管理员密码> 对应前面 env.txt 中的 APP_PASSWORD 的值;
  • <数据库root账户的密码> 对应前面 env.txt 中的 DB_ROOT_PASSWORD 的值;

之所以会出现这样的情况,应该还是容器编排的启动顺序上有问题,这些命令按道理在 erp-create-site 容器中应该是要被执行的

之后,如果容器停止了,再启动也是需要时间的,你太快打开网址,会看到下面这样的界面

登录成功后,第一次还需要设置

语言有时候能弹出下拉,但是有时候又不行,不过可以直接输入,现在已经支持 简体中文

国家支持下拉,但可能输入更快

设置用户

设置公司

设置组织

设置完成

现在可以开始使用了

至于反代,老苏试过 npm ,正常设置就可以,无论你的域名有没有端口,都是可以正常访问的。

参考文档

ERPNext: Free and Open Source Cloud ERP Software
地址:https://erpnext.com/

frappe/erpnext: Free and Open Source Enterprise Resource Planning (ERP)
地址:https://github.com/frappe/erpnext

frappe/frappe_docker: Docker images for production and development setups of the Frappe framework and ERPNext
地址:https://github.com/frappe/frappe_docker
Home
地址:https://docs.erpnext.com/