Docker 与 Docker Compose

Docker 让"环境一致"从口号变成现实:同样的镜像,在任何机器上跑出同样的结果。本文从零开始,覆盖 Docker 与 Docker Compose 的安装、常用命令、compose 编排、数据备份与日常运维,一篇到位。

为什么需要 Docker

传统部署的痛点:环境不一致("在我电脑上是好的")、依赖冲突(两个项目要不同版本的 PHP)、迁移麻烦。Docker 通过镜像(Image)→ 容器(Container)的两层抽象解决这些问题:

开发机: 代码 + 镜像 ---> 容器 ---> 跑起来
生产机: 同一镜像 ---> 容器 ---> 同样的结果

镜像是一个只读模板(含代码、运行时、依赖、配置),容器是镜像的运行实例,彼此隔离。

一、安装 Docker(Debian 12 为例)

国内服务器直接拉取 Docker 官方源容易超时,推荐使用国内镜像源:

1. 安装依赖并添加软件源

apt-get update
apt-get install -y ca-certificates curl gnupg lsb-release

# 添加 Docker 官方 GPG 密钥
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg

# 添加软件源(阿里云镜像)
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/debian \
  $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null

2. 安装 Docker CE 全家桶

apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 启动并设置开机自启
systemctl enable docker
systemctl start docker

# 验证
docker --version
docker compose version

3. 配置镜像加速(可选,国内拉镜像更快)

编辑 /etc/docker/daemon.json:

{
  "registry-mirrors": [
    "https://docker.m.daocloud.io",
    "https://hub-mirror.c.163.com"
  ]
}
# 重启生效
systemctl daemon-reload && systemctl restart docker

二、Docker 常用命令

命令 作用
docker ps -a 查看所有容器(含停止的)
docker images 查看本地镜像
docker run -d --name myapp -p 8080:80 nginx 后台运行 nginx,宿主机 8080 映射容器 80
docker exec -it myapp bash 进入容器交互终端
docker logs -f myapp 跟踪容器日志
docker cp myapp:/etc/nginx/nginx.conf ./ 容器内外复制文件
docker stop / start / restart myapp 停止 / 启动 / 重启容器
docker rm -f myapp 强制删除容器
docker rmi nginx 删除镜像
docker system df 查看磁盘占用

端口映射速记

-p 8080:80    # 宿主机8080 -> 容器80(TCP)
-p 8080:80/udp # 指定 UDP 协议
-P            # 随机映射所有暴露端口

三、Docker Compose:多容器编排

一个应用往往需要多个服务(Web + 数据库 + 缓存),手写 docker run 命令难以维护。Compose 用一份 docker-compose.yml 声明全部服务:

1. 最小示例:Web 应用 + MySQL

# docker-compose.yml
name: myapp
services:
  db:
    image: mysql:8.0
    container_name: app-db
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ChangeMe123
      MYSQL_DATABASE: app_db
      MYSQL_USER: app_user
      MYSQL_PASSWORD: ChangeMe456
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  web:
    image: nginx:alpine
    container_name: app-web
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html

volumes:
  db_data:

2. Compose 常用命令

命令 作用
docker compose up -d 构建并后台启动全部服务
docker compose down 停止并删除容器(保留数据卷)
docker compose down -v 连同数据卷一起删除(⚠️ 慎用)
docker compose ps 查看服务状态
docker compose logs -f web 跟踪指定服务日志
docker compose exec web bash 进入指定服务容器
docker compose config 校验配置并展开环境变量

3. 常用配置项速查

配置项 说明
restart: unless-stopped 重启策略:异常退出自动拉起(生产推荐)
depends_on + condition 等待依赖服务健康后再启动
volumes(命名卷) 数据持久化,容器删除数据不丢
environment 注入环境变量(可用 .env 文件管理)
healthcheck 健康检查,供其他服务依赖

4. 用 .env 管理敏感配置

# .env
MYSQL_ROOT_PASSWORD=ChangeMe123
MYSQL_DATABASE=app_db
MYSQL_USER=app_user
MYSQL_PASSWORD=ChangeMe456
WEB_PORT=8080

# compose 文件中用 ${MYSQL_PASSWORD} 引用,密码不写进 yml
# .env 文件加入 .gitignore,防止泄露

四、日常运维操作

1. 数据备份

数据库用 mysqldump 逻辑备份,文件用数据卷快照:

# 数据库备份
docker exec app-db mysqldump -u root -p"${MYSQL_ROOT_PASSWORD}" app_db > backup_$(date +%F).sql

# 数据卷文件备份
docker run --rm -v db_data:/data -v $(pwd):/backup alpine tar czf /backup/db_files_$(date +%F).tar.gz -C /data .

# 定时任务(crontab -e,每天凌晨3点)
0 3 * * * cd /opt/myapp && docker exec app-db mysqldump -u root -p"密码" app_db > backup_$(date +\%F).sql && find . -name "*.sql" -mtime +7 -delete

2. 数据恢复

# 先停掉应用避免写库
docker compose down

# 恢复数据库
docker exec -i app-db mysql -u root -p"${MYSQL_ROOT_PASSWORD}" app_db < backup_2026-08-21.sql

# 恢复文件(先删旧卷再导入,或直接用新卷挂载)
docker compose up -d

3. 升级镜像

docker compose pull        # 拉取最新镜像
docker compose up -d       # 用新镜像重建容器
docker image prune -f      # 清理旧镜像

4. 磁盘清理

docker system df            # 查看占用
docker system prune -a      # 清理所有未使用的镜像/容器/网络(⚠️ 会删构建缓存)
docker system prune -a --volumes  # 连数据卷一起清(⚠️⚠️ 数据不可恢复!)

5. 容器自动启动

compose 里设置 restart: unless-stopped 后,机器重启容器会自动拉起。但注意:docker compose down 手动停止的容器不会自动启动,需要手动 docker compose up -d。

五、常见问题排查

现象 原因与解决
拉镜像超时 / DNS 解析失败 国内网络问题,配置 registry-mirrors 加速
端口被占用 改映射端口,或用 docker ps 查看占用
容器一直重启(restarting) docker logs 看报错,通常是配置或权限问题
Permission denied 挂载卷 容器内用户权限问题,加 :Z 或用命名卷
docker 命令权限不足 将用户加入 docker 组:usermod -aG docker $USER
数据"丢了" 容器删除后数据丢失,务必用命名卷持久化

六、安全提醒

  • 不要用 root 直接跑业务容器,容器内用低权限用户
  • 敏感信息(数据库密码、API Key)放 .env,不要写死在镜像或 yml 里
  • 云服务器记得在安全组里只开放必要端口
  • 定期备份,备份文件放异地(对象存储或另一台机器)
  • docker compose down -v 和 system prune --volumes 会删数据,操作前先备份

Docker 的上手曲线其实很平缓:装好环境 → 跑通第一个容器 → 用 Compose 编排多服务 → 加备份和监控,就完成了从"能用"到"好用"的跨越。文中的命令都已在 Debian 12 上实测可用,遇到问题欢迎在评论区交流。