Tool

Docker 与 Docker Compose:从入门到实战

系统梳理 Docker 核心概念和 Docker Compose 编排技巧,配合实际项目案例,帮你快速掌握容器化部署。

Docker 把应用和依赖打包成容器,让「在我机器上能跑」成为过去式。Docker Compose 则是管理多容器项目的利器。两者搭配,是现代部署的标配。

Docker 核心概念

三个关键词搞定:

概念类比说明
镜像 (Image)安装包只读模板,包含应用和运行环境
容器 (Container)运行中的程序镜像的运行实例,可启停
Dockerfile安装脚本描述如何构建镜像
Dockerfile → build → Image → run → Container

安装 Docker

Ubuntu / Debian

# 卸载旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc

# 安装依赖
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg

# 添加 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
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

# 安装
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 验证
docker --version
docker compose version

免 sudo 运行

sudo usermod -aG docker $USER
# 重新登录生效

常用命令速查

镜像操作

docker pull nginx:latest          # 拉取镜像
docker images                     # 查看本地镜像
docker rmi nginx:latest           # 删除镜像
docker build -t myapp:v1 .        # 从 Dockerfile 构建镜像

容器操作

docker run -d --name web -p 8080:80 nginx     # 后台启动
docker ps                                     # 查看运行中的容器
docker ps -a                                  # 查看所有容器(含已停止)
docker logs web                               # 查看日志
docker exec -it web /bin/bash                 # 进入容器
docker stop web                               # 停止
docker start web                              # 启动
docker rm web                                 # 删除容器
docker restart web                            # 重启

清理

docker system prune              # 清理无用镜像/容器/网络
docker system prune -a           # 连未使用的镜像也清理
docker volume prune              # 清理无用卷

Dockerfile 最佳实践

以一个 Node.js 应用为例:

# 1. 精简基础镜像
FROM node:20-alpine AS builder

WORKDIR /app

# 2. 先复制依赖文件,利用缓存层
COPY package.json package-lock.json ./
RUN npm ci --only=production

# 3. 多阶段构建 — 构建阶段
FROM node:20-alpine AS build
WORKDIR /app
COPY . .
RUN npm ci && npm run build

# 4. 运行阶段 — 最小镜像
FROM node:20-alpine AS runner
WORKDIR /app

# 5. 非 root 用户运行
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 app
USER app

COPY --from=builder /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist

EXPOSE 3000

CMD ["node", "dist/server.js"]

关键原则

  1. 用 Alpine 基础镜像 — 体积小,攻击面少
  2. 多阶段构建 — 构建工具不进最终镜像
  3. 利用构建缓存 — 先 COPY 依赖文件,再 COPY 源码
  4. 非 root 运行 — 安全最佳实践
  5. 一个容器一个进程 — 不要在容器里跑多个服务

Docker Compose 详解

Compose 用一个 YAML 文件定义多容器应用,一条命令启动全部。

基本结构

version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./html:/usr/share/nginx/html:ro
    depends_on:
      - api
    restart: unless-stopped

  api:
    build: ./api
    ports:
      - "3000:3000"
    environment:
      - DB_HOST=db
      - DB_PORT=5432
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_PASSWORD=secret
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: unless-stopped

volumes:
  pgdata:

常用命令

docker compose up -d              # 后台启动所有服务
docker compose down               # 停止并删除容器
docker compose down -v            # 同时删除卷
docker compose logs -f api        # 实时查看日志
docker compose ps                 # 查看服务状态
docker compose restart api        # 重启某个服务
docker compose build              # 重新构建镜像
docker compose pull               # 拉取最新镜像
docker compose up -d --build api  # 重新构建并启动某个服务

实战案例

案例 1:WordPress + MySQL

version: '3.8'
services:
  wordpress:
    image: wordpress:6.7
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_USER: wp
      WORDPRESS_DB_PASSWORD: wp-password
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - wp-content:/var/www/html
    depends_on:
      mysql:
        condition: service_healthy

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root-password
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wp
      MYSQL_PASSWORD: wp-password
    volumes:
      - mysql-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  wp-content:
  mysql-data:

案例 2:反向代理 + 多站点

version: '3.8'
services:
  nginx-proxy:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - ./certs:/etc/nginx/certs:ro
    restart: always

  site-a:
    image: myapp:a
    expose:
      - "3000"

  site-b:
    image: myapp:b
    expose:
      - "3000"

Nginx 配置按域名分发到不同容器,一个代理管多站。

数据持久化

容器是无状态的,删除容器数据就没了。持久化方案:

方式用途生命周期
命名卷 (Volume)数据库、应用数据随卷存在
绑定挂载 (Bind Mount)配置文件、代码目录随宿主文件存在
tmpfs临时数据容器停止即消失
volumes:
  # 命名卷 — Docker 管理
  - pgdata:/var/lib/postgresql/data
  # 绑定挂载 — 映射宿主路径
  - ./config.yml:/app/config.yml:ro   # :ro 只读

网络模式

services:
  app:
    networks:
      - frontend
      - backend

  db:
    networks:
      - backend    # db 只在 backend 网络,外部不可访问

networks:
  frontend:
  backend:
    internal: true   # 隔离网络,无法访问外网
  • 同一网络中的容器可通过服务名互访(如 db:5432
  • internal: true 创建隔离网络,数据库不会被外部访问

优化技巧

  1. 镜像瘦身 — Alpine 基础镜像 + 多阶段构建
  2. 健康检查healthcheck 让 Compose 知道服务是否就绪
  3. 资源限制 — 防止某个容器吃光资源
services:
  api:
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          memory: 256M
  1. 日志限制 — 防止日志撑爆磁盘
services:
  api:
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
  1. 环境变量文件 — 敏感信息不写进 YAML
# .env
DB_PASSWORD=secret
services:
  db:
    environment:
      - POSTGRES_PASSWORD=${DB_PASSWORD}

总结

  • Docker 解决「环境一致性问题」,让应用在哪里都能跑
  • Docker Compose 解决「多容器编排问题」,一条命令管理整套服务
  • 关键原则:一个容器一个进程、数据持久化用卷、敏感信息用环境变量、网络隔离最小权限
  • 实战路径:先跑别人的镜像 → 写自己的 Dockerfile → 用 Compose 编排多服务