Docker容器化部署实战:物联网平台从开发到生产的完整路径
Docker容器化部署实战:物联网平台从开发到生产的完整路径
"在我机器上能跑"这句话在物联网项目里出现的频率比任何其他领域都高。开发环境用Ubuntu 22.04,生产服务器跑CentOS 7,PHP版本差一个minor,扩展依赖不一致,部署当天晚上就得加班排障。Docker解决的就是这个问题。
这篇文章不讲Docker的基础概念,直接上物联网平台的容器化部署实战。从Dockerfile编写、docker-compose编排、到生产环境的镜像构建和CI/CD流水线,每一步都附带可直接复用的配置和踩坑记录。
一、为什么物联网平台特别需要Docker
物联网平台的部署环境多样。有的部署在云服务器上,有的跑在工业网关的ARM板上,有的部署在客户自有的内网机房。不同环境的操作系统、CPU架构、软件版本各不相同。
Docker的核心价值在这种场景下特别明显:
| 痛点 | 传统部署 | Docker部署 |
|---|---|---|
| 环境不一致 | 手动安装依赖,版本漂移 | 镜像锁定环境,到处一致 |
| 多服务依赖 | 手动启动顺序,容易遗漏 | compose编排,一键启动 |
| 回滚困难 | 需要手动卸载和重装 | 切换镜像tag即可 |
| 资源隔离 | 服务共享资源,互相干扰 | 每个容器独立资源限制 |
二、Dockerfile实战
2.1 PHP后端镜像
物联网平台的后端常用PHP。以下是一个生产级PHP-FPM镜像的Dockerfile:
FROM php:8.2-fpm-alpine
# 安装系统依赖和PHP扩展
RUN apk add --no-cache \
libzip-dev \
libxml2-dev \
curl-dev \
&& docker-php-ext-install \
pdo_mysql \
zip \
xml \
bcmath \
opcache
# 配置OPcache
RUN echo "opcache.enable=1" >> /usr/local/etc/php/conf.d/opcache.ini \
&& echo "opcache.memory_consumption=256" >> /usr/local/etc/php/conf.d/opcache.ini \
&& echo "opcache.max_accelerated_files=20000" >> /usr/local/etc/php/conf.d/opcache.ini
# 设置工作目录
WORKDIR /var/www/html
# 复制代码
COPY . /var/www/html
# 设置权限
RUN chown -R www-data:www-data /var/www/html \
&& chmod -R 755 /var/www/html
EXPOSE 9000
2.2 前端Nginx镜像
FROM nginx:alpine
# 复制自定义Nginx配置
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
# 复制前端构建产物
COPY ./dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
2.3 多阶段构建优化
生产镜像应该尽量小。用多阶段构建,把编译和运行分开:
# 阶段1:构建前端
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# 阶段2:运行Nginx
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
多阶段构建的好处是最终镜像不包含Node.js运行时和node_modules,镜像体积从800MB降到50MB以下。
三、docker-compose编排
物联网平台通常包含多个服务:PHP后端、Nginx前端、MySQL数据库、Redis缓存、MQTT消息中间件。用docker-compose一键编排:
version: '3.8'
services:
nginx:
build: ./docker/nginx
ports:
- "80:80"
depends_on:
- php
volumes:
- ./src:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
networks:
- iot_net
php:
build: ./docker/php
volumes:
- ./src:/var/www/html
depends_on:
- mysql
- redis
networks:
- iot_net
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- iot_net
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
ports:
- "6379:6379"
networks:
- iot_net
mosquitto:
image: eclipse-mosquitto:2
ports:
- "1883:1883"
- "9001:9001"
volumes:
- ./docker/mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf
networks:
- iot_net
volumes:
mysql_data:
redis_data:
networks:
iot_net:
driver: bridge
3.1 环境变量管理
开发环境和生产环境的配置不同,不应该硬编码在compose文件里。用.env文件管理:
# .env.development
DB_ROOT_PASSWORD=dev_root_pass
DB_NAME=iot_platform
DB_USER=iot_user
DB_PASSWORD=dev_pass
# .env.production
DB_ROOT_PASSWORD=prod_strong_password
DB_NAME=iot_platform
DB_USER=iot_user
DB_PASSWORD=prod_strong_pass
启动时指定环境文件:
docker compose --env-file .env.production up -d
四、生产部署最佳实践
4.1 镜像版本锁定
生产环境严禁使用latest标签。latest指向的镜像会随着上游更新而变化,今天能跑明天可能就崩。在Dockerfile和compose中锁定具体版本:
mysql:
image: mysql:8.0.36 # 而不是 mysql:latest
4.2 健康检查
生产环境必须配置健康检查,让编排系统知道容器是否真的在工作:
php:
build: ./docker/php
healthcheck:
test: ["CMD", "php-fpm", "-t"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
4.3 资源限制
物联网平台常部署在资源有限的服务器上。给每个容器设定CPU和内存上限,防止单个服务吃光所有资源:
mysql:
image: mysql:8.0.36
deploy:
resources:
limits:
cpus: '2.0'
memory: 1024M
reservations:
cpus: '0.5'
memory: 256M
4.4 日志管理
Docker默认日志文件会无限增长。生产环境配置日志轮转:
php:
build: ./docker/php
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
五、CI/CD流水线
用GitHub Actions(或Gitee CI)实现自动化构建和推送:
name: Build and Push IoT Platform Image
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login to Container Registry
run: docker login -u ${{ secrets.REG_USER }} -p ${{ secrets.REG_PASS }}
- name: Build PHP image
run: |
docker build -f docker/php/Dockerfile -t iot-platform/php:latest .
docker push iot-platform/php:latest
- name: Build Nginx image
run: |
docker build -f docker/nginx/Dockerfile -t iot-platform/nginx:latest .
docker push iot-platform/nginx:latest
六、实际项目案例
虎王科技的导航站系统anime_nav_pro_plus(gitee.com/zesso/anime_nav_pro_plus)就是一个适合Docker化部署的PHP项目。它支持后台管理、分类排序、SEO优化、静态页面生成,采用深色玻璃拟态设计。这类Web应用的Docker化步骤和我上面描述的完全一致:PHP-FPM镜像+Nginx镜像+MySQL服务,用compose编排一键启动。
实际上,物联网平台的Web管理台和导航站在技术栈上是高度一致的。PHP后端提供API、前端渲染仪表盘、MySQL存储设备数据、Redis做实时数据缓存。虎王科技在开发hardware_tool(随身WiFi调试工具)时也采用了类似的Docker化部署方案,PHP后端管理串口通信配置,前端做可视化操作界面。
6.1 ARM架构适配
物联网平台常部署在ARM架构的工业网关上(树莓派、NanoPi等)。Docker支持多架构镜像构建:
# 构建多架构镜像
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t iot-platform/php:latest \
--push .
这样同一镜像可以在x86服务器和ARM网关上运行,开发环境和生产环境的镜像完全一致。
七、常见部署问题
权限问题 :PHP容器以www-data用户运行,挂载的宿主机目录权限不对会导致写入失败。解决方案是compose中指定user参数,或者用init容器在启动时修正权限。
时区问题 :容器默认UTC时区,国内业务需要改为Asia/Shanghai。在Dockerfile中添加:
RUN apk add --no-cache tzdata \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone
MySQL初始化 :MySQL容器首次启动时执行SQL脚本,把文件放到/docker-entrypoint-initdb.d/目录下即可自动执行建表和初始数据导入。
Docker在物联网平台部署中的价值不是"跟上潮流",而是实打实地解决环境一致性、依赖隔离和快速回滚三大痛点。上面的配置都是从实际项目里沉淀出来的,直接拿去用能省不少排坑时间。觉得有用的话点个赞存一下,后续会补上K8s编排和监控告警的实践,关注了第一时间收到更新。

浙公网安备 33010602011771号