☰
Ubuntu 22.04 + Docker 部署 ERPNext14 全流程:从环境配置到避坑指南
2026/10/16 22:08:53 网站建设 项目流程

简介:对于需要在虚拟机上快速部署ERPNext14的运维人员与开发者,这份docx操作指南提供了从零开始的全程参考。文档基于Ubuntu22.04.5,讲解了Git、Docker、Docker Compose的安装与配置,涵盖了官方GPG密钥校验、阿里云软件源设置、docker用户组权限,以及daemon.json镜像加速配置等关键环节。随后通过docker compose命令拉起汉化开箱即用版ERPNext,并在浏览器中访问使用。资源共1个文件,为docx格式,压缩包仅321KB,内容以命令说明和验证步骤为主,轻量却完整。目前已有629人学习下载,适合需要快速上手ERPNext14或希望了解Docker化部署流程的读者。按照文中步骤操作,可以有效避开Docker拉取镜像失败、Compose权限不足等常见问题,实现企业级ERP环境的快速搭建。

1. 从翻车到跑通:为什么选择 Ubuntu 22.04 + Docker 部署 ERPNext14

很多人以为 ERPNext 这种开源 ERP 系统装起来很简单,真上手不是那么回事。尤其是想在虚拟机上跑通 ERPNext14,Ubuntu 22.04 配 Docker 这条路,版本选不对、镜像拉不下来、权限没配好,每一步都可能卡住大半天。最典型的翻车场景是:Docker 装完了,docker compose up -d 拉取镜像时一直超时;或者是 docker 命令提示 permission denied,折腾半天发现是用户组没加对。这次在 VMware 虚拟机的 Ubuntu 22.04.5 上,用 Docker 方式装 ERPNext14,从 git、docker、docker-compose 到镜像加速配置和常见问题排查,尽量把你可能踩的坑一次性填平。适合想快速搭一套 ERP 环境做测试、演示或实施的开发者,照着走完就能跑通。

2. 虚拟机打底:VMware 里的 Ubuntu 22.04 与 Git 安装验证

2.1 VMware 创建虚拟机时的资源配置建议

我这边用的是 VMware 装 Ubuntu 22.04.5,镜像装好之后第一件事就是把虚拟机的资源配置确认清楚。ERPNext14 跑起来不是一个容器,而是前端、后端、数据库、缓存一整套,所以虚拟机资源别给得太抠。内存建议至少 8GB,CPU 4 核,磁盘 60GB 起步。之前试过 20GB 磁盘加 4GB 内存,容器起来之后数据库初始化到一半直接 OOM,日志里全是 Killed 字样,根本没得救。

网络这块用 NAT 模式就行,宿主机和虚拟机之间能互相访问,后面浏览器直接访问 localhost 逻辑上才通。创建虚拟机向导里选择 Ubuntu 22.04.5 的 ISO 镜像,安装到询问额外软件时,顺手把 OpenSSH server 勾上。这样后续不管是用 MobaXterm 还是 Xshell 连进去操作,都比在 VMware 窗口里敲命令舒服,复制粘贴命令也不会因为剪贴板问题翻车。

提示:如果手上没有 22.04 的镜像,别随意拿 24.04 顶上。ERPNext14 的 compose 文件、依赖包在 22.04 LTS 上验证得最多,换版本容易遇到 systemd 服务和 docker 生态的兼容差异,最后排查起来玄学问题一堆。

2.2 系统更新与依赖包安装

装完系统进入终端,先别急着装东西,把软件源和系统包整体刷新一遍。Ubuntu 22.04 刚装完时软件源指向官方 CDN,国内虚拟机拉取速度一般,更新这步多等等就好。

sudo apt update sudo apt upgrade sudo apt full-upgrade

三段命令各干各的事:update 只同步软件源索引,upgrade 升级已安装软件包,full-upgrade 会把内核、依赖关系变动的包也一起处理。ERPNext 依赖的容器运行时和存储驱动跟内核模块有关系,所以 full-upgrade 这步建议跑,别跳。

跑 upgrade 的过程中可能弹出类似“Daemon configuration changed,restart services automatically?”的蓝框,这是系统服务需要重启的提示。我一般选择 No 让系统自己按需重启,避免误杀当前终端会话。如果你在远程 SSH 里执行,选 Yes 可能导致连接突然断开,那就等重启完再连一次,不是什么大事。

2.3 Git 安装与版本验证

Git 是接下来的基础工具,因为 ERPNext 的开箱即用版部署文件要从 gitee 仓库拉下来,没 git 寸步难行。Ubuntu 22.04 的 apt 源里带的就是 Git 2.34.1,这个版本对 gitee 的 HTTPS 克隆完全够用,不用特意加 PPA 装新版。

sudo apt-get install git git --version

安装完成后 git --version 会输出类似 git version 2.34.1 的信息。看到这个输出就说明装好了。这里有个小坑值得说:有些教程里把 --version 写成了全角短横线的形式,你复制到终端里执行会报 command not found。终端只认 ASCII 的半角减号,手敲的时候注意输入法别开着中文状态。

3. Docker 安装:GPG 密钥、阿里源、用户组三步走

3.1 安装 HTTPS 依赖包:为什么 docker-ce 需要这些先决组件

Docker 官方仓库走的是 HTTPS 通道,Ubuntu 默认的 apt 配置并不完全支持从 HTTPS 源拉取软件包元数据,所以得先把依赖装齐。这一步少了哪个包,后面 add-apt-repository 都会报错,属于前置条件。

sudo apt install apt-transport-https ca-certificates curl software-properties-common

四个包的作用分别是:apt-transport-https 让 apt 支持通过 HTTPS 协议访问软件源;ca-certificates 提供 CA 证书信任链,否则 curl 访问阿里源的 GPG 地址时报证书错误;curl 负责下载远程文件,后面拉 Docker GPG 密钥就要靠它;software-properties-common 提供 add-apt-repository 命令,没有这个命令,下一节添加稳定版软件源那行根本没法执行。缺哪一个都会卡住,所以这条命令别精简。

3.2 添加 GPG 密钥与阿里稳定源

Docker 官方要求先导入 GPG 密钥,apt 才能验证软件包签名,防止源被篡改。这里直接用阿里云的 Docker 镜像源而不是 Docker 官方源,原因很简单:国内虚拟机访问 download.docker.com 经常超时或慢到无法忍受,阿里源速度快得多。

sudo -i curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/docker-ce.gpg

sudo -i 是把当前 shell 切换到 root 环境,因为 gpg 要把解出的密钥文件写到 /etc/apt/trusted.gpg.d/ 目录,普通用户没有写权限,单独 sudo 每条命令也可以但后续步骤多,直接切 root 省事。curl -fsSL 里的 f 表示 HTTP 错误时静默失败、S 显示错误信息、L 自动跟随重定向。管道后面的 gpg --dearmor 把从网络拿到的 ASCII 格式公钥转成二进制格式,写入信任目录。这样 apt 在后续 update 时就能识别这个源是可信的。

密钥导入后建议验证一下指纹,确认公钥确实来自 Docker 官方。Docker 官方公钥的指纹后缀是 0EBFCD88。

apt-key fingerprint 0EBFCD88

执行后终端会列出该指纹对应的公钥信息。如果输出里能找到 Docker Release 相关的签名和有效期,说明密钥没导歪。需要留意的是 apt-key 在较新的 Ubuntu 版本里已经被标记为弃用,但 22.04 里还能用,做一次验证足够。接着添加软件源并刷新索引:

sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" sudo apt update

add-apt-repository 里的 $(lsb_release -cs) 会自动替换成 jammy,也就是 Ubuntu 22.04 的代号。如果这里写死成 focal 或者其他版本代号,apt update 会找不到对应目录。arch=amd64 指定的是当前 CPU 架构,如果你用的是 ARM 架构虚拟机,这里要相应调整。

3.3 安装 docker-ce、docker-ce-cli 与 containerd.io

软件源配置好之后,直接安装 Docker 核心组件。这里必须强调一下,不要图省事用 sudo apt install docker.io 去装 Ubuntu 自带源里的旧版 Docker,那个包版本老、更新机制也和 Docker 官方脱节,后面跑 ERPNext 的 compose 文件可能因为 API 版本问题起不来容器。

sudo apt install docker-ce docker-ce-cli containerd.io

三条组件各有分工:docker-ce 是 Docker 守护进程的主程序,容器创建、网络、存储都由它管理;docker-ce-cli 是命令行客户端,你敲的 docker 命令就是它;containerd.io 是容器运行时,真正负责把容器进程跑起来,docker-ce 在底层调用它。Ubuntu 22.04 上 apt 会装当前仓库里的最新稳定版,安装完成后先验证一下:

docker --version

3.4 用户组配置与运行验证

装完 Docker 直接敲 docker ps 大概率会遇到 permission denied。原因是 Docker 守护进程默认以 root 身份运行,而当前用户不在 docker 用户组里,socket 访问被拒绝。解决方式是把当前用户加入 docker 组,避免每条命令都加 sudo。

sudo usermod -aG docker 你的用户名 su - 你的用户名 docker images

usermod 的 -aG 参数是追加用户到指定组,注意必须带 -a,否则会把用户从其他组全部移除。su - 后面带上用户名是为了重新加载用户的环境变量和用户组信息,单纯用 su 切过去 docker 组可能还是没生效,这是个非常容易踩的细节。执行 docker images 不报权限错误,说明组权限生效了。

Docker 服务的运行状态也要确认一遍。如果刚才的安装步骤自动启动了服务,systemctl status 会显示 active(running);万一没起来,需要手动启动并设置开机自启。

sudo systemctl status docker sudo systemctl start docker sudo systemctl enable docker

到这一步我习惯再执行一次 systemctl restart docker 让所有配置干净地加载一遍,然后看 status 确认没有任何报错日志,最后再跑一次 docker --version 收尾。重启 Docker 不会影响后面的镜像加速配置,反而能让 daemon.json 的修改在下一步及时生效。

4. Docker Compose 安装与镜像加速避坑:daemon.json 配置和拉取失败排查

4.1 Docker Compose 安装:下载可执行文件、赋权与软链接

ERPNext 的开箱即用版不是一个单容器应用,而是通过 pwd.yml 一次性编排前端、后端、数据库、缓存等多容器启动,所以 Docker Compose 是刚需。这里选择下载官方发布的二进制文件安装,而不是用 Ubuntu 源里的旧版 python-docker-compose,后者已经停止维护,对新版 compose 文件的兼容性也不好。

sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

curl 命令中的 $(uname -s)-$(uname -m) 会自动替换成 linux-x86_64,下载对应平台的二进制文件。-L 参数跟随 GitHub Release 的重定向,少了它下载可能拿到一个 JSON 跳转页面而不是真正的可执行文件。chmod +x 赋予执行权限,这步漏了的话后面 docker-compose --version 会报 Permission denied。ln -s 建立软链接到 /usr/bin 是为了让命令在所有用户的 PATH 里都可用,因为有些环境里 /usr/local/bin 没被默认加进 PATH,换个用户登录就找不到命令了。

安装完成后检查版本:

docker-compose --version

正常会输出类似 Docker Compose version v2.x.x 的信息。这里说一下命令名的问题:现在 Docker 官方推荐用 docker compose(空格)的插件模式,但我们手动安装的是独立二进制,所以还是用 docker-compose 这个旧命令名调用。仓库里的 compose 文件格式两种方式都能识别,保持全局统一用 docker-compose 即可。

提示:如果 GitHub 下载超时,常见的做法是从国内镜像站拉 compose 二进制,比如 ghproxy 这类加速地址,或者从另一台已经装好 compose 的机器上把 /usr/local/bin/docker-compose 直接拷贝过来。版本差异不大,不影响后续使用。

4.2 daemon.json 镜像加速器配置:多地址切换

Docker 装好后第一个拦路虎就是从 Docker Hub 拉镜像慢。ERPNext 相关镜像加起来有好几个 GB,如果不配镜像加速,docker compose up 阶段就能让你等到怀疑人生。解决方式是修改 Docker 守护进程的配置文件 /etc/docker/daemon.json,把 registry-mirrors 加速地址填进去。

touch /etc/docker/daemon.json chmod 777 -R /etc/docker/daemon.json vim /etc/docker/daemon.json

chmod 777 是给文件临时开了全部的读写权限,方便 vim 编辑完保存。这里要补一句,生产环境千万别留 777,我习惯改完权限后马上收回来,执行 chmod 644 /etc/docker/daemon.json 恢复成 root 可写、其他用户只读的状态,不然以后排查问题容易被无关进程改动这个文件。

在 vim 里填入如下 JSON 内容:

{ "registry-mirrors": [ "https://docker.registry.cyou", "https://docker-cf.registry.cyou", "https://dockercf.jsdelivr.fyi", "https://docker.jsdelivr.fyi", "https://dockertest.jsdelivr.fyi", "https://mirror.aliyuncs.com", "https://dockerproxy.com", "https://mirror.baidubce.com", "https://docker.m.daocloud.io", "https://docker.nju.edu.cn", "https://docker.mirrors.sjtug.sjtu.edu.cn", "https://docker.mirrors.ustc.edu.cn", "https://mirror.iscas.ac.cn", "https://docker.rainbond.cc" ] }

registry-mirrors 数组里的地址是多个不同的镜像加速服务,Docker 在拉取镜像时会按顺序尝试。多填几个的原因是这些加速服务的稳定性在不同时间段波动很大,有些地址今天能用明天就失效,备选越多,单点挂掉的影响越小。阿里云、百度云、DaoCloud、中科大这些属于国内老牌镜像源,jsdelivr 和 registry.cyou 系列是后起的社区加速,全部保留能提高容错率。

配置写完必须先重启 Docker 守护进程,daemon.json 才会被重新加载。

systemctl restart docker systemctl daemon-reload systemctl restart docker

daemon-reload 是用来让 systemd 重新读取 Docker 服务的 unit 文件,如果 unit 文件没改过,单独执行它没有实际效果。通常的做法是重启一次 docker 服务就够了,但多执行一遍 daemon-reload 再 restart 也无害,算是双保险。配置生效后可以用 docker info 来确认加速器已经注册:

docker info | grep -A 5 "Registry Mirrors"

输出里能看到 Registry Mirrors 下面列出一串 https 地址,说明 daemon.json 的修改已被识别。如果这里显示空白,大概率是 JSON 语法有问题或者 Docker 服务没起来,直接回到第 4.3 节排查。

4.3 常见问题排查:拉取超时、权限不足、端口冲突

下面这几条是我实际部署时踩过的坑,按现象、原因、解决三步写清楚。

第一条,docker compose up -d 拉取镜像时长时间卡住,最终报 net/http: TLS handshake timeout。原因是 registry-mirrors 配置没有生效,或者配置的加速地址已经失效。解决方法是先执行 systemctl restart docker 确保 daemon.json 被加载,再用 docker info 查看当前 Registry Mirrors 列表,确认里面确实有可用的地址。如果列表中出现的地址全部超时,就换一批新的加速地址,改完继续 restart docker。

第二条,docker ps 或 docker images 报 Got permission denied while trying to connect to the Docker daemon socket。原因是当前用户不在 docker 用户组,或者执行了 usermod 但 shell 环境没刷新。解决方法是执行 sudo usermod -aG docker 用户名 把用户加进 docker 组,然后退出终端重新登录,或者直接用 su - 用户名 重新加载环境。只开一个新终端窗口是没用的,组信息在登录时就已经加载进了 shell 会话,必须重新登录。

第三条,systemctl restart docker 后服务起不来,journalctl -u docker 日志里报 json: cannot unmarshal 或者 invalid character。原因是手写 daemon.json 时逗号、引号、大括号写错导致 JSON 解析失败。解决方法是先跑 python3 -m json.tool /etc/docker/daemon.json 校验语法,python 的 json 模块会精确指出第几行第几个字符出错,修好之后再重启。我一般写完 JSON 必校验一遍,绝不直接 restart,这已经成了习惯。

第四条,容器能启动,但浏览器访问虚拟机 IP 或 localhost 时打不开页面。原因可能是宿主机或虚拟机上的 80 端口被其他服务占用,导致容器端口映射失败。解决方法是先 docker-compose ps 看容器状态,如果状态是 Restarting 或者 Exit,用 sudo ss -tlnp | grep :80 查看 80 端口被谁占着。Apache、Nginx 都可能默认监听 80 端口,停掉占用进程,或者把 pwd.yml 里的端口映射改成 8080:80,改完重新 down 再 up 一次。

5. 部署 ERPNext14:从克隆仓库到容器启动

5.1 克隆汉化开箱即用版仓库

环境准备完毕,接下来就是把 ERPNext14 的部署文件拉下来。这里用的是 gitee 上的汉化开箱即用版仓库,比从 GitHub 拉官方 compose 示例折腾的要少。仓库里已经按 ERPNext14 + 依赖服务的容器编排写好了 pwd.yml,还包含了汉化初始化和数据库配置参数,省去对着官方文档一行一行拼环境变量。

git clone https://gitee.com/yuzelin/erpnext_oob_docker && cd erpnext_oob_docker

clone 完成会自动进入仓库目录。在 gitee 上下载这个仓库速度很快,国内网络环境下几秒钟就能完成。进目录后用 ls 看一眼文件结构,确认 pwd.yml 存在并且目录非空。如果 clone 出来是空目录,先看网络代理配置,git 拉取 gitee 通常不需要额外设置代理,空目录大概率是 gitee 对临时匿名访问限流,稍后重试一次即可。

5.2 docker compose 启动并创建数据库

部署文件就位后,直接使用 docker compose 命令启动整套环境。这里用 --project-name 参数指定项目名,-f 指定使用仓库里的 pwd.yml 文件。

docker compose --project-name erpnext_oob -f pwd.yml up -d

参数含义拆开讲:--project-name erpnext_oob 是所有容器共享的项目前缀,在 docker ps 里看到的容器名都会带上这个前缀,方便辨认;-f pwd.yml 告诉 compose 使用当前目录下的 pwd.yml 文件,而不是默认的 docker-compose.yml;up 是创建并启动容器,-d 表示后台运行,不加 -d 的话终端会一直被日志刷屏,而且关掉终端容器也会跟着停。

首次执行这行命令时,compose 会按照 pwd.yml 里的服务定义逐个拉取镜像。ERPNext 的镜像、MariaDB 数据库镜像、Redis 缓存镜像加起来体积不小,拉取时间取决于镜像加速器的实际速度。这个过程里终端会显示每个镜像的 Pulling 进度条。只要不报 TLS timeout 或者 manifest unknown 的错误,就耐心等着。所有镜像拉取完成后,compose 会自动创建容器间的内部网络,然后依次启动数据库、Redis、后端服务、前端服务。数据库的首次初始化会执行 ERPNext 的建表脚本,这一步需要几分钟,期间不要 Ctrl+C 中断。

启动完成后确认容器状态:

docker compose --project-name erpnext_oob -f pwd.yml ps

输出中所有服务的 State 列都显示 Up 或 running(healthy),说明容器层面已经就绪。如果某个服务显示 Restarting 或者 Exit,记下服务名,再用 docker compose logs 查看对应容器的日志。常见的原因是数据库还没初始化完,后端服务连接数据库失败后自动重启,这种是暂时性的,等一两分钟再 ps 一次就会恢复正常。

5.3 访问入口确认与首次登录检查

容器起来后,在 Ubuntu 的 Firefox 浏览器里打开访问地址。这里有个细节要纠正:很多教程写的是 http://localhost/80,其实 80 是端口,访问地址应该是 http://localhost:80,因为 80 是 HTTP 默认端口,直接写成 http://localhost 也行。

# 在浏览器地址栏输入 http://localhost

打开后会看到 ERPNext 的登录页面。第一次访问需要确认管理员账号,ERPNext 默认管理员是 administrator,初始密码通常在仓库的 README 文件里说明,或者从容器初始化日志里查看。如果之前跑过一次初始化但中断了,数据库里可能残留了半初始化的数据,这时候最干净的做法是把容器 down 掉,删除对应数据卷,重新 up 一次,避免在半初始化状态下反复试探。

登录成功后进入 ERPNext 的桌面界面,至少能看到仪表盘、会计、销售、采购、库存、人力资源、项目管理这些核心模块入口。点击任意模块如果能正常打开页面而不是白屏或 502,说明底层的后端服务和数据库连接都是通的。

6. 装完怎么验证跑通:登录页面、容器状态与运维命令

6.1 验证页面能登录、功能模块能打开

部署完成的标准不是容器起来了,而是页面能登录、模块能操作。我会按下面的顺序做一遍完整验证:浏览器打开 http://localhost 看到登录页;用 administrator 账号登录进入桌面;随机点开“会计”和“库存”模块,确认列表页能加载出数据、新建单据按钮可用。如果页面提示 502 Bad Gateway,多半是后端容器挂了,用 docker compose ps 查看是否有容器意外退出,再配合日志定位。

6.2 常用运维命令:重启、停止、查看日志

日常用得最多的运维命令就这几条,够覆盖绝大多数场景:

docker compose --project-name erpnext_oob -f pwd.yml ps docker compose --project-name erpnext_oob -f pwd.yml logs -f backend docker compose --project-name erpnext_oob -f pwd.yml restart docker compose --project-name erpnext_oob -f pwd.yml down

ps 查看容器状态,logs -f 实时跟踪 backend 容器的日志输出,排查登录报错和接口报错都靠它;restart 重启所有服务,适合修改配置后需要整体生效的场景;down 停止并删除容器,但数据卷会保留,下次 up 时数据库数据还在,这一点对升级和回滚很关键。

6.3 我的日常巡检习惯

现在每次部署完 ERPNext,我都不急着收工,而是强制走一遍三段式验证:systemctl status docker 确认 Docker 守护进程健康,docker compose ps 确认所有容器都是 Up 状态,浏览器实际登录一遍并打开两个核心模块。有一次交付虚拟机时我跳过浏览器验证,直接让同事接手,第二天反馈页面打不开,查了半天发现是容器启动顺序问题,数据库晚于后端就绪导致连接失败。从那以后这个验证顺序就成了固定流程,少一步我心里都不踏实。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询