Docker 上生产别只会 docker run:一套可落地的部署配置清单
Docker 生产环境部署指南|附配置文件
Docker 已经成为现代应用交付和运维体系中的重要基础设施。相比传统部署方式,Docker 能够将应用、运行环境、依赖库、配置文件等统一封装为镜像,从而实现“构建一次,到处运行”。但需要注意的是,开发环境能跑起来,并不代表生产环境就适合直接上线。生产环境更关注稳定性、安全性、可观测性、资源控制、数据持久化、灰度发布、故障恢复和运维规范。
本文将从生产环境部署的角度,系统介绍 Docker 的部署原则、服务器初始化、镜像构建、Docker Compose 编排、Nginx 反向代理、日志管理、数据卷、健康检查、安全加固、备份恢复以及常见配置文件示例,帮助你构建一套相对规范、可维护的 Docker 生产环境部署方案。
一、生产环境使用 Docker 的核心目标
在生产环境中使用 Docker,并不是简单地执行:
docker run xxx
而是要解决以下几个关键问题:
-
应用可重复部署
不同服务器、不同时间部署出来的环境应尽可能一致,避免“在我机器上可以运行”的问题。 -
服务快速扩缩容
通过容器化方式,可以更方便地横向扩展应用实例。 -
降低环境耦合
应用依赖不直接污染宿主机,便于版本管理和迁移。 -
简化发布流程
配合 CI/CD,可以实现自动构建镜像、自动推送镜像仓库、自动拉取更新。 -
提升故障恢复能力
容器异常退出后可以自动重启,服务迁移也更加简单。 -
统一运维标准
日志、配置、端口、数据目录、网络隔离等都可以规范化管理。
二、生产环境部署前的准备工作
1. 推荐服务器环境
生产环境建议使用稳定的 Linux 发行版,例如:
- Ubuntu Server 22.04 LTS / 24.04 LTS
- Debian 12
- Rocky Linux 9
- AlmaLinux 9
- CentOS Stream 9
服务器配置需要根据业务量评估。一个中小型 Web 应用的基础配置可以参考:
| 资源 | 推荐配置 |
|---|---|
| CPU | 2 核及以上 |
| 内存 | 4GB 及以上 |
| 磁盘 | 50GB 及以上 SSD |
| 网络 | 公网 IP + 安全组 |
| 系统 | 64 位 Linux |
如果包含数据库、Redis、消息队列等服务,建议至少 4 核 8GB 起步,并根据实际并发量和数据规模进行扩容。
2. 系统初始化建议
在正式安装 Docker 之前,应先完成基础系统初始化。
更新系统软件包
以 Ubuntu 为例:
sudo apt update
sudo apt upgrade -y
设置时区
sudo timedatectl set-timezone Asia/Shanghai
timedatectl
安装常用工具
sudo apt install -y vim curl wget git unzip htop net-tools ca-certificates gnupg lsb-release
创建普通运维用户
生产环境不建议长期使用 root 用户操作。
sudo adduser deploy
sudo usermod -aG sudo deploy
后续可以使用 deploy 用户进行日常部署操作。
三、安装 Docker 与 Docker Compose
1. 安装 Docker
以 Ubuntu 为例,推荐使用 Docker 官方源安装。
sudo apt update
sudo apt install -y ca-certificates curl gnupg
添加 Docker 官方 GPG key:
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
添加软件源:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
安装 Docker:
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
查看版本:
docker version
docker compose version
2. 设置非 root 用户使用 Docker
将用户加入 Docker 用户组:
sudo usermod -aG docker deploy
重新登录后验证:
docker ps
注意:加入
docker用户组后,该用户几乎等同于拥有 root 权限,因此只应授予可信用户。
3. 设置 Docker 开机自启
sudo systemctl enable docker
sudo systemctl start docker
查看状态:
sudo systemctl status docker
四、Docker 生产环境目录规范
生产环境建议建立统一目录结构,例如:
/opt/apps
├── myapp
│ ├── docker-compose.yml
│ ├── .env
│ ├── nginx
│ │ └── default.conf
│ ├── data
│ │ ├── mysql
│ │ └── redis
│ ├── logs
│ │ ├── app
│ │ └── nginx
│ └── backup
推荐原则:
- 应用统一放在
/opt/apps - 配置文件纳入版本管理,但敏感配置不要提交到 Git
- 数据目录和日志目录与容器生命周期解耦
- 每个项目使用独立目录
- 不同环境使用不同
.env文件
创建目录:
sudo mkdir -p /opt/apps/myapp
sudo chown -R deploy:deploy /opt/apps/myapp
五、生产环境 Dockerfile 示例
假设我们有一个 Node.js 应用,生产 Dockerfile 可参考如下:
# Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
COPY --from=builder /app/package*.json ./
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
USER appuser
EXPOSE 3000
CMD ["node", "dist/main.js"]
配置说明
这个 Dockerfile 使用了多阶段构建:
builder阶段负责安装依赖和构建项目;runner阶段只保留运行所需文件;- 使用
node:20-alpine减小镜像体积; - 创建普通用户
appuser运行应用,避免容器内使用 root; - 设置
NODE_ENV=production,使用生产环境模式。
如果是 Java 应用,Dockerfile 可以写成:
# Dockerfile
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
COPY target/app.jar /app/app.jar
USER appuser
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
六、Docker Compose 生产配置示例
在单机生产环境中,Docker Compose 是非常常见的部署方式。它比直接使用 docker run 更易维护,可以将服务、网络、数据卷、环境变量统一写入配置文件。
下面是一个包含 Web 应用、MySQL、Redis、Nginx 的生产级示例。
# docker-compose.yml
services:
app:
image: registry.example.com/myapp/backend:1.0.0
container_name: myapp-backend
restart: always
env_file:
- .env
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_started
networks:
- app-network
expose:
- "3000"
volumes:
- ./logs/app:/app/logs
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
logging:
driver: json-file
options:
max-size: "100m"
max-file: "5"
nginx:
image: nginx:1.26-alpine
container_name: myapp-nginx
restart: always
depends_on:
- app
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
- ./logs/nginx:/var/log/nginx
- ./certs:/etc/nginx/certs:ro
networks:
- app-network
logging:
driver: json-file
options:
max-size: "100m"
max-file: "5"
mysql:
image: mysql:8.0
container_name: myapp-mysql
restart: always
env_file:
- .env
command:
- --default-authentication-plugin=mysql_native_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --max_connections=500
ports:
- "127.0.0.1:3306:3306"
volumes:
- ./data/mysql:/var/lib/mysql
- ./mysql/conf.d:/etc/mysql/conf.d
- ./backup/mysql:/backup
networks:
- app-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-p$${MYSQL_ROOT_PASSWORD}"]
interval: 20s
timeout: 5s
retries: 5
start_period: 40s
logging:
driver: json-file
options:
max-size: "100m"
max-file: "5"
redis:
image: redis:7.2-alpine
container_name: myapp-redis
restart: always
command: redis-server /usr/local/etc/redis/redis.conf
volumes:
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf:ro
- ./data/redis:/data
networks:
- app-network
expose:
- "6379"
logging:
driver: json-file
options:
max-size: "50m"
max-file: "3"
networks:
app-network:
driver: bridge
七、环境变量配置文件 .env
生产环境中不要把数据库密码、JWT 密钥、第三方 API Key 等硬编码到镜像中,应该通过环境变量注入。
# .env
APP_ENV=production
APP_PORT=3000
MYSQL_HOST=mysql
MYSQL_PORT=3306
MYSQL_DATABASE=myapp
MYSQL_USER=myapp_user
MYSQL_PASSWORD=ChangeMe_StrongPassword_123
MYSQL_ROOT_PASSWORD=ChangeMe_RootPassword_456
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=ChangeMe_RedisPassword_789
JWT_SECRET=ChangeMe_JwtSecret_With_Long_Random_String
.env 使用建议
- 文件权限建议设置为
600 - 不要提交到公开 Git 仓库
- 可以提供
.env.example作为模板 - 生产环境密码应使用随机强密码
- 不同环境使用不同变量配置
设置权限:
chmod 600 .env
八、Nginx 反向代理配置
Nginx 在生产环境中通常用于:
- HTTP/HTTPS 入口代理
- 静态资源服务
- SSL 证书终止
- 请求压缩
- 访问日志记录
- 限流与安全控制
示例配置如下:
# nginx/default.conf
server {
listen 80;
server_name example.com www.example.com;
client_max_body_size 50m;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
location / {
proxy_pass http://app:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
location /health {
proxy_pass http://app:3000/health;
access_log off;
}
}
如果启用 HTTPS,可以参考:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/nginx/certs/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
client_max_body_size 50m;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
location / {
proxy_pass http://app:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
九、Redis 生产配置示例
Redis 默认配置并不完全适合生产环境,至少应配置密码、持久化策略和内存淘汰策略。
# redis/redis.conf
bind 0.0.0.0
port 6379
requirepass ChangeMe_RedisPassword_789
appendonly yes
appendfilename "appendonly.aof"
save 900 1
save 300 10
save 60 10000
dir /data
maxmemory 512mb
maxmemory-policy allkeys-lru
tcp-keepalive 300
timeout 0
loglevel notice
需要注意的是,在 Docker 内部网络中 Redis 可以监听 0.0.0.0,但不要直接把 Redis 端口暴露到公网。如果必须远程访问,应使用 VPN、堡垒机或安全组白名单限制来源 IP。
十、MySQL 配置示例
可以为 MySQL 添加自定义配置文件:
# mysql/conf.d/my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default-time-zone=+08:00
max_connections=500
connect_timeout=10
wait_timeout=28800
interactive_timeout=28800
innodb_buffer_pool_size=512M
innodb_log_file_size=256M
innodb_flush_log_at_trx_commit=1
sync_binlog=1
slow_query_log=1
slow_query_log_file=/var/lib/mysql/slow.log
long_query_time=2
[client]
default-character-set=utf8mb4
配置说明:
utf8mb4支持 Emoji 和完整 Unicode 字符;innodb_flush_log_at_trx_commit=1更安全,但性能略低;slow_query_log=1用于记录慢查询;long_query_time=2表示超过 2 秒的 SQL 会被记录。
十一、启动、停止与更新服务
进入项目目录:
cd /opt/apps/myapp
启动服务:
docker compose up -d
查看服务状态:
docker compose ps
查看日志:
docker compose logs -f app
docker compose logs -f nginx
停止服务:
docker compose down
只重启某个服务:
docker compose restart app
更新镜像并重启:
docker compose pull app
docker compose up -d app
如果使用了固定镜像版本,例如 backend:1.0.0,发布新版本时建议改为 backend:1.0.1,然后执行:
docker compose up -d
十二、生产环境镜像版本管理
生产环境不建议长期使用 latest 标签,例如:
image: registry.example.com/myapp/backend:latest
原因是:
- 无法明确当前运行的是哪个版本;
- 回滚困难;
- 多台服务器拉取结果可能不一致;
- 不利于审计和问题排查。
推荐使用明确版本号:
image: registry.example.com/myapp/backend:1.2.3
或者使用 Git Commit Hash:
image: registry.example.com/myapp/backend:20240601-a1b2c3d
发布流程建议:
- 代码合并到主分支;
- CI 构建镜像;
- 镜像打版本标签;
- 推送到私有镜像仓库;
- 服务器拉取指定版本;
- 更新 Compose 文件;
- 重启服务;
- 验证健康检查;
- 如异常则回滚上一版本。
十三、日志管理与轮转
Docker 默认日志驱动为 json-file,如果不限制大小,日志文件可能不断增长,最终占满磁盘。因此生产环境必须配置日志轮转。
在 docker-compose.yml 中可以这样配置:
logging:
driver: json-file
options:
max-size: "100m"
max-file: "5"
也可以在 Docker Daemon 全局配置中设置。
创建或修改:
sudo vim /etc/docker/daemon.json
示例:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "5"
},
"registry-mirrors": [],
"live-restore": true
}
重启 Docker:
sudo systemctl daemon-reload
sudo systemctl restart docker
其中:
max-size表示单个日志文件最大大小;max-file表示最多保留几个日志文件;live-restore可以在 Docker Daemon 重启时尽量保持容器继续运行。
十四、数据持久化策略
生产环境中,一定要明确哪些数据需要持久化。典型需要持久化的数据包括:
- MySQL 数据目录;
- Redis AOF/RDB 文件;
- 用户上传文件;
- 应用日志;
- SSL 证书;
- 配置文件。
在 Compose 中使用宿主机目录挂载:
volumes:
- ./data/mysql:/var/lib/mysql
优点是:
- 数据位置清晰;
- 便于备份;
- 便于迁移;
- 容器删除后数据仍然存在。
需要注意权限问题。如果容器无法写入挂载目录,可以检查目录权限:
ls -ld ./data/mysql
必要时调整权限,但不要盲目使用 chmod 777。应根据镜像运行用户进行权限设置。
十五、数据库备份与恢复
1. MySQL 备份脚本
创建脚本:
vim backup_mysql.sh
内容如下:
#!/bin/bash
APP_DIR="/opt/apps/myapp"
BACKUP_DIR="$APP_DIR/backup/mysql"
CONTAINER_NAME="myapp-mysql"
DB_NAME="myapp"
DB_USER="root"
DATE=$(date +"%Y%m%d_%H%M%S")
mkdir -p "$BACKUP_DIR"
docker exec "$CONTAINER_NAME" mysqldump \
-u"$DB_USER" \
-p"$MYSQL_ROOT_PASSWORD" \
--single-transaction \
--routines \
--triggers \
"$DB_NAME" > "$BACKUP_DIR/${DB_NAME}_${DATE}.sql"
find "$BACKUP_DIR" -type f -name "*.sql" -mtime +14 -delete
不过上面的脚本直接使用环境变量 MYSQL_ROOT_PASSWORD,执行时需要确保当前 shell 中存在该变量。更常见的方式是从 .env 加载:
#!/bin/bash
APP_DIR="/opt/apps/myapp"
ENV_FILE="$APP_DIR/.env"
BACKUP_DIR="$APP_DIR/backup/mysql"
CONTAINER_NAME="myapp-mysql"
DB_NAME="myapp"
DATE=$(date +"%Y%m%d_%H%M%S")
set -a
source "$ENV_FILE"
set +a
mkdir -p "$BACKUP_DIR"
docker exec "$CONTAINER_NAME" mysqldump \
-uroot \
-p"$MYSQL_ROOT_PASSWORD" \
--single-transaction \
--routines \
--triggers \
"$DB_NAME" > "$BACKUP_DIR/${DB_NAME}_${DATE}.sql"
gzip "$BACKUP_DIR/${DB_NAME}_${DATE}.sql"
find "$BACKUP_DIR" -type f -name "*.gz" -mtime +14 -delete
赋予执行权限:
chmod +x backup_mysql.sh
添加定时任务:
crontab -e
每天凌晨 2 点备份:
0 2 * * * /opt/apps/myapp/backup_mysql.sh >> /opt/apps/myapp/logs/backup.log 2>&1
2. MySQL 恢复
gunzip myapp_20240601_020000.sql.gz
docker exec -i myapp-mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" myapp < myapp_20240601_020000.sql
恢复前建议先停止应用服务,避免写入冲突:
docker compose stop app
恢复完成后再启动:
docker compose start app
十六、安全加固建议
1. 不要暴露不必要端口
数据库、Redis 等服务通常不应暴露到公网。Compose 中可以只使用内部网络:
expose:
- "6379"
如果确实需要宿主机访问 MySQL,可绑定到本地:
ports:
- "127.0.0.1:3306:3306"
这样公网无法直接访问。
2. 使用强密码和最小权限账户
MySQL 不建议应用直接使用 root 用户,应创建独立业务账号:
CREATE USER 'myapp_user'@'%' IDENTIFIED BY 'StrongPassword';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, ALTER ON myapp.* TO 'myapp_user'@'%';
FLUSH PRIVILEGES;
不要给应用账号授予不必要的全局权限。
3. 容器内尽量不要使用 root 用户
Dockerfile 中应创建普通用户:
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
这可以降低容器逃逸或应用漏洞带来的风险。
4. 设置只读配置挂载
对于配置文件和证书,建议使用只读挂载:
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
- ./certs:/etc/nginx/certs:ro
5. 控制容器资源
可以在 Compose 中为服务设置资源限制。不同 Compose 版本对资源限制支持略有差异,常见写法如下:
services:
app:
image: registry.example.com/myapp/backend:1.0.0
deploy:
resources:
limits:
cpus: "1.0"
memory: 1024M
reservations:
memory: 512M
需要注意:deploy 字段在 Docker Swarm 中支持更完整;普通 Docker Compose 对部分字段支持依赖版本。也可以使用 mem_limit:
services:
app:
mem_limit: 1024m
cpus: 1.0
十七、健康检查与自动恢复
生产环境必须提供健康检查接口,例如:
GET /health
返回示例:
{
"status": "ok"
}
Compose 中配置:
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
同时设置:
restart: always
这样当容器异常退出时,Docker 会自动重启容器。但需要注意,restart: always 不能解决所有问题,比如应用进程假死但容器未退出,因此健康检查和外部监控也很重要。
十八、监控与告警建议
Docker 生产环境建议至少监控以下指标:
- CPU 使用率;
- 内存使用率;
- 磁盘空间;
- 容器运行状态;
- 容器重启次数;
- HTTP 状态码;
- 接口响应时间;
- 数据库连接数;
- Redis 内存使用;
- Nginx 访问量和错误日志。
常见方案包括:
- Prometheus + Grafana;
- cAdvisor;
- Node Exporter;
- Loki + Promtail;
- ELK / OpenSearch;
- 云厂商监控服务。
查看容器资源使用:
docker stats
查看容器重启次数:
docker ps --format "table {{.Names}}\t{{.Status}}"
磁盘空间检查:
df -h
docker system df
清理无用镜像和缓存:
docker system prune
谨慎使用:
docker system prune -a
它可能删除未使用的镜像,导致回滚时需要重新拉取。
十九、发布与回滚流程
1. 标准发布流程
推荐生产发布流程:
- 本地或 CI 完成测试;
- 构建 Docker 镜像;
- 镜像打版本号;
- 推送到镜像仓库;
- 登录服务器;
- 修改
docker-compose.yml镜像版本; - 执行
docker compose pull; - 执行
docker compose up -d; - 查看容器状态;
- 检查应用健康接口;
- 观察日志和监控指标。
示例命令:
docker compose pull app
docker compose up -d app
docker compose logs -f app
2. 快速回滚
假设当前版本为:
image: registry.example.com/myapp/backend:1.0.1
上一稳定版本为:
image: registry.example.com/myapp/backend:1.0.0
回滚时将版本改回 1.0.0,然后执行:
docker compose pull app
docker compose up -d app
如果数据库结构已经变更,回滚前必须确认数据库迁移是否兼容。生产环境中,数据库变更应遵循“向前兼容”原则,例如先加字段、再发代码、最后清理旧字段。
二十、常见问题排查
1. 容器启动失败
查看日志:
docker compose logs app
查看容器详细信息:
docker inspect myapp-backend
常见原因:
- 环境变量缺失;
- 数据库连接失败;
- 端口冲突;
- 文件权限错误;
- 镜像版本错误;
- 配置文件挂载路径错误。
2. 容器不断重启
docker ps
docker logs myapp-backend --tail=100
如果状态中出现 Restarting,通常表示主进程启动后立即退出。应重点查看应用启动日志。
3. Nginx 访问 502
常见原因:
- app 容器未启动;
- app 服务监听端口不正确;
- Nginx
proxy_pass地址错误; - Docker 网络不通;
- 应用启动慢但 Nginx 已经开始转发。
检查:
docker compose ps
docker compose logs nginx
docker compose logs app
进入 Nginx 容器测试:
docker exec -it myapp-nginx sh
wget -qO- http://app:3000/health
4. 磁盘被 Docker 占满
查看 Docker 占用:
docker system df
查看日志文件:
sudo du -sh /var/lib/docker/containers/*
清理未使用资源:
docker image prune
docker container prune
docker volume prune
注意:volume prune 可能删除未使用的数据卷,生产环境需谨慎执行。
二十一、推荐最终项目文件结构
完整项目结构可以整理为:
/opt/apps/myapp
├── docker-compose.yml
├── .env
├── backup_mysql.sh
├── nginx
│ └── default.conf
├── redis
│ └── redis.conf
├── mysql
│ └── conf.d
│ └── my.cnf
├── certs
│ ├── fullchain.pem
│ └── privkey.pem
├── data
│ ├── mysql
│ └── redis
├── logs
│ ├── app
│ ├── nginx
│ └── backup.log
└── backup
└── mysql
这个结构将配置、数据、日志和备份清晰分离,便于日常维护和迁移。
二十二、生产环境部署检查清单
上线前建议逐项检查:
- [ ] Docker 和 Docker Compose 已正确安装;
- [ ] 服务已设置
restart: always; - [ ] 镜像使用明确版本号,而不是
latest; - [ ]
.env文件权限已设置为600; - [ ] 数据库和 Redis 未暴露到公网;
- [ ] Nginx 已配置正确的反向代理;
- [ ] HTTPS 证书已配置;
- [ ] 日志轮转已启用;
- [ ] 数据目录已持久化;
- [ ] 数据库备份脚本已配置;
- [ ] 备份任务已加入定时任务;
- [ ] 健康检查接口可正常访问;
- [ ] 监控和告警已配置;
- [ ] 回滚版本已准备;
- [ ] 防火墙和云安全组已限制端口;
- [ ] 生产密码已使用强密码;
- [ ] 容器尽量不使用 root 用户运行。
总结
Docker 能显著提升应用部署效率,但生产环境部署不能只关注“能运行”,更要关注“长期稳定运行”。一套可靠的 Docker 生产部署方案,至少应包含:规范的目录结构、明确的镜像版本、合理的 Dockerfile、可维护的 Docker Compose 配置、Nginx 反向代理、环境变量管理、数据持久化、日志轮转、备份恢复、健康检查、安全加固和监控告警。
对于中小型项目,单机 Docker Compose 已经可以满足大部分生产需求;当业务规模进一步扩大,可以逐步演进到 Docker Swarm、Kubernetes 或云原生平台。无论采用哪种方式,核心原则始终不变:配置可追踪、数据可恢复、服务可观测、故障可回滚、安全有边界。
只要遵循这些原则,Docker 不仅能简化部署流程,也能成为生产环境稳定运行的重要基础。