
工单管理系统这东西很多团队一开始并不重视工单靠聊天记录、Excel表格甚至口头传达等出了问题才想起来要一套正儿八经的系统。但真要自研一套开发周期长、维护成本高直接买商业版对很多中小团队来说又是一笔不必要的开销。开源方案就成了最务实的选择而Ferry就是其中比较值得关注的一个。Ferry是一套基于Go语言开发的开源工单管理系统前端用Vue做界面整体架构轻量、部署简单功能上覆盖了工单录入、流转审批、SLA时效、用户与角色权限、系统配置、知识库等常见运维场景需求。最吸引人的地方在于它打包成了Docker镜像一条命令就能把整套系统拉起来对没有专职运维的小团队或者想快速验证流程的技术同学来说省去了大量环境搭建和依赖配置的时间。这篇文章就围绕小事是怎么把Ferry跑起来的来写。目标读者是有一定Linux或Windows使用基础、但没怎么碰过Docker的新手。我会把从Docker环境准备到Ferry镜像下载、容器启动、系统初始化的完整过程拆开讲清楚每一步都说明白为什么要这么做以及实测中容易踩的坑。读完这篇文章你可以在半小时内拥有一套可用的工单系统并且知道后续怎么升级、备份、排查问题——即便你在这之前从来没装过Docker。1. 项目整体认知与方案选型思路1.1 Ferry工单系统到底能做什么很多刚接触开源项目的人看到工单管理系统这个名字会下意识认为它是给IT运维部门用的。实际上Ferry的适用范围比想象中宽很多。它本质上是把某个人提出需求 → 负责人派单 → 处理人反馈 → 发起人确认 → 归档这条流程规范化所以售后客服、行政后勤、产研协同、设备报修等场景都能套用。Ferry的核心功能模块可以分成这么几块工单全生命周期管理创建、分派、处理、归档、重新打开状态流转清晰可追踪。工单模板与表单设计不同类型的问题可以配置不同字段和必填项方便收集结构化信息。多层审批流与SLA统计工单超过预设时限会自动提醒或升级适合对响应时效有要求的部门。用户、角色、菜单权限支持精细到按钮级别的权限控制不同部门的数据可以隔离查看。系统管理与知识库内置FAQ、文档沉淀模块常见问题可以直接从知识库中检索解决。对一个小团队来说部署Ferry相当于二十人左右的内部支撑团队有了一套标准化流程入口。它的部署形态是一体化平台Web端管理后台加后端服务端前台申请端都由那一个镜像提供访问入口不用再单独部署前端文件。1.2 为什么推荐用Docker部署FerryFerry本身也支持直接编译二进制运行但把整套环境跑起来对新手来说难度不小。它依赖MySQL数据库还需要初始化表结构和默认数据再加上前端静态资源托管的配置稍有不慎就会卡在某一步排查半天还是起不来。把应用装进Docker容器后镜像里已经把所有运行时依赖打包好了。你不需要关心Go版本、Node版本也不需要手工配置MySQL账号密码只需要按文档写一段docker-compose配置容器之间自动联网、自动完成数据初始化。想删除重来的时候停掉容器、删掉数据目录系统就干净归零了不会在宿主机上留下一堆残留进程和文件。用Docker部署还有一层实际考虑版本隔离。Ferry后续升级时可以同时跑新版容器作验证等确认稳定再切换端口给生产用。整个过程对现有服务不产生侵入这是二进制部署很难做到的。1.3 镜像版本说明anyulei/ferry:1.0.1是什么很多人第一次在Docker Hub上搜Ferry会看到一堆镜像名容易分不清该拉哪个。标题里提到的anyulei/ferry:1.0.1是Ferry项目作者打包发布的Docker镜像。这里解释一下镜像命名规则anyulei是镜像发布者的账号名ferry是镜像仓库名后面的1.0.1是标签代表这个镜像对应Ferry的1.0.1版本。你在拉取时务必带上这个标签不要图省事只写anyulei/ferry或者anyulei/ferry:latest。最新标签虽然在拉取时省事但它指向的内容可能随作者重新构建而变化不能保证和这套教程里的初始化步骤完全一致。稳妥起见我后续所有命令都以1.0.1这个固定版本为例。这个镜像按照我实测的情况内部已经内置了初始化数据结构与必要依赖。你不需要自己写一堆建表SQL启动容器时会根据预设配置自动创建数据库、写入初始管理员账号。这也是为什么我推荐小白直接走这套镜像路线而不是从源码编译。2. 部署前的环境准备与基础认知2.1 Docker环境搭建Windows和Linux两条路线在正式接触Ferry之前先把Docker环境搞定。这一步做不好后面所有命令都会报错所以值得多花几分钟把基础打牢。如果你手头是一台Windows电脑我建议直接安装Docker Desktop。下载安装包之后重点检查两件事一是电脑的BIOS里必须开启CPU虚拟化Intel的VT-x或AMD的SVM二是Windows功能里勾选适用于Linux的Windows子系统和虚拟机平台两项。很多Windows用户遇到的Docker Desktop failed to start because virtualisation support wasnt detected报错就出在这两点上。装完Docker Desktop后不用急着跑Ferry先用docker version命令确认服务端和客户端版本都能正常打印。如果你用的是Linux服务器操作路径更直接。以Ubuntu为例官方安装方式是用apt源安装不要用系统自带的旧版docker.io包那个版本太老很多新特性不支持。安装完别忘了把当前用户加入docker用户组sudo usermod -aG docker $USER newgrp docker这一步做完之后你再运行docker命令就不用每次加sudo了。我见过太多新手在这一步没做后面所有命令前都带着sudo一旦写成docker-compose又遇到权限问题非常容易劝退。2.2 部署前必须搞懂的4个Docker概念直接上手跑命令当然也能跑通但过程中一旦出问题你会完全不知道从哪排查。所以我先用最通俗的方式把四个核心概念过一遍后面所有操作都建立在这之上。镜像相当于一个打包好的操作系统应用模板只读不能直接运行。就好比你下载了一个Windows安装盘ISO里面什么都有但它本身不是一个正在运行的系统。容器由镜像启动出来的运行实例可以启动、停止、删除。每个容器相当于一台隔离的小电脑有自己的文件系统、网络、进程空间。你对容器内部做的修改在容器重建后会丢所以需要挂载数据卷。数据卷宿主机上的一个目录映射进容器内部用来持久化存储数据。比如Ferry的MySQL数据文件必须放到数据卷里否则容器一删数据全没了。端口映射容器内部的服务监听在某个端口比如Ferry监听8080但外部访问需要通过宿主机的IP加映射端口。就像小区里每家每户有自己的门牌号你必须开一道门让外面的人能进来。理解了这四点之后再看docker run那一长串参数就不会觉得玄乎了。前面那些-p、-v、--name之类的参数本质上都是在配置外面怎么进到容器里面以及容器的数据存在哪里。2.3 下载Ferry镜像前的准备工作镜像拉取速度是很多国内新手遇到的第一个痛。Docker默认从Docker Hub拉镜像网络情况不好的时候可能一个几十MB的镜像都要等好几分钟甚至直接超时。针对这种情况建议提前配置镜像加速器。Linux下修改/etc/docker/daemon.jsonWindows下在Docker Desktop的Settings → Docker Engine里修改配置加入国内可用的镜像源地址改完保存重启Docker{ registry-mirrors: [ https://docker.m.daocloud.io, https://dockerproxy.com ] }这里说明一下镜像加速器只是加速拉取镜像的过程不影响容器运行时的网络访问。如果你在内网环境或者网络受限场景也可以在有外网的机器上先把镜像拉下来用docker save导出为tar包再传进目标服务器用docker load导入。这是离线环境部署的通用做法Ferry同样适用。镜像准备好的标准是docker images能看到anyulei/ferry这一行标签是1.0.1大小在几百MB级别。如果这步正常下面就可以正式开工了。3. Docker部署Ferry工单系统的完整实操3.1 拉取镜像并检查基础配置接下来所有命令都在终端里执行。先用一条命令把镜像拉下来docker pull anyulei/ferry:1.0.1拉取过程如果长时间卡住不动多半是网络问题按前面说的方法配置镜像加速后重试。镜像拉完后先不要急着跑容器我做了一件新手容易忽略但很值得做的一件事——看一眼这个镜像暴露了什么端口、声明了哪些环境变量、需要挂载哪些目录docker image inspect anyulei/ferry:1.0.1重点看Config.ExposedPorts、Config.Env和Volumes三个字段。我实测这个镜像声明的端口是8080API及Web管理端统一入口数据目录在/data目录。有了这些信息你在写docker-compose的时候端口映射和数据挂载就不会瞎猜了。再强调一次不要看到conductor就慌感受不到可视化图表也不要紧把握住端口8080、数据目录/data这两个关键点整个部署就稳了。3.2 编写docker-compose.yml的完整过程我建议用docker-compose而不是直接用docker run。理由很直接compose文件把端口、数据卷、环境变量都写在一起方便版本管理以后换服务器迁移环境拷贝一个文件就能恢复部署。在宿主机上建一个专门放Ferry数据的目录执行mkdir -p /opt/ferry/data cd /opt/ferry然后在/opt/ferry目录下创建docker-compose.yml内容如下version: 3 services: ferry: image: anyulei/ferry:1.0.1 container_name: ferry ports: - 8080:8080 volumes: - /opt/ferry/data:/data environment: - MYSQL_ROOT_PASSWORDYourStrongRootPwd - MYSQL_DATABASEferry - MYSQL_USERferry - MYSQL_PASSWORDYourFerryPwd restart: unless-stopped这里面的设计思路挨个解释一下。端口映射8080:8080左边是宿主机端口右边是容器内部端口。如果你服务器上的8080已经被其他服务占了可以改成18080:8080这样外部访问就用18080。新手最常见的端口冲突错误就是bind: address already in use改左侧端口就能解决。数据卷挂载/opt/ferry/data:/data作用是把容器的数据目录映射到宿主机。Ferry的MySQL数据库文件、上传文件、系统配置都会存在这个目录下。换机器迁移时打包这个目录加上compose文件整套系统就跟着走了。环境变量里的MYSQL_ROOT_PASSWORD、MYSQL_DATABASE、MYSQL_USER、MYSQL_PASSWORD是给容器内置MySQL设置初始化密码和业务库名。这些变量只在第一次启动时生效之后改动不会自动修改已有数据库。3.3 启动容器与初始化系统配置写完后执行docker compose up -d首次启动时间比较长因为容器内部要初始化MySQL表结构、写入种子数据、创建默认管理员整个过程可能需要一两分钟。这时候不要急着关掉终端反复重试先用这条命令观察日志docker logs -f ferry日志里出现类似database migration successful或者server started on port 8080之类的输出就说明初始化完成、服务已经起来了。如果日志一直在滚动或者出现红色报错再针对报错内容排查。容器启动早期的常见假象是docker ps看到容器状态是Up但页面访问不通。原因通常是MySQL初始化还没完成容器进程还在等待数据库就绪。docker ps显示的是进程级状态不等于业务可用。正确做法是看日志不要看状态灯。等日志稳定后执行docker ps确认两个信息容器状态为Up端口映射列能看见0.0.0.0:8080-8080/tcp。3.4 验证部署成果并完成首次登录验证是否成功最直接的方式就是打开浏览器输入http://服务器IP:8080如果你是本机部署直接访问http://localhost:8080。页面能弹出Ferry的登录界面说明Web端已经对外提供服务了。Ferry的初始管理员账号和密码在首次初始化时会自动生成。这个信息一般在容器日志里能看到运行docker logs ferry 21 | grep -i admin\|password\|账号\|密码看到初始管理员账号后用浏览器登录进入后台第一件事是修改默认密码。工单系统涉及内部流程数据默认口令不及时处理等于把系统大门敞给所有知道初始密码的人。登录后去用户管理界面找到管理员账号点修改密码设置一个强度足够的密码。到这里Ferry工单系统的核心部署就已经结束了。你可以在后台创建部门、添加用户、配置工单分类和模板然后发给同事使用。整个流程走下来新手大概需要20到40分钟其中大头时间是在等镜像下载和首次启动初始化。4. 常见问题与排查技巧实录4.1 端口冲突引起的启动失败docker compose up -d执行后终端报错bind: address already in use是最常见的问题。原因一般是宿主机上已经有进程占用了8080端口。排查方法ss -lntp | grep 8080看到有进程监听8080确认那个进程是不是必须保留的。如果能停掉直接停掉再启容器如果不能停建议修改compose文件里的左侧端口映射到其他空闲端口。千万不要把右侧端口改了右侧端口是容器内部Ferry监听的修改后反而会连不上。4.2 Docker权限问题很多新手执行docker命令时报错permission denied while trying to connect to the Docker daemon socket。这个报错的意思是当前用户没有访问Docker服务进程的权限。执行sudo usermod -aG docker $USER newgrp docker然后重新登录终端会话或者重启Docker Desktop问题基本解决。注意不要在容器内部执行docker命令除非你专门在容器里挂了Docker socket否则容器里默认没有可用的Docker CLI权限。4.3 首次启动后页面一直打不开这个问题细分成两种情况。第一种是日志已经在正常输出但浏览器访问超时。检查防火墙。云服务器用户重点检查安全组入方向规则看8080端口是否放行本地虚拟机用户检查系统防火墙sudo ufw status如果防火墙开启了但没放行8080执行sudo ufw allow 8080。云服务器厂商的安全组规则不在系统内需要登录云控制台去配置这一步最容易被忽略。第二种是容器一直处于Restarting状态。查看日志会发现MySQL或初始化脚本在报错。这种情况优先考虑数据卷权限问题。如果宿主机的/opt/ferry/data目录权限过严容器内进程无法读写启动就会失败。执行chown -R 1000:1000 /opt/ferry/data这里的1000是容器内默认用户的UID具体数字以镜像实际运行用户为准可以先docker exec进入容器看id -u确认。把数据目录权限改成容器内用户可写重启容器基本能恢复。4.4 忘记管理员密码的解决办法Ferry不管哪种版本都有一个通用的兜底方案清掉数据卷让容器重新初始化。这个方法最直接但会把系统里的工单数据、用户数据全部清空只适合还没正式使用或者数据可以舍弃的情况。操作方式docker compose down rm -rf /opt/ferry/data/* docker compose up -d重新初始化后系统回到初始状态用日志里打印的默认管理员账号密码登录再重新配置即可。如果系统里已经有重要数据就不建议用这个方法了而是想办法进数据库手工重置管理员密码。这个操作涉及Ferry内部表结构不同分支有差异建议直接查容器内MySQL中user表的结构用标准SQL更新密码字段。实际操作为了安全考虑还是更推荐在系统还没产生大量数据前养成先备份的好习惯。4.5 Docker网络不通的排查思路有时候容器启动了日志正常但页面就是访问不了docker ps看端口映射也正常。这时要检查容器与宿主机的网络连通情况。在宿主机上执行docker exec -it ferry ping 宿主机IP如果容器内无法ping通宿主机多半是Docker默认桥接网络出问题重启docker服务即可sudo systemctl restart docker重启之后容器一般会自动恢复因为compose文件里设置了restart: unless-stopped。网络问题在Docker里排查思路比较固定先看docker network ls确认网络存在再看容器是否连接到该网络最后检查映射端口是否监听。5. 日常运维、备份与后续扩展建议5.1 容器日志与开机自启管理Ferry部署完成之后日常运维中需要关注的其实没几件事。首先是容器是否一直在跑可以用docker ps看状态。其次是日志里有没有异常报错尤其是磁盘空间不足导致的MySQL写入失败这个在工单量变大后需要注意。如果使用systemd管理Docker服务设置Docker开机自启sudo systemctl enable dockerdocker-compose.yaml里配置了restart: unless-stopped之后只要Docker服务随系统启动Ferry容器会自动跟着拉起来不需要额外写系统服务文件。这一点对小白来说非常友好Firewall等系统配置都不用单独为Ferry定制。5.2 数据备份与恢复工单系统的数据是核心资产必须做好备份。最简单的备份方式是把/opt/ferry/data目录整体打包tar czf ferry-backup-$(date %F).tar.gz /opt/ferry/data备份文件建议拷贝到另一台机器或对象存储不要只放在本机磁盘里。恢复时在干净的Docker环境下解压备份包到/opt/ferry/data先清空原目录再docker compose up -d启动容器即可。恢复到什么样的数据粒度取决于备份时间点所以备份频率根据工单量自己定推荐至少每天一次。5.3 版本升级与二次开发方向Ferry后续如果出了新版本镜像升级流程也不复杂。先把旧容器停掉备份数据卷再拉新版本镜像修改compose文件里的镜像标签执行docker compose up -d即可。如果新版本数据库结构有变更容器启动时一般会自动执行迁移脚本但你仍然要在升级前确认数据卷备份可用以防迁移失败需要回滚。从二次开发的角度看Ferry整体的技术栈是前后端分离后端Go语言接口清晰前端Vue工程可独立打包。如果团队有开发能力可以在官方基础上扩展自己的工单审批流、对接企业微信或钉钉机器人通知或者通过API把工单系统接到内部的监控告警平台。Docker部署的天然隔离优势在这里体现得很明显开发环境改坏了直接删容器重建不影响生产实例。写在最后把这套系统跑起来之后我对Ferry这个项目最大的体会是它对小团队非常友好不需要一上来就搞一堆复杂配置核心业务闭环开箱即用。而Docker作为部署承载层价值不仅仅在于一键启动更在于给了你一个随时可以推倒重来的安全边界。如果你之前没有接触过容器技术拿Ferry当第一个练手项目也非常合适——它能让你在完成一个真实可用系统的过程中顺带把镜像、容器、数据卷、端口映射这些核心概念全部实践一遍。还有一个小技巧 部署成功之后建议先把docker-compose.yml文件提交到Git仓库或者云盘。以后无论你是换服务器、恢复环境还是给别人推荐这套方案有了这个文件再加上上面的步骤五分钟就能把一套相同的工单系统复制出来。这才是Docker部署最让人舒服的地方——环境不再是个黑盒而是可以随身携带的配置。