跨境电商团队用 Docker:这些坑踩一次就够了 Docker 部署跨境电商系统,最容易被忽略的 18 个问题 跨境电商上 Docker 前,先把这些坑避开 从能跑到稳跑:跨境电商 Docker 实战避坑 订单、支付、库存都在跑,Docker 别这样用 跨境电商 Docker 部署指南:少踩坑,稳上线 Docker 在跨境电商里的正确打开方式 跨境电商系统容器化,这些 Docker 细节决定稳定性 别只会 docker compose up:跨境电商 Docker 避坑清单 跨境电商做容
Docker 使用避坑指南|适合跨境电商
在跨境电商业务中,系统往往不是一个单体应用就能解决问题。一个成熟的跨境电商团队,通常会同时涉及独立站、ERP、WMS、订单中台、商品刊登系统、支付回调服务、物流轨迹同步、营销活动系统、客服工单、数据看板等多个模块。随着业务增长,研发团队会越来越依赖 Docker 来完成环境统一、快速部署、弹性扩容和多服务编排。
Docker 的确能解决很多问题:开发环境不一致、部署依赖复杂、服务迁移困难、版本回滚麻烦等。但如果使用方式不当,它也会带来新的坑,比如镜像越来越大、容器时间不准、数据丢失、配置泄露、日志撑爆磁盘、数据库性能下降、线上环境无法排查问题等。
本文结合跨境电商常见业务场景,系统整理 Docker 使用过程中的关键避坑经验,帮助团队少踩坑、快落地、稳运行。
一、为什么跨境电商团队特别适合使用 Docker?
跨境电商业务有几个典型特点:
-
系统模块多
- 独立站前端
- 商品管理系统
- 订单系统
- 支付系统
- 物流系统
- 仓储系统
- 数据分析系统
- 第三方平台对接服务
-
环境依赖复杂
- PHP、Node.js、Java、Go、Python 可能同时存在
- MySQL、Redis、Elasticsearch、RabbitMQ、Kafka 等组件混合使用
- 不同项目可能依赖不同版本运行时
-
部署频率高
- 活动页更新
- 商品规则调整
- 支付接口变更
- 物流接口适配
- 平台 API 升级
-
跨地区团队协作
- 国内研发
- 海外运营
- 海外仓团队
- 第三方服务商
-
稳定性要求高
- 黑五、网一、圣诞节等大促期间不能轻易宕机
- 支付、下单、库存扣减等链路不能出错
- 订单数据和财务数据不能丢失
Docker 的价值在于:把运行环境标准化,把服务交付流程标准化,把部署行为自动化。
不过,Docker 不是银弹。它能降低环境差异,却不能替代架构设计、运维规范和安全治理。很多团队在刚开始使用 Docker 时,往往只关注“能跑起来”,忽略了“能不能稳定跑、长期跑、安全跑、可维护地跑”。
二、避坑一:不要把 Docker 当成虚拟机使用
很多刚接触 Docker 的团队,容易把容器理解成一台轻量级虚拟机,然后在容器里安装一堆东西:
apt install vim
apt install nginx
apt install php
apt install supervisor
apt install mysql
最后一个容器里跑了 Nginx、PHP、定时任务、队列消费者,甚至还跑 MySQL。这种做法看似方便,实际上非常危险。
错误做法
一个容器里运行多个核心服务:
container-a
├── nginx
├── php-fpm
├── cron
├── queue-worker
└── mysql
问题包括:
- 容器职责不清晰
- 服务异常后不好重启
- 日志混杂,难以排查
- 扩容不灵活
- 镜像体积越来越大
- 数据和应用耦合,迁移困难
推荐做法
一个容器只做一类事情:
nginx-container
php-container
mysql-container
redis-container
worker-container
scheduler-container
例如跨境电商独立站可以拆成:
services:
nginx:
image: nginx:stable
php:
build: ./php
mysql:
image: mysql:8.0
redis:
image: redis:7
queue-worker:
build: ./php
command: php artisan queue:work
scheduler:
build: ./php
command: php artisan schedule:work
这样做的好处是:
- 每个容器职责明确
- 某个服务异常时可以单独重启
- 队列消费者可以单独扩容
- 日志更清晰
- 后续迁移到 Kubernetes 更容易
对于跨境电商来说,队列消费者尤其应该独立出来。比如订单同步、物流轨迹拉取、邮件发送、库存更新等任务,绝不应该和 Web 服务混在一起。
三、避坑二:不要在容器里直接保存重要业务数据
Docker 容器本身是临时的。容器删除后,容器内部未挂载的数据也会丢失。
很多团队初期为了省事,直接这样启动 MySQL:
docker run -d --name mysql mysql:8.0
看起来数据库正常运行,但数据实际保存在容器内部。一旦执行:
docker rm -f mysql
数据就可能直接消失。
对于跨境电商业务而言,以下数据绝不能只保存在容器内部:
- 订单数据
- 支付记录
- 用户资料
- 商品库存
- 物流轨迹
- 优惠券记录
- 财务结算数据
- 售后退款数据
正确做法:使用数据卷或宿主机挂载
示例:
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: strong_password
MYSQL_DATABASE: shop
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
或者使用宿主机目录:
services:
mysql:
image: mysql:8.0
volumes:
- /data/mysql:/var/lib/mysql
更推荐的生产方案
对于生产环境,建议数据库不要轻易放在普通 Docker 容器里,尤其是以下业务:
- 订单中心
- 支付系统
- 库存系统
- 财务系统
更稳妥的方案是:
- 使用云数据库,例如 AWS RDS、阿里云 RDS、腾讯云 TDSQL 等;
- 使用具备备份、主从、高可用能力的数据库集群;
- 容器只运行无状态应用;
- 数据库、对象存储、消息队列等状态服务单独治理。
Docker 很适合跑应用服务,但核心数据层要慎重。
四、避坑三:镜像不要越做越大
很多团队写 Dockerfile 时,会把所有依赖、缓存、临时文件都塞进镜像,导致镜像越来越大。一个普通的 Web 服务镜像动辄 2GB、3GB,不仅构建慢,拉取慢,还会影响上线效率。
跨境电商团队在黑五、圣诞节大促期间经常需要快速修复问题,如果镜像太大,紧急发布会变得非常痛苦。
常见错误 Dockerfile
FROM node:18
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["npm", "start"]
问题:
- 把本地无关文件也复制进镜像
- 没有利用 Docker 缓存
- 没有清理 npm 缓存
- 构建产物和源码混在一起
- 镜像体积偏大
推荐写法:多阶段构建
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:stable-alpine
COPY --from=builder /app/dist /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
多阶段构建的好处:
- 最终镜像只包含运行所需文件
- 不包含构建工具
- 镜像更小
- 安全风险更低
- 发布速度更快
记得配置 .dockerignore
很多人只知道 .gitignore,却忘记 .dockerignore。如果没有配置,Docker 构建时可能会把日志、缓存、依赖目录、测试文件全部复制进去。
推荐:
.git
node_modules
vendor
logs
tmp
.env
.env.*
.DS_Store
coverage
.idea
.vscode
尤其注意:.env 文件不要打进镜像。
五、避坑四:不要把配置和密钥写死在镜像里
跨境电商系统经常会对接大量第三方平台和服务:
- Shopify API
- Amazon SP-API
- eBay API
- PayPal
- Stripe
- Airwallex
- PingPong
- Payoneer
- 物流商 API
- 海外仓 API
- 邮件服务 API
- 短信服务 API
这些服务通常都需要密钥、Token、Secret、证书。如果把它们直接写进 Dockerfile 或代码仓库,风险非常高。
错误示例
ENV STRIPE_SECRET_KEY=sk_live_xxxxx
ENV PAYPAL_CLIENT_SECRET=xxxxx
ENV MYSQL_PASSWORD=123456
或者在代码中写死:
$stripeKey = "sk_live_xxxxx";
一旦镜像被误传到公开仓库,或者代码仓库权限管理不严格,可能造成严重安全事故。
推荐做法
- 通过环境变量注入配置
services:
app:
image: shop-app:latest
environment:
APP_ENV: production
REDIS_HOST: redis
DB_HOST: mysql
- 敏感信息使用 Secret 管理
如果使用 Docker Swarm,可以使用 Docker Secret;如果使用 Kubernetes,可以使用 Secret;如果在云上,建议使用云厂商的密钥管理服务,例如:
- AWS Secrets Manager
- AWS Parameter Store
- 阿里云 KMS
- 腾讯云 SSM
- HashiCorp Vault
- 区分不同环境配置
至少区分:
- 本地开发环境
- 测试环境
- 预发布环境
- 生产环境
不要出现“测试环境连生产数据库”的情况。这在跨境电商中非常危险,因为测试订单、测试支付、测试库存扣减可能污染真实业务数据。
六、避坑五:注意容器时间和时区问题
跨境电商天然涉及多个国家和地区,时区问题非常常见。例如:
- 美国站使用 PST/PDT
- 欧洲站使用 CET/CEST
- 英国站使用 GMT/BST
- 中国团队使用 Asia/Shanghai
- 数据库存储使用 UTC
如果容器时区配置不一致,可能引发很多问题:
- 订单时间显示错误
- 促销活动提前或延迟开始
- 优惠券过期时间不准
- 定时任务执行时间偏差
- 财务报表按天统计错误
- 物流轨迹时间混乱
推荐原则
- 数据库统一存 UTC 时间
- 后端内部计算尽量使用 UTC
- 前端展示根据用户地区转换时区
- 定时任务明确指定时区
- 容器时区保持一致,不要各自为政
Docker Compose 示例
services:
app:
image: shop-app
environment:
TZ: UTC
如果业务明确要求使用上海时间,也可以:
environment:
TZ: Asia/Shanghai
但更推荐核心业务统一使用 UTC,尤其是订单、支付、库存、物流这些跨地区数据。
特别提醒:大促活动时间
例如你设置美国站黑五活动:
2025-11-28 00:00:00 America/Los_Angeles
不要简单当成服务器本地时间处理。否则活动可能在中国时间、UTC 时间或服务器默认时区下错误触发。促销系统一定要保存活动所属时区,并在计算时明确转换。
七、避坑六:日志不要只写在容器内部
很多应用默认把日志写到容器内部文件,例如:
/app/logs/app.log
如果没有挂载日志目录,容器删除后日志也会消失。更糟糕的是,日志文件不断增长,会把容器层或宿主机磁盘撑爆。
跨境电商业务中,日志对于排查问题非常关键:
- 用户为什么支付失败?
- PayPal 回调有没有收到?
- Stripe webhook 是否验签失败?
- Shopify 订单同步是否超时?
- 亚马逊库存更新是否被限流?
- 物流商接口返回了什么错误?
- 优惠券为什么没有生效?
推荐做法
- 应用日志输出到 stdout/stderr
容器化应用推荐将日志输出到标准输出,由 Docker 或日志系统采集。
例如 Node.js:
console.log("order created");
console.error("payment failed");
Laravel、Spring Boot、Go 服务也都应尽量配置为输出到控制台。
- 配置 Docker 日志轮转
如果不配置日志轮转,Docker 默认 json 日志可能会无限增长。
示例:
services:
app:
image: shop-app
logging:
driver: json-file
options:
max-size: "100m"
max-file: "5"
- 生产环境接入集中式日志系统
推荐方案:
- ELK / EFK
- Loki + Grafana
- Datadog
- CloudWatch Logs
- 阿里云 SLS
- 腾讯云 CLS
对于跨境电商来说,支付、订单、库存、物流相关日志建议单独打标签,方便快速检索。
八、避坑七:不要忽略健康检查
很多团队判断容器是否正常,只看容器是否还在运行:
docker ps
但容器运行中不代表服务可用。例如:
- PHP-FPM 卡死
- Node.js 进程假死
- 数据库连接池耗尽
- Redis 连接失败
- 应用无法访问外部支付 API
- 队列消费者不再消费消息
推荐增加 Healthcheck
Dockerfile 示例:
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD curl -f http://localhost/health || exit 1
Docker Compose 示例:
services:
app:
image: shop-app
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 5s
retries: 3
健康检查接口应该检查什么?
基础检查:
- 应用进程是否可响应
- 关键配置是否加载
- 数据库是否可连接
- Redis 是否可连接
- 队列是否可连接
但要注意,健康检查不应该太重,不要每次都访问第三方支付、物流接口,否则会增加不必要的外部请求。
可以设计两个接口:
/health 基础存活检查
/readiness 就绪检查,验证依赖服务
大促期间,健康检查对于自动重启、负载均衡摘除异常实例非常重要。
九、避坑八:不要用 latest 部署生产环境
很多教程喜欢这样写:
image: nginx:latest
image: mysql:latest
image: redis:latest
这在生产环境中非常不推荐。
latest 不是“最新稳定版”的意思,它只是一个标签。你今天拉到的 latest 和下个月拉到的 latest 可能完全不同。
风险
- 依赖版本突然变化
- 配置兼容性问题
- 数据库升级导致异常
- 应用运行时行为变化
- 回滚困难
例如 MySQL 5.7 和 MySQL 8.0 在认证方式、SQL 模式、字符集等方面都有差异。跨境电商系统里如果订单查询、报表 SQL、库存扣减逻辑依赖某些数据库行为,版本变化可能引发线上事故。
推荐做法
固定版本:
image: mysql:8.0.36
image: redis:7.2.4
image: nginx:1.25.4-alpine
业务镜像也应该使用明确版本:
image: registry.example.com/shop/order-service:2025.01.15-001
不要生产环境使用:
image: order-service:latest
发布系统最好能记录:
- 镜像名称
- 镜像版本
- Git Commit ID
- 构建时间
- 发布人
- 变更说明
这样出问题时才能快速定位和回滚。
十、避坑九:不要忽视网络隔离和端口暴露
Docker Compose 中常见写法:
ports:
- "3306:3306"
- "6379:6379"
这会把 MySQL 和 Redis 暴露到宿主机端口。如果服务器安全组或防火墙配置不严,可能导致数据库直接暴露在公网。
对于跨境电商而言,数据库里有用户信息、订单信息、地址信息、支付状态、财务信息,一旦泄露,后果非常严重。
推荐原则
- 能不暴露就不暴露
- 内部服务使用 Docker network 通信
- 只有 Nginx、网关、负载均衡暴露公网端口
- 数据库、Redis、MQ 不直接暴露公网
- 使用安全组限制访问来源
示例
services:
app:
image: shop-app
networks:
- backend
mysql:
image: mysql:8.0
networks:
- backend
expose:
- "3306"
redis:
image: redis:7
networks:
- backend
expose:
- "6379"
nginx:
image: nginx
ports:
- "80:80"
- "443:443"
networks:
- frontend
- backend
networks:
frontend:
backend:
expose 只在容器网络内部暴露,不会映射到宿主机公网端口。生产环境中,MySQL、Redis、RabbitMQ 管理后台等都要谨慎暴露。
十一、避坑十:队列消费者不要和 Web 容器混在一起
跨境电商系统中,异步任务非常多:
- 订单支付后发送邮件
- 创建物流单
- 推送海外仓
- 同步平台订单
- 更新库存
- 生成发票
- 拉取物流轨迹
- 发送营销短信
- 生成报表
- 处理退款通知
这些任务通常由队列消费者处理。如果把消费者和 Web 服务放在同一个容器里,会出现几个问题:
- Web 服务扩容时,消费者也被动扩容
- 消费者异常影响 Web 容器
- 队列积压无法独立扩容
- 不同任务优先级无法区分
- 日志混乱
推荐拆分
services:
web:
image: shop-app
command: php-fpm
order-worker:
image: shop-app
command: php artisan queue:work --queue=orders
payment-worker:
image: shop-app
command: php artisan queue:work --queue=payments
logistics-worker:
image: shop-app
command: php artisan queue:work --queue=logistics
这样可以根据业务压力单独扩容:
docker compose up -d --scale logistics-worker=5
比如大促期间,物流轨迹不一定要实时,但支付和订单任务必须优先处理。可以为不同业务设置不同队列和消费者数量。
十二、避坑十一:定时任务不要随便放在多个容器里
很多跨境电商系统依赖定时任务:
- 每 5 分钟同步 Shopify 订单
- 每 10 分钟拉取物流轨迹
- 每小时同步汇率
- 每天生成销售报表
- 每天清理过期优惠券
- 每月生成财务结算单
如果多个应用容器都运行了同一份 cron,可能导致任务重复执行。
例如:
app-container-1 执行同步订单
app-container-2 执行同步订单
app-container-3 执行同步订单
结果可能是:
- 重复创建订单
- 重复扣库存
- 重复发送邮件
- 重复调用第三方 API
- 被平台限流
- 财务数据异常
推荐做法
定时任务单独部署一个 scheduler 容器:
services:
scheduler:
image: shop-app
command: php artisan schedule:work
并确保只运行一个实例。如果必须多实例部署,需要使用分布式锁,例如:
- Redis Lock
- MySQL Lock
- etcd
- Consul
- Redlock
业务逻辑也要保证幂等性。即使任务重复执行,也不应该造成重复扣款、重复发货、重复扣库存。
十三、避坑十二:支付和订单链路必须做好幂等
这虽然不是 Docker 独有问题,但 Docker 部署下服务重启、扩容、重试更加频繁,如果接口没有幂等设计,会更容易暴露问题。
跨境电商最典型的场景:
- 用户点击支付按钮多次
- Stripe webhook 重复推送
- PayPal 回调重复通知
- 队列任务失败后重试
- 容器重启导致任务重新消费
- 网络超时后客户端重试请求
如果系统没有幂等控制,可能出现:
- 重复创建订单
- 重复扣减库存
- 重复发货
- 重复发放优惠券
- 重复记录支付成功
- 重复发送邮件
推荐策略
- 订单号全局唯一
- 支付回调使用第三方交易号去重
- 库存扣减使用事务或原子操作
- 队列任务带唯一任务 ID
- 关键表建立唯一索引
- 状态机只允许合法流转
例如支付回调表可以设置唯一约束:
ALTER TABLE payment_events
ADD UNIQUE KEY uniq_provider_event_id (provider, event_id);
队列任务处理时,先检查事件是否已处理,再执行后续逻辑。不要单纯依赖“代码判断”,数据库唯一约束是最后一道防线。
十四、避坑十三:资源限制一定要配置
默认情况下,容器可能会尽可能占用宿主机资源。一个异常容器可能把 CPU、内存吃满,影响同一台机器上的其他服务。
跨境电商大促期间,以下情况很常见:
- 报表查询占满 CPU
- 图片处理占用大量内存
- 商品批量导入导致数据库压力暴增
- 队列消费者并发过高
- 搜索服务内存不足
- 日志写入过快占满磁盘
Docker Compose 资源限制示例
不同 Compose 版本支持略有差异,常见写法:
services:
app:
image: shop-app
mem_limit: 1024m
cpus: 1.0
如果使用 Swarm:
deploy:
resources:
limits:
cpus: "1.0"
memory: 1024M
reservations:
cpus: "0.5"
memory: 512M
建议
- Web 容器限制内存,避免无限膨胀
- 队列消费者按业务类型限制并发
- 报表任务尽量放到独立服务
- 图片处理、视频处理等重任务不要和核心订单服务混跑
- Redis、MySQL 不要和大量业务容器挤在低配机器上
资源隔离的核心目标是:一个服务出问题,不要拖垮整个系统。
十五、避坑十四:生产环境不要依赖手工操作
很多小团队初期部署 Docker 是这样:
ssh root@server
git pull
docker compose down
docker compose up -d --build
这种方式在早期可行,但随着业务增长,会出现很多问题:
- 谁发布的不清楚
- 发布了什么版本不清楚
- 回滚困难
- 容易漏步骤
- 容易误操作生产环境
- 构建环境和生产环境混在一起
- 发布过程不可审计
推荐建立 CI/CD 流程
基本流程:
代码提交
↓
自动测试
↓
构建镜像
↓
推送镜像仓库
↓
部署到测试环境
↓
人工确认
↓
部署到生产环境
↓
健康检查
↓
失败自动回滚或告警
常用工具:
- GitHub Actions
- GitLab CI
- Jenkins
- Drone
- Argo CD
- Harbor
- AWS ECR
- 阿里云 ACR
发布时不要在生产服务器上构建镜像,而是提前构建好镜像并推送到镜像仓库。生产服务器只负责拉取指定版本镜像并运行。
十六、避坑十五:备份和恢复必须演练
备份不是“有文件就行”,而是“能恢复才算数”。
跨境电商系统的数据价值非常高,尤其是订单、支付、库存和财务数据。Docker 环境中如果数据卷、挂载目录、数据库备份策略没有设计好,可能出现灾难性后果。
需要备份的内容
- 数据库
- Redis 中的重要数据,如果有持久化需求
- 上传文件
- 商品图片
- 发票文件
- 配置文件
- 证书
- 镜像版本记录
- Compose/Kubernetes 配置
建议策略
- 数据库每日全量备份,每小时增量备份;
- 备份文件上传到异地对象存储;
- 备份文件加密;
- 定期做恢复演练;
- 大促前检查备份有效性;
- 重要变更前手动生成快照;
- 备份权限与生产库权限分离。
如果使用 Docker volume,也要清楚 volume 存放在哪里:
docker volume inspect mysql_data
不要在不了解 volume 的情况下随意执行:
docker system prune -a --volumes
这条命令可能清理掉未使用的数据卷,造成数据丢失。
十七、避坑十六:慎用 docker system prune
很多人发现服务器磁盘满了,会直接执行:
docker system prune -a
甚至加上:
docker system prune -a --volumes
这很危险。
它可能删除什么?
- 未使用的镜像
- 停止的容器
- 未使用的网络
- 构建缓存
- 未使用的数据卷
如果加了 --volumes,可能删除数据卷。对于数据库、Redis、上传文件等挂载不清晰的场景,后果非常严重。
推荐做法
先查看磁盘占用:
docker system df
查看具体镜像:
docker images
查看容器日志大小:
du -sh /var/lib/docker/containers/*
清理前确认:
docker volume ls
docker volume inspect volume_name
更稳妥的方式是:
- 只清理明确无用的镜像
- 配置日志轮转
- 将数据目录和 Docker 目录分盘
- 生产环境清理前先备份
- 清理操作纳入运维 SOP
十八、避坑十七:不要忽略镜像安全扫描
跨境电商涉及用户隐私、支付信息、地址信息和商业数据,安全风险不可忽视。Docker 镜像中可能存在:
- 系统漏洞
- 过期依赖
- 恶意包
- 泄露的密钥
- 不必要的调试工具
- 高权限运行风险
推荐措施
- 使用官方基础镜像或可信镜像;
- 尽量使用 slim、alpine 等精简镜像;
- 定期更新基础镜像;
- 构建阶段和运行阶段分离;
- 镜像扫描后再上线;
- 容器不要默认 root 用户运行;
- 不要把 SSH 服务放进容器;
- 不要在容器内存放私钥。
Dockerfile 示例:
FROM node:18-alpine
WORKDIR /app
RUN addgroup -S app && adduser -S app -G app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
USER app
CMD ["node", "server.js"]
常用扫描工具:
- Trivy
- Grype
- Docker Scout
- Harbor Scanner
- Snyk
十九、避坑十八:本地开发环境和生产环境要相似,但不能完全混用
Docker 很适合统一开发环境。例如团队新人只需要:
docker compose up -d
就能启动项目,大幅降低配置成本。
但需要注意,本地环境和生产环境虽然应该相似,但不应该完全共用同一套配置。
本地环境可以有
- 热更新
- 代码目录挂载
- 调试端口
- 测试数据库
- Mock 支付
- Mock 物流接口
- Mailhog 邮件测试服务
生产环境不应该有
- 代码热更新挂载
- Xdebug
- 测试账号密钥
- Debug 模式
- Mock 服务
- 开放的管理端口
- 宽松的 CORS 配置
例如 Laravel:
APP_ENV=production
APP_DEBUG=false
Node.js:
NODE_ENV=production
生产环境必须关闭调试模式,否则错误堆栈可能暴露数据库配置、接口密钥、文件路径等敏感信息。
二十、适合跨境电商的 Docker Compose 示例
下面是一个简化版示例,适合中小型跨境电商独立站或后台系统参考:
version: "3.9"
services:
nginx:
image: nginx:1.25-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./deploy/nginx/conf.d:/etc/nginx/conf.d:ro
- ./public:/var/www/public:ro
depends_on:
- app
networks:
- frontend
- backend
logging:
driver: json-file
options:
max-size: "100m"
max-file: "5"
app:
image: registry.example.com/shop/app:2025.01.15-001
environment:
APP_ENV: production
APP_DEBUG: "false"
TZ: UTC
DB_HOST: mysql
REDIS_HOST: redis
expose:
- "9000"
networks:
- backend
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 5s
retries: 3
logging:
driver: json-file
options:
max-size: "100m"
max-file: "5"
order-worker:
image: registry.example.com/shop/app:2025.01.15-001
command: php artisan queue:work --queue=orders --sleep=3 --tries=3
environment:
APP_ENV: production
TZ: UTC
DB_HOST: mysql
REDIS_HOST: redis
networks:
- backend
depends_on:
- redis
- mysql
logging:
driver: json-file
options:
max-size: "100m"
max-file: "5"
logistics-worker:
image: registry.example.com/shop/app:2025.01.15-001
command: php artisan queue:work --queue=logistics --sleep=5 --tries=3
environment:
APP_ENV: production
TZ: UTC
DB_HOST: mysql
REDIS_HOST: redis
networks:
- backend
depends_on:
- redis
- mysql
scheduler:
image: registry.example.com/shop/app:2025.01.15-001
command: php artisan schedule:work
environment:
APP_ENV: production
TZ: UTC
DB_HOST: mysql
REDIS_HOST: redis
networks:
- backend
depends_on:
- redis
- mysql
mysql:
image: mysql:8.0.36
environment:
MYSQL_ROOT_PASSWORD: change_me
MYSQL_DATABASE: shop
TZ: UTC
volumes:
- mysql_data:/var/lib/mysql
networks:
- backend
expose:
- "3306"
redis:
image: redis:7.2.4-alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
networks:
- backend
expose:
- "6379"
volumes:
mysql_data:
redis_data:
networks:
frontend:
backend:
这个示例并不是生产环境最终答案,但体现了几个关键原则:
- 固定镜像版本
- Web、Worker、Scheduler 分离
- 数据使用 volume
- 数据库和 Redis 不暴露公网端口
- 配置日志轮转
- 使用独立网络
- 设置健康检查
- 使用 UTC 时区
二十一、跨境电商 Docker 上线前检查清单
上线前建议逐项检查:
1. 镜像与版本
- 是否固定镜像版本?
- 是否避免使用
latest? - 是否配置
.dockerignore? - 是否使用多阶段构建?
- 是否完成镜像安全扫描?
2. 配置与密钥
- 是否没有把
.env打进镜像? - 是否没有在代码中写死密钥?
- 生产、测试、本地环境是否隔离?
- 支付密钥是否使用 Secret 管理?
3. 数据安全
- 数据库是否使用 volume 或云数据库?
- 是否有自动备份?
- 是否做过恢复演练?
- 是否避免执行危险清理命令?
- 数据库端口是否未暴露公网?
4. 日志与监控
- 是否配置日志轮转?
- 是否接入集中式日志?
- 是否能按订单号、支付号、用户邮箱检索日志?
- 是否有磁盘、CPU、内存监控?
- 是否有异常告警?
5. 业务稳定性
- 支付回调是否幂等?
- 队列任务是否幂等?
- 定时任务是否只运行一个实例?
- 队列消费者是否可单独扩容?
- 大促前是否压测?
6. 网络与安全
- MySQL、Redis、MQ 是否未暴露公网?
- 容器是否避免 root 用户运行?
- 是否最小化端口开放?
- 是否配置防火墙和安全组?
- 是否定期更新基础镜像?
结语
Docker 对跨境电商团队非常有价值,它能让环境更统一、部署更快速、扩容更灵活,也能帮助团队从“手工运维”逐步走向“标准化交付”。
但 Docker 也不是简单地把应用“装进容器”就万事大吉。真正稳定的容器化实践,需要同时关注镜像构建、配置管理、数据持久化、日志采集、健康检查、网络隔离、资源限制、备份恢复、安全扫描和 CI/CD 流程。
对于跨境电商来说,订单、支付、库存、物流和财务数据都是核心资产。使用 Docker 时一定要坚持几个原则:
- 容器尽量无状态;
- 数据必须可靠持久化;
- 配置和密钥不能进镜像;
- 日志必须可追踪;
- 任务必须幂等;
- 版本必须可回滚;
- 生产操作必须可审计。
只要避开这些常见坑,Docker 不仅不会增加复杂度,反而会成为跨境电商业务快速迭代和稳定增长的重要基础设施。