Docker 中使用自定义镜像安装和配置 ERPNext

由于 Docker 在环境隔离、简化部署、可移植性、版本管理和容器生命周期管理方面具有显著优势。所以,使用 Docker 安装部署 ERPNext 也是一种不错的选择。

Docker 能够将 ERPNext 及其依赖项封装在独立的容器中,在确保应用程序的稳定性并避免组件间的干扰的同时还可以降低手动安装时出错的可能性。此外,我们还可以在不同版本之间快速切换而不必担心兼容性问题。

本文以官方文档和论坛为参考整理而来,以手搓代码为主。更主要的是解释一下整个安装流程。

注意:安装过程中会使用到国际网络,所以推荐使用海外服务器

安装 Docker 和 Compose

curl -fsSL https://get.docker.com | bash
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.2.3/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose

前期准备:应用程序配置

第一步:通过 apps.json 文件加载自定义应用程序:

export APPS_JSON='[
  {
    "url": "https://github.com/frappe/erpnext",
    "branch": "version-15"
  },
  {
    "url": "https://github.com/frappe/payments",
    "branch": "version-15"
  },
  {
    "url": "https://{{ PAT }}@github.com/project/repository.git",
    "branch": "main"
  }
]'

配置说明

  1. URL 格式:如果使用私有仓库,需要用个人访问令牌(PAT)进行身份验证。(参考第三条 URL)格式为 http://{{PAT}}@github.com/project/repository.git,其中 {{PAT}} 是你的令牌,project/repository.git 是仓库地址。

  2. 手动添加依赖项:在 apps.json 文件中,需要手动添加依赖项。例如:要安装 HRMS 系统,则需要在文件中加入 HRMS 的地址和版本信息。

  3. 使用分支:branch 字段指定要使用的版本分支。

第二步:将 JSON 文件内容转换为 Base64 编码并存储为环境变量

export APPS_JSON_BASE64=$(echo ${APPS_JSON} | base64 -w 0)

第三步:验证

通过以下步骤验证环境变量 APPS_JSON_BASE64 是否正确设置:

  1. 检查环境变量

使用 echo命令查看 APPS_JSON_BASE64的值:

echo $APPS_JSON_BASE64

这将输出 apps.json 文件的 Base64 编码内容。如果输出的内容看起来像一串随机字符,说明变量已成功设置。

  1. 解码验证
echo $APPS_JSON_BASE64 | base64 --decode

这将输出解码后的内容,应该与刚才配置的 apps.json 文件内容相同。

构建镜像

第一步:从 GitHub 克隆 frappe_docker 仓库

git clone https://github.com/frappe/frappe_docker

如果使用自己的仓库,请注意修改地址。

进入 frappe_docker 目录

cd frappe_docker

第二步:构建镜像

构建镜像,并将镜像命名为 custom:1.0.0

  1. 快速构建

使用 images/layered/Containerfile 文件构建,这个方法通过使用已经构建好的 Docker 镜像来加快构建速度,镜像中已经包含了所需的 Python 和 Node.js 运行环境。

docker build \
  --build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \
  --build-arg=FRAPPE_BRANCH=version-15 \
  --build-arg=APPS_JSON_BASE64=$APPS_JSON_BASE64 \
  --tag=custom:1.0.0 \
  --file=images/layered/Containerfile .
  1. 自定义构建

使用 images/custom/Containerfile 文件构建,这个方法每次都构建基础层和构建层,允许自定义 Python 和 NodeJS 的运行时版本,但构建所需的时间更长。

docker build \
  --build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \
  --build-arg=FRAPPE_BRANCH=version-15 \
  --build-arg=PYTHON_VERSION=3.11.9 \
  --build-arg=NODE_VERSION=18.20.2 \
  --build-arg=APPS_JSON_BASE64=$APPS_JSON_BASE64 \
  --tag=custom:1.0.0 \
  --file=images/custom/Containerfile .

根据自身需求选择即可。

推送镜像(可选)

你可以将构建的镜像推送到公有/私有仓库,以便下次直接拉取。

配置镜像

  1. 打开 compose.yaml 文件
nano compose.yaml
  1. 找到以下开头内容:
x-customizable-image: &customizable_image
  image: ${CUSTOM_IMAGE:-frappe/erpnext}:${CUSTOM_TAG:-${ERPNEXT_VERSION:?No ERPNext version or tag set}}
  pull_policy: ${PULL_POLICY:-always}
  1. 修改为:
x-customizable-image: &customizable_image
  image: custom:1.0.0
  pull_policy: never

配置说明

  • CUSTOM_IMAGE:自定义镜像的名称。如果没有设置,默认会使用 frappe/erpnext 这个镜像。
  • CUSTOM_TAG:自定义镜像的标签。当你使用 CUSTOM_IMAGE 时,必须设置。如果没有设置,系统会默认使用 ERPNEXT_VERSION 的值。
  • PULL_POLICY:Docker 的拉取策略。默认情况下,这个策略是 always,意味着每次运行时都会尝试从远程仓库下载最新的镜像。本地镜像推荐设置为 never,以避免不必要的下载。

安装部署应用

首先,创建配置和资源目录:

mkdir ~/gitops

这将创建一个名为 ~/gitops 的目录,用于存放所有与项目设置相关的资源和环境文件。由于可能会有多个项目需要不同的环境变量,为了更好地管理这些文件的变化,可以考虑将这个目录创建为一个私有的 Git 仓库

安装部署 Traefik

Traefik 是一个反向代理和负载均衡器,主要用于管理和路由流量到多个后端服务,如 Docker 容器或 Kubernetes 应用。安装 Traefik 可以简化服务的访问和管理,类似于 Nginx 或 Apache,但它支持动态配置和自动 HTTPS。

  1. ~/gitops 中创建一个名为 traefik.env 的环境变量文件:
echo 'TRAEFIK_DOMAIN=erp.localhost' > ~/gitops/traefik.env
echo 'EMAIL=admin@erp.localhost' >> ~/gitops/traefik.env
echo 'HASHED_PASSWORD='$(openssl passwd -apr1 changeit | sed -e s/\\$/\\$\\$/g) >> ~/gitops/traefik.env

配置说明

  • 将域名从 erp.localhost 更改为生产环境中使用的域名,并确保DNS 记录指向了服务器的 IP 地址。

  • 将 Let’s Encrypt 的通知邮箱从 admin@erp.localhost. 更改为常用的邮箱。

  • 将密码从 changeit 更改为其他更安全的密码。

  1. 验证

使用 cat ~/gitops/traefik.env 验证刚刚生成的内容。

  1. 部署 traefik 容器
docker compose --project-name traefik \
  --env-file ~/gitops/traefik.env \
  -f overrides/compose.traefik.yaml \
  -f overrides/compose.traefik-ssl.yaml up -d

注意:对于局域网设置,请不要覆盖 overrides/compose.traefik-ssl.yaml

安装部署 MariaDB

  1. ~/gitops 中创建一个名为 mariadb.env 的环境变量文件:
echo "DB_PASSWORD=changeit" > ~/gitops/mariadb.env

将密码从 changeit 更改为其他更安全的密码。

  1. 验证

使用 cat ~/gitops/mariadb.env 验证刚刚生成的内容。

  1. 部署 mariadb 容器
docker compose --project-name mariadb --env-file ~/gitops/mariadb.env -f overrides/compose.mariadb-shared.yaml up -d

安装部署 ERPNEXT

  1. ~/gitops 中创建一个名为 erpnext-one.env 的环境变量文件
cp example.env ~/gitops/erpnext-one.env
sed -i 's/DB_PASSWORD=123/DB_PASSWORD=changeit/g' ~/gitops/erpnext-one.env
sed -i 's/DB_HOST=/DB_HOST=mariadb-database/g' ~/gitops/erpnext-one.env
sed -i 's/DB_PORT=/DB_PORT=3306/g' ~/gitops/erpnext-one.env
sed -i 's/SITES=`erp.example.com`/SITES=\`erp.localhost\`/g' ~/gitops/erpnext-one.env
echo 'ROUTER=erpnext-one' >> ~/gitops/erpnext-one.env
echo "BENCH_NETWORK=erpnext-one" >> ~/gitops/erpnext-one.env
  • 将密码从 changeit 更改为刚才 MariaDB 修改后的密码。
  • erp.localhost 中的域名修改为自己的域名。
  1. 生成 erpnext-one.yaml 文件
docker compose --project-name erpnext-one \
  --env-file ~/gitops/erpnext-one.env \
  -f compose.yaml \
  -f overrides/compose.redis.yaml \
  -f overrides/compose.multi-bench.yaml \
  -f overrides/compose.multi-bench-ssl.yaml config > ~/gitops/erpnext-one.yaml

注意:对于局域网设置,请不要覆盖 compose.multi-bench-ssl.yaml

  1. 部署 ERPNEXT 容器
docker compose --project-name erpnext-one -f ~/gitops/erpnext-one.yaml up -d

创建网站

docker compose --project-name erpnext-one exec backend \
  bench new-site --no-mariadb-socket --mariadb-root-password changeit --install-app erpnext --admin-password changeit erp.localhost

配置说明

  • erp.localhost 替换为自己的域名。

  • mariadb-root-password changeit 替换为刚才设置的 MariaDB 数据库的 root 用户密码。

  • admin-password changeit 是 ERPNext 管理员账户的密码。将其替换为一个更安全的密码。

启用调度器

  1. 进入 docker 容器
docker exec -it erpnext-one-backend-1 bash
  1. 启用调度器
bench --site erpnext.local enable-scheduler
  • erpnext.local 中的域名修改为自己的域名。

执行这个命令后,系统将会启用调度器,使得定时任务能够正常运行。

调试

如果站点没有正常工作可以尝试重启项目几次

停止命令:

docker compose --project-name erpnext-one -f ~/gitops/erpnext-one.yaml down

启动命令:

docker compose --project-name erpnext-one -f ~/gitops/erpnext-one.yaml up -d