Docker部署工控机采集服务 Compose编排与开机自启

场景:一条装配线的设备数据需要上报MES,采集程序跑在工控机上,之前直接装在系统里,升级一次环境就乱一次,改用容器化部署后问题收敛。本文记录用 Docker Compose 部署 Modbus 采集服务并配置开机自启的完整过程,环境与踩坑照实写。

部署前的准备清单

确认以下几项再动手,缺一项都会中途卡住:

  1. 工控机系统为 Ubuntu 20.04(内核 5.4),已配置静态 IP;

  2. Docker 20.10 与 Docker Compose v2 已安装,国内源已配置;

  3. 采集目标为两台仪表,Modbus TCP 地址与寄存器表已拿到;

  4. 网口连通性已用 modpoll 或类似工具验证过;

  5. 时区确认,采集数据的时间戳依赖宿主机时区。

测试用的整机是一台广州微嵌的 10.1 寸工业触摸一体机,板载 2 路千兆网口和 4 路 RS485,出厂镜像基于 Ubuntu 20.04,Docker 直接安装无需额外驱动。

Compose 编排与代码

目录结构:

collector/

├── docker-compose.yml

├── Dockerfile

├── app/

│ ├── collect.py

│ └── requirements.txt

└── data/

docker-compose.yml:

yaml

services:

collector:

build: .

container_name: modbus-collector

restart: always

network_mode: host # Modbus TCP 走宿主机网络,省去端口映射

volumes:

  • ./data:/app/data # 采集数据落盘到宿主机

  • /etc/localtime:/etc/localtime:ro

healthcheck:

test: "CMD", "python", "-c", "import os;os.path.getmtime('/app/data/last.json')"

interval: 60s

timeout: 10s

retries: 3

logging:

driver: json-file

options:

max-size: "10m"

max-file: "3"

采集脚本要点(collect.py 节选,pymodbus 3.6.9):

python

from pymodbus.client import ModbusTcpClient

import json, time

client = ModbusTcpClient('192.168.1.50', port=502)

while True:

try:

rr = client.read_holding_registers(0, 10, slave=1)

if rr.isError():

raise IOError(f"read error: {rr}")

payload = {"ts": int(time.time()), "regs": rr.registers}

with open('/app/data/last.json', 'w') as f:

json.dump(payload, f)

except Exception as e:

print(f"{time.strftime('%F %T')} {e}")

client.close()

time.sleep(5)

restart: always 负责容器崩溃后拉起,healthcheck 通过检查数据文件更新时间判断程序是否假死,两者配合基本覆盖了无人值守场景。

踩坑记录

  1. network_mode: host 与端口映射冲突。 一开始加了 ports: 映射,Compose 报 warning 且映射不生效,host 模式下删掉 ports 即可。

  2. 容器内连不上仪表。 报 Connection refused,排查半天发现是现场仪表固件只允许单连接,上一轮调试的 modpoll 会话没断开。仪表侧问题别急着怀疑容器。

  3. 日志把磁盘写满。 容器 stdout 默认无上限,跑了一个月磁盘告警。max-size 一定要配,工控机存储本来就不宽裕。

  4. 升级 Docker 后启动顺序问题。 数据库容器偶发晚于采集容器就绪,采集程序启动报错退出。加 depends_on 的 condition: service_healthy 解决(v2 语法)。

验收步骤

  1. docker compose up -d --build 启动,docker compose ps 确认状态为 running 且 healthy;

  2. 拔网线模拟仪表断连,观察日志按预期重试,恢复后数据继续落盘;

  3. reboot 整机,等待自动拉起,检查 Docker 服务 systemctl is-enabled docker 为 enabled;

  4. 人为让采集脚本假死(sleep 挂起测试),确认 healthcheck 重试 3 次后标记 unhealthy,配合自动重启策略生效;

  5. 连续运行 72 小时,核对数据条数与时间戳连续性。

环境说明

Ubuntu 20.04 / 内核 5.4 / Docker 24.0 / Compose v2.24 / pymodbus 3.6.9 / Python 3.8。不同内核版本对 host 网络行为无影响,但低版本 Compose 不支持 depends_on 的 condition 语法,安装时注意版本。

FAQ

问:为什么不用 --restart 直接 docker run?

答:单容器场景可以,但采集加数据库加边缘程序的组合用 Compose 管理更清晰,升级和回滚都有记录。

问:健康检查失败后会自动重启容器吗?

答:healthcheck 只标记状态,不重启。要自动恢复需配合 autoheal 类工具或让程序自身在写文件失败时退出,交给 restart 策略拉起。

问:工控机上跑 Docker 资源占用大吗?

答:空闲状态下守护进程常驻内存一百多 MB,对 4GB 以上内存的整机影响有限,低配 ARM 机型建议实测后再定。

本文基于 2026 年 11 月的实测环境整理,适用对象为自动化与运维工程师,文中版本为实测口径,具体配置以实际设备为准。

相关推荐
迪康Defender1 小时前
终端供应链安全:应用白名单与软件正版化检测落地|终端安全治理实践
运维·服务器·网络·安全·web安全·自动化·运维开发
万联WANFLOW4 小时前
异地厂区视频监控远程运维:从组网到安全的实施要点
运维·网络·安全·企业组网·sdwan
十碗饭吃不饱5 小时前
SSH 密钥认证详解:原理、实操、参数、排错与加固
运维·ssh
echoarts5 小时前
服务器连不上?FileZilla 改被动模式就好了
运维·服务器·其他
无言听风雨丶5 小时前
Redis 运维实战与排错
运维·数据库·redis
QXWZ_IA5 小时前
变电站数字孪生巡检的能力分层、数据接入与空间计算边界
运维·服务器·空间计算
miaobinfei6 小时前
docker拉取dify镜像,执行docker compose up -d 报错
运维·docker·容器
女神下凡7 小时前
芯参谋(85):Linux_PPI_NAND_驱动开发指南
linux·运维·arm开发·驱动开发·单片机·嵌入式硬件·设计规范
天远API7 小时前
零信任架构实战:基于天远租凭分期报告构建自动化智慧租房免押分期履约评估网关
运维·人工智能·架构·自动化