上一篇 下一篇 分享链接 返回 返回顶部

Docker 上生产别只会 docker run:一套可落地的部署配置清单

发布人:慈云数据-客服中心 发布时间:5小时前 阅读量:3

Docker 生产环境部署指南|附配置文件

Docker 已经成为现代应用交付和运维体系中的重要基础设施。相比传统部署方式,Docker 能够将应用、运行环境、依赖库、配置文件等统一封装为镜像,从而实现“构建一次,到处运行”。但需要注意的是,开发环境能跑起来,并不代表生产环境就适合直接上线。生产环境更关注稳定性、安全性、可观测性、资源控制、数据持久化、灰度发布、故障恢复和运维规范。

本文将从生产环境部署的角度,系统介绍 Docker 的部署原则、服务器初始化、镜像构建、Docker Compose 编排、Nginx 反向代理、日志管理、数据卷、健康检查、安全加固、备份恢复以及常见配置文件示例,帮助你构建一套相对规范、可维护的 Docker 生产环境部署方案。


一、生产环境使用 Docker 的核心目标

在生产环境中使用 Docker,并不是简单地执行:

docker run xxx

而是要解决以下几个关键问题:

  1. 应用可重复部署
    不同服务器、不同时间部署出来的环境应尽可能一致,避免“在我机器上可以运行”的问题。

  2. 服务快速扩缩容
    通过容器化方式,可以更方便地横向扩展应用实例。

  3. 降低环境耦合
    应用依赖不直接污染宿主机,便于版本管理和迁移。

  4. 简化发布流程
    配合 CI/CD,可以实现自动构建镜像、自动推送镜像仓库、自动拉取更新。

  5. 提升故障恢复能力
    容器异常退出后可以自动重启,服务迁移也更加简单。

  6. 统一运维标准
    日志、配置、端口、数据目录、网络隔离等都可以规范化管理。


二、生产环境部署前的准备工作

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 使用了多阶段构建:

  1. builder 阶段负责安装依赖和构建项目;
  2. runner 阶段只保留运行所需文件;
  3. 使用 node:20-alpine 减小镜像体积;
  4. 创建普通用户 appuser 运行应用,避免容器内使用 root;
  5. 设置 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

原因是:

  1. 无法明确当前运行的是哪个版本;
  2. 回滚困难;
  3. 多台服务器拉取结果可能不一致;
  4. 不利于审计和问题排查。

推荐使用明确版本号:

image: registry.example.com/myapp/backend:1.2.3

或者使用 Git Commit Hash:

image: registry.example.com/myapp/backend:20240601-a1b2c3d

发布流程建议:

  1. 代码合并到主分支;
  2. CI 构建镜像;
  3. 镜像打版本标签;
  4. 推送到私有镜像仓库;
  5. 服务器拉取指定版本;
  6. 更新 Compose 文件;
  7. 重启服务;
  8. 验证健康检查;
  9. 如异常则回滚上一版本。

十三、日志管理与轮转

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. 标准发布流程

推荐生产发布流程:

  1. 本地或 CI 完成测试;
  2. 构建 Docker 镜像;
  3. 镜像打版本号;
  4. 推送到镜像仓库;
  5. 登录服务器;
  6. 修改 docker-compose.yml 镜像版本;
  7. 执行 docker compose pull
  8. 执行 docker compose up -d
  9. 查看容器状态;
  10. 检查应用健康接口;
  11. 观察日志和监控指标。

示例命令:

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 不仅能简化部署流程,也能成为生产环境稳定运行的重要基础。

目录结构
全文