一、真实场景下的Docker救场

场景还原
上周,团队新来的开发同事小王遇到了一个令人头疼的问题。他在本地开发了一个基于Node.js 18.0.0的应用,一切运行正常。但当他把代码交给测试同学时,测试同学反馈:“代码在我的机器上报错,提示Node版本不匹配,我的是16.x版本”。

问题本质:这就是经典的"在我机器上能跑"问题。不同的开发环境、测试环境、生产环境之间的差异导致应用行为不一致。

Docker解决方案

# 小王创建了Dockerfile
FROM node:18.0.0-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]

# 构建镜像
docker build -t myapp:1.0 .

# 测试同学直接运行
docker run -p 3000:3000 myapp:1.0
# 运行结果:应用成功启动,无版本兼容问题

这个简单的例子展示了Docker的核心价值:环境一致性

二、Docker到底是什么?

2.1 官方定义

Docker是一个开源的容器化平台,允许开发者将应用及其依赖打包到一个标准化的单元中,这个单元包含了应用运行所需的一切:代码、运行时、系统工具、系统库和设置。

2.2 与传统虚拟机的对比

传统虚拟机结构:
┌─────────────────────────────────────────────────────┐
│                   应用1    应用2    应用3            │
├─────────────────────────────────────────────────────┤
│                Guest Operating System               │
├─────────────────────────────────────────────────────┤
│                Guest Operating System               │
├─────────────────────────────────────────────────────┤
│                Guest Operating System               │
├─────────────────────────────────────────────────────┤
│                Hypervisor (虚拟机监控程序)            │
├─────────────────────────────────────────────────────┤
│                Host Operating System                │
└─────────────────────────────────────────────────────┘

Docker容器结构:
┌─────────────────────────────────────────────────────┐
│       应用1          应用2          应用3             │
├─────────────────────────────────────────────────────┤
│               Docker Engine (容器运行时)             │
├─────────────────────────────────────────────────────┤
│                Host Operating System                │
└─────────────────────────────────────────────────────┘

关键差异

特性传统虚拟机Docker容器
启动时间分钟级秒级
磁盘占用GB级别MB级别
性能损耗较高(15-20%)很低(3-5%)
系统资源每个VM需完整OS共享宿主机OS内核
隔离性完全隔离进程级隔离

三、Docker核心概念详解

3.1 镜像(Image)

镜像是只读的模板,包含运行应用所需的所有文件和配置。镜像是分层的,每一层都是对前一层的修改。

# 查看本机镜像
docker images
# 输出结果:
# REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
# nginx        latest    abc123def456   2 weeks ago    133MB
# ubuntu       20.04     xyz789uvw012   3 weeks ago    72.8MB

# 查看镜像详细信息
docker inspect nginx:latest

3.2 容器(Container)

容器是镜像的运行实例。一个镜像可以创建多个容器,每个容器都是独立隔离的。

# 运行一个容器
docker run -it --name my-ubuntu ubuntu:20.04 /bin/bash
# 进入容器后,执行:
root@容器ID:/# cat /etc/os-release
# 输出结果:
# NAME="Ubuntu"
# VERSION="20.04.4 LTS (Focal Fossa)"
# ID=ubuntu
# ID_LIKE=debian
# PRETTY_NAME="Ubuntu 20.04.4 LTS"
# VERSION_ID="20.04"
# HOME_URL="https://www.ubuntu.com/"
# SUPPORT_URL="https://help.ubuntu.com/"

3.3 仓库(Registry)

存储镜像的地方,分为公共仓库(Docker Hub)和私有仓库。

# 从Docker Hub拉取镜像
docker pull mysql:8.0
# 输出结果:
# 8.0: Pulling from library/mysql
# Digest: sha256:3d7ae561cf6095f6aca8c61aac6f297f5a6f35862c4813676c7b3f6c5e3a8e7a
# Status: Downloaded newer image for mysql:8.0

# 推送镜像到私有仓库
docker tag myapp:1.0 myregistry.com/myapp:1.0
docker push myregistry.com/myapp:1.0

四、Docker完整架构解析

Docker整体架构:
┌─────────────────────────────────────────────────────────────────────┐
│                          Docker Client                               │
│  (docker CLI、Docker Desktop、第三方工具如Portainer)                   │
└──────────────────────────────┬──────────────────────────────────────┘
                               │ REST API (HTTP/HTTPS)
┌──────────────────────────────▼──────────────────────────────────────┐
│                          Docker Host                                 │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │                     Docker Daemon (dockerd)                   │  │
│  │  ┌───────────┐  ┌───────────┐  ┌───────────┐               │  │
│  │  │ Container │  │ Container │  │ Container │               │  │
│  │  │  (Nginx)  │  │ (MySQL)   │  │ (Redis)   │               │  │
│  │  └─────┬─────┘  └─────┬─────┘  └─────┬─────┘               │  │
│  │        │              │              │                     │  │
│  │  ┌─────▼──────────────▼──────────────▼─────┐               │  │
│  │  │           Container Runtime              │               │  │
│  │  │  (containerd + runc)                    │               │  │
│  │  └─────────────────────────────────────────┘               │  │
│  └──────────────────────────────────────────────────────────────┘  │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐         │  │
│  │   Images      │  │   Networks    │  │   Volumes    │         │  │
│  │   (镜像存储)   │  │   (网络配置)  │  │   (数据存储)  │         │  │
│  └──────────────┘  └──────────────┘  └──────────────┘         │  │
└─────────────────────────────────────────────────────────────────────┘
                               │
┌──────────────────────────────▼──────────────────────────────────────┐
│                     Docker Registry                                 │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │                  Docker Hub (公共仓库)                          │  │
│  │  ┌────────────────────────────────────────────────────────┐  │  │
│  │  │             Private Registry (私有仓库)                  │  │  │
│  │  └────────────────────────────────────────────────────────┘  │  │
│  └──────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────┘

五、Docker完整命令分类详解

5.1 镜像管理命令

# 1. 搜索镜像
docker search nginx
# 输出结果:
# NAME        DESCRIPTION         STARS     OFFICIAL   AUTOMATED
# nginx       Official build...   18000     [OK]       
# jwilder/... Nginx proxy...      2000      [OK]

# 2. 拉取镜像
docker pull nginx:1.23.0
# 输出结果:
# 1.23.0: Pulling from library/nginx
# 7b1a6ab2e44d: Pull complete 
# Status: Downloaded newer image for nginx:1.23.0

# 3. 查看镜像历史
docker history nginx:latest
# 输出结果:
# IMAGE          CREATED        CREATED BY
# abc123def456   2 weeks ago    /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon...
# def456ghi789   2 weeks ago    /bin/sh -c #(nop)  STOPSIGNAL SIGQUIT
# ...

# 4. 删除镜像
docker rmi ubuntu:20.04
# 输出结果:
# Untagged: ubuntu:20.04
# Deleted: sha256:xyz789uvw012

# 5. 导出导入镜像
# 导出
docker save nginx:latest > nginx.tar
# 导入
docker load < nginx.tar

5.2 容器生命周期管理

# 1. 创建并启动容器
docker run -d --name web-server -p 80:80 nginx:latest
# 输出结果:容器ID(如:a1b2c3d4e5f6)

# 2. 查看运行中的容器
docker ps
# 输出结果:
# CONTAINER ID  IMAGE         COMMAND    CREATED       STATUS      PORTS               NAMES
# a1b2c3d4e5f6  nginx:latest  "nginx..." 2 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp  web-server

# 3. 查看所有容器(包括已停止的)
docker ps -a
# 输出结果:
# CONTAINER ID  IMAGE         COMMAND    CREATED       STATUS                     PORTS     NAMES
# a1b2c3d4e5f6  nginx:latest  "nginx..." 5 minutes ago Up 5 minutes               0.0.0.0:80->80/tcp web-server
# b2c3d4e5f6a1  ubuntu:20.04  "/bin/bash" 2 days ago   Exited (0) 2 days ago                test-container

# 4. 进入容器
docker exec -it web-server /bin/bash
# 在容器内执行:
root@a1b2c3d4e5f6:/# nginx -v
# 输出结果:nginx version: nginx/1.23.0

# 5. 查看容器日志
docker logs web-server
# 输出结果:
# 2023-10-01T10:00:00.000Z 172.17.0.1 - - [01/Oct/2023:10:00:00 +0000] "GET / HTTP/1.1" 200 612

# 6. 停止容器
docker stop web-server
# 输出结果:web-server

# 7. 启动已停止的容器
docker start web-server
# 输出结果:web-server

# 8. 重启容器
docker restart web-server
# 输出结果:web-server

# 9. 删除容器
docker rm web-server
# 输出结果:web-server

5.3 网络管理命令

# 1. 查看网络
docker network ls
# 输出结果:
# NETWORK ID     NAME      DRIVER    SCOPE
# abc123def456   bridge    bridge    local
# def456ghi789   host      host      local
# ghi789jkl012   none      null      local

# 2. 创建自定义网络
docker network create my-network
# 输出结果:网络ID

# 3. 查看网络详情
docker network inspect bridge
# 输出结果(JSON格式):
# [
#   {
#     "Name": "bridge",
#     "Id": "abc123def456",
#     "Created": "2023-10-01T00:00:00Z",
#     "Scope": "local",
#     "Driver": "bridge",
#     "Containers": {
#       "a1b2c3d4e5f6": {
#         "Name": "web-server",
#         "IPv4Address": "172.17.0.2/16"
#       }
#     }
#   }
# ]

# 4. 容器连接到网络
docker network connect my-network web-server

# 5. 断开网络连接
docker network disconnect my-network web-server

# 6. 删除网络
docker network rm my-network

5.4 数据卷管理命令

# 1. 创建数据卷
docker volume create mydata
# 输出结果:mydata

# 2. 查看数据卷
docker volume ls
# 输出结果:
# DRIVER    VOLUME NAME
# local     mydata

# 3. 查看数据卷详情
docker volume inspect mydata
# 输出结果:
# [
#   {
#     "CreatedAt": "2023-10-01T10:00:00Z",
#     "Driver": "local",
#     "Labels": {},
#     "Mountpoint": "/var/lib/docker/volumes/mydata/_data",
#     "Name": "mydata",
#     "Options": {},
#     "Scope": "local"
#   }
# ]

# 4. 使用数据卷
docker run -d --name mysql \
  -v mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=123456 \
  mysql:8.0
# 查看数据卷使用情况
docker inspect mysql | grep -A 5 Mounts
# 输出结果:
# "Mounts": [
#   {
#     "Type": "volume",
#     "Name": "mysql-data",
#     "Source": "/var/lib/docker/volumes/mysql-data/_data",
#     "Destination": "/var/lib/mysql"
#   }
# ]

# 5. 删除数据卷
docker volume rm mydata

5.5 Docker系统命令

# 1. 查看系统信息
docker system info
# 输出结果:
# Client: Docker Engine - Community
# Version:    24.0.5
# Context:    default
# Debug Mode: false
# Server: Docker Engine - Community
# Engine:
#  Version:          24.0.5
#  Containers:       5
#  Running:          3
#  Paused:           0
#  Stopped:          2
#  Images:           15
#  Server Version:   24.0.5
#  Storage Driver:   overlay2
#  ...

# 2. 查看磁盘使用情况
docker system df
# 输出结果:
# TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
# Images          5         3         1.2GB     600MB (50%)
# Containers      3         2         120MB     0B (0%)
# Local Volumes   2         1         200MB     100MB (50%)
# Build Cache     0         0         0B        0B

# 3. 清理无用资源
docker system prune
# 输出结果:
# WARNING! This will remove:
#   - all stopped containers
#   - all networks not used by at least one container
#   - all dangling images
#   - all build cache
# Are you sure you want to continue? [y/N] y
# Deleted Containers: 2
# Deleted Networks: 1
# Deleted Images: 3
# Total reclaimed space: 450MB

六、Docker运行参数详解

6.1 基础运行参数

# 完整示例
docker run -d \
  --name my-app \
  --hostname app-server \
  --restart=always \
  -p 8080:80 \
  -p 8443:443 \
  -v /data/app:/app \
  -v /etc/localtime:/etc/localtime:ro \
  -e NODE_ENV=production \
  -e TZ=Asia/Shanghai \
  --memory="512m" \
  --cpus="1.0" \
  --cpu-shares=512 \
  --memory-swap="1g" \
  --memory-reservation="256m" \
  --blkio-weight=500 \
  --ulimit nofile=1024:1024 \
  --log-driver=json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  --health-cmd="curl -f http://localhost/health || exit 1" \
  --health-interval=30s \
  --health-timeout=3s \
  --health-retries=3 \
  --network=my-network \
  --dns=8.8.8.8 \
  --dns-search=mydomain.com \
  nginx:latest

6.2 常用参数说明表

参数说明示例默认值
-d后台运行容器-d前台运行
-it交互式终端-it
--name容器名称--name web随机名称
-p端口映射-p 80:80
-P随机端口映射-P
-v数据卷挂载-v /data:/app
-e环境变量-e KEY=value
--network网络连接--network bridgebridge
--restart重启策略--restart=alwaysno
--memory内存限制--memory="512m"无限制
--cpusCPU限制--cpus="1.5"无限制

七、Dockerfile最佳实践示例

# 多阶段构建示例
# 第一阶段:构建阶段
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

# 第二阶段:运行时阶段
FROM node:18-alpine
WORKDIR /app

# 创建非root用户
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001

# 从构建阶段复制文件
COPY --from=builder /app/node_modules ./node_modules
COPY . .

# 设置权限
RUN chown -R nodejs:nodejs /app
USER nodejs

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node healthcheck.js || exit 1

# 暴露端口
EXPOSE 3000

# 启动命令
CMD ["node", "server.js"]

构建命令:

# 构建镜像
docker build -t myapp:1.0.0 .

# 查看构建历史
docker history myapp:1.0.0
# 输出结果:
# IMAGE          CREATED BY                                      SIZE
# abc123def456   CMD ["node" "server.js"]                       0B
# def456ghi789   USER nodejs                                    0B
# ghi789jkl012   RUN /bin/sh -c chown -R nodejs:nodejs /app     4.5kB
# ...

# 使用多架构构建
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:multi-arch .

八、Docker Compose实战示例

8.1 完整docker-compose.yml

version: '3.8'

services:
  # Web服务
  web:
    image: nginx:1.23.0-alpine
    container_name: my-web
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - ./html:/usr/share/nginx/html
      - ./logs:/var/log/nginx
    environment:
      - TZ=Asia/Shanghai
      - NGINX_PORT=80
    env_file:
      - .env
    networks:
      - frontend
    depends_on:
      - app
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # 应用服务
  app:
    build: 
      context: .
      dockerfile: Dockerfile
      args:
        NODE_ENV: production
    image: myapp:1.0.0
    container_name: my-app
    restart: always
    expose:
      - "3000"
    volumes:
      - app-data:/app/data
      - /etc/localtime:/etc/localtime:ro
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
      - REDIS_URL=redis://cache:6379/0
    networks:
      - frontend
      - backend
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started

  # 数据库服务
  db:
    image: postgres:15-alpine
    container_name: my-db
    restart: unless-stopped
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: mydb
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U admin"]
      interval: 10s
      timeout: 5s
      retries: 5
    ports:
      - "5432:5432"

  # 缓存服务
  cache:
    image: redis:7-alpine
    container_name: my-cache
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis-data:/data
    networks:
      - backend
    ports:
      - "6379:6379"

  # 监控服务
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
    ports:
      - "9090:9090"
    networks:
      - monitoring

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    volumes:
      - grafana-data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
    ports:
      - "3000:3000"
    networks:
      - monitoring
    depends_on:
      - prometheus

networks:
  frontend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16
  backend:
    driver: bridge
  monitoring:
    driver: bridge

volumes:
  app-data:
    driver: local
  postgres-data:
    driver: local
  redis-data:
    driver: local
  prometheus-data:
    driver: local
  grafana-data:
    driver: local

8.2 Compose常用命令

# 1. 启动服务
docker-compose up -d
# 输出结果:
# Creating network "project_frontend" with driver "bridge"
# Creating network "project_backend" with driver "bridge"
# Creating network "project_monitoring" with driver "bridge"
# Creating volume "project_app-data" with driver "local"
# Creating volume "project_postgres-data" with driver "local"
# Creating volume "project_redis-data" with driver "local"
# Creating volume "project_prometheus-data" with driver "local"
# Creating volume "project_grafana-data" with driver "local"
# Creating my-cache ... done
# Creating my-db    ... done
# Creating my-app   ... done
# Creating prometheus ... done
# Creating grafana    ... done
# Creating my-web     ... done

# 2. 查看服务状态
docker-compose ps
# 输出结果:
#     Name                Command              State                    Ports
# ------------------------------------------------------------------------------------
# grafana      /run.sh                        Up      0.0.0.0:3000->3000/tcp
# my-app       docker-entrypoint.sh node ...  Up      3000/tcp
# my-cache     docker-entrypoint.sh redis ... Up      0.0.0.0:6379->6379/tcp
# my-db        docker-entrypoint.sh postgres  Up      0.0.0.0:5432->5432/tcp
# my-web       /docker-entrypoint.sh ngin ... Up      0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
# prometheus   /bin/prometheus --config.f ... Up      0.0.0.0:9090->9090/tcp

# 3. 查看日志
docker-compose logs -f
# 输出结果(实时日志):
# my-app    | Server running on port 3000
# my-db     | database system is ready to accept connections
# my-web    | 172.20.0.1 - - [01/Oct/2023:10:00:00 +0000] "GET / HTTP/1.1" 200 612

# 4. 执行命令
docker-compose exec app npm test
# 在app服务中执行npm test命令

# 5. 停止服务
docker-compose stop
# 输出结果:
# Stopping my-web     ... done
# Stopping grafana    ... done
# Stopping prometheus ... done
# Stopping my-app     ... done
# Stopping my-db      ... done
# Stopping my-cache   ... done

# 6. 停止并删除资源
docker-compose down
# 输出结果:
# Stopping my-web     ... done
# Removing my-web     ... done
# Removing grafana    ... done
# Removing prometheus ... done
# Removing my-app     ... done
# Removing my-db      ... done
# Removing my-cache   ... done
# Removing network project_frontend
# Removing network project_backend
# Removing network project_monitoring
# Removing volume project_app-data
# Removing volume project_postgres-data
# Removing volume project_redis-data
# Removing volume project_prometheus-data
# Removing volume project_grafana-data

九、Docker配置深度解析

9.1 守护进程配置(/etc/docker/daemon.json)

{
  "authorization-plugins": [],
  "data-root": "/var/lib/docker",
  "exec-opts": ["native.cgroupdriver=systemd"],
  "dns": ["8.8.8.8", "114.114.114.114"],
  "dns-opts": [],
  "dns-search": ["mydomain.com"],
  "hosts": [
    "unix:///var/run/docker.sock",
    "tcp://0.0.0.0:2376"
  ],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3",
    "labels": "production_status",
    "env": "os,customer"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ],
  "labels": ["env=production"],
  "live-restore": true,
  "max-concurrent-downloads": 3,
  "max-concurrent-uploads": 5,
  "default-shm-size": "64m",
  "shutdown-timeout": 15,
  "debug": false,
  "experimental": false,
  "features": {
    "buildkit": true
  },
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com"
  ],
  "insecure-registries": [
    "192.168.1.100:5000"
  ],
  "runtimes": {
    "nvidia": {
      "path": "/usr/bin/nvidia-container-runtime",
      "runtimeArgs": []
    }
  },
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 65536,
      "Soft": 65536
    },
    "nproc": {
      "Name": "nproc",
      "Hard": 65536,
      "Soft": 65536
    }
  },
  "log-level": "info",
  "iptables": true,
  "ip-forward": true,
  "ip-masq": true,
  "userland-proxy": true,
  "userland-proxy-path": "/usr/libexec/docker-proxy",
  "ip": "0.0.0.0",
  "bridge": "",
  "bip": "",
  "fixed-cidr": "",
  "fixed-cidr-v6": "",
  "mtu": 0,
  "default-gateway": "",
  "default-gateway-v6": "",
  "raw-logs": false,
  "allow-nondistributable-artifacts": [],
  "registry-configs": {},
  "service-cluster-ip-range": "10.96.0.0/12",
  "default-address-pools": [
    {
      "base": "172.80.0.0/16",
      "size": 24
    },
    {
      "base": "172.90.0.0/16",
      "size": 24
    }
  ]
}

9.2 配置项详解

配置项说明默认值推荐值
data-rootDocker数据存储路径/var/lib/docker根据磁盘空间调整
log-driver日志驱动json-filejson-filejournald
log-opts.max-size单个日志文件最大大小-1(无限制)10m
log-opts.max-file最大日志文件数13
storage-driver存储驱动自动检测overlay2
registry-mirrors镜像加速器国内镜像源地址
live-restore守护进程重启时保持容器falsetrue
max-concurrent-downloads最大并发下载数33-5
max-concurrent-uploads最大并发上传数55

十、Docker网络模式详解

10.1 四种网络模式对比

# 1. bridge模式(默认)
docker run -d --name web1 --network bridge nginx
# 查看网络详情
docker network inspect bridge
# 输出结果:容器获得172.17.0.x网段IP

# 2. host模式
docker run -d --name web2 --network host nginx
# 容器直接使用宿主机网络,无IP隔离
# 验证:容器内执行ifconfig,与宿主机一致

# 3. none模式
docker run -d --name web3 --network none nginx
# 容器只有lo回环接口
docker exec web3 ip addr
# 输出结果:
# 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536
# 只有lo接口,无eth0

# 4. container模式
# 创建一个容器
docker run -d --name base-container nginx
# 共享网络命名空间
docker run -d --name shared-container --network container:base-container nginx
# 两个容器共享网络栈
docker exec base-container ip addr
docker exec shared-container ip addr
# 输出结果:两个容器的IP地址完全相同

10.2 自定义网络实战

# 创建自定义bridge网络
docker network create --driver bridge \
  --subnet=172.20.0.0/16 \
  --ip-range=172.20.1.0/24 \
  --gateway=172.20.0.1 \
  my-custom-network

# 查看网络配置
docker network inspect my-custom-network
# 输出结果:
# [
#   {
#     "Name": "my-custom-network",
#     "Id": "network-id",
#     "Created": "2023-10-01T10:00:00Z",
#     "Scope": "local",
#     "Driver": "bridge",
#     "EnableIPv6": false,
#     "IPAM": {
#       "Driver": "default",
#       "Options": {},
#       "Config": [
#         {
#           "Subnet": "172.20.0.0/16",
#           "IPRange": "172.20.1.0/24",
#           "Gateway": "172.20.0.1"
#         }
#       ]
#     },
#     "Internal": false,
#     "Attachable": false,
#     "Ingress": false,
#     "ConfigFrom": {
#       "Network": ""
#     },
#     "ConfigOnly": false,
#     "Containers": {},
#     "Options": {},
#     "Labels": {}
#   }
# ]

# 在自定义网络中运行容器
docker run -d --name app1 --network my-custom-network nginx
docker run -d --name app2 --network my-custom-network nginx

# 测试网络连通性
docker exec app1 ping app2
# 输出结果:
# PING app2 (172.20.1.2) 56(84) bytes of data.
# 64 bytes from 172.20.1.2: icmp_seq=1 ttl=64 time=0.052 ms
# 64 bytes from 172.20.1.2: icmp_seq=2 ttl=64 time=0.043 ms

十一、Docker存储驱动原理

11.1 存储驱动对比

存储驱动优点缺点适用场景
overlay2性能好,内存使用少,支持最多128层需要Linux内核4.0+生产环境首选
aufs兼容性好,支持更多层性能较差,官方不再推荐旧系统兼容
devicemapper直接操作块设备配置复杂,性能一般特定场景
btrfs支持快照,压缩稳定性有待验证需要快照功能
zfs高级功能多内存占用大大规模存储

11.2 存储驱动配置

# 检查当前存储驱动
docker info | grep "Storage Driver"
# 输出结果:
# Storage Driver: overlay2
#  Backing Filesystem: xfs
#  Supports d_type: true
#  Native Overlay Diff: true

# 修改存储驱动
# 编辑 /etc/docker/daemon.json
{
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}

十二、Docker安全最佳实践

12.1 安全配置示例

# 1. 使用非root用户
# Dockerfile中
RUN addgroup -g 1000 -S appuser && \
    adduser -S -D -H -u 1000 -h /app -s /sbin/nologin -G appuser appuser
USER appuser

# 2. 设置容器只读
docker run -d --read-only --tmpfs /tmp nginx:alpine

# 3. 限制能力
docker run -d --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx:alpine

# 4. 设置安全策略
docker run -d \
  --security-opt=no-new-privileges \
  --security-opt=seccomp=unconfined \
  nginx:alpine

# 5. 使用AppArmor
docker run -d --security-opt apparmor=docker-default nginx:alpine

# 6. 资源限制
docker run -d \
  --memory="256m" \
  --memory-swap="512m" \
  --cpus="0.5" \
  --cpu-shares=512 \
  --blkio-weight=100 \
  --pids-limit=100 \
  nginx:alpine

12.2 安全扫描

# 使用Docker安全扫描
docker scan nginx:latest
# 输出结果:
# ✗ High severity vulnerability found in apt/libapt-pkg6.0
# Description: Buffer Overflow
# Info: https://snyk.io/vuln/SNYK-DEBIAN11-APT-1916438
# Introduced through: apt@2.2.4, apt/libapt-pkg6.0@2.2.4
# From: apt@2.2.4
# From: apt/libapt-pkg6.0@2.2.4
# Fixed in: 2.2.4-1
# 
# ✗ Medium severity vulnerability found in openssl/libssl1.1
# ...

# 使用Trivy扫描
trivy image nginx:latest

十三、Docker性能监控与调优

13.1 监控命令

# 1. 查看容器资源使用
docker stats
# 输出结果:
# CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT     MEM %     NET I/O          BLOCK I/O   PIDS
# a1b2c3d4e5f6   web1      0.05%     15.3MiB / 1GiB        1.50%     1.2kB / 648B     0B / 0B     3
# b2c3d4e5f6a1   db1       2.15%     120.4MiB / 2GiB       5.88%     12.4kB / 8.2kB   0B / 0B     12

# 2. 查看容器详情
docker inspect --format='{{json .State}}' my-container
# 输出结果:
# {"Status":"running","Running":true,"Paused":false,"Restarting":false,...

# 3. 查看容器进程
docker top my-container
# 输出结果:
# UID    PID    PPID   C   STIME   TTY   TIME       CMD
# root   1234   5678   0   10:00   ?     00:00:00   nginx: master process
# nginx  1235   1234   0   10:00   ?     00:00:00   nginx: worker process

# 4. 性能分析
docker run -d --name perf-container \
  --memory="512m" \
  --cpus="1.0" \
  --cpu-quota=100000 \
  --cpu-period=100000 \
  nginx:alpine

13.2 性能优化配置

# 创建优化配置的容器
docker run -d --name optimized-app \
  # CPU限制
  --cpus="2" \
  --cpu-shares=1024 \
  --cpuset-cpus="0-3" \
  --cpu-quota=200000 \
  --cpu-period=100000 \
  
  # 内存限制
  --memory="1g" \
  --memory-swap="2g" \
  --memory-reservation="512m" \
  --kernel-memory="256m" \
  --memory-swappiness=60 \
  
  # IO限制
  --blkio-weight=500 \
  --device-read-bps="/dev/sda:10mb" \
  --device-write-bps="/dev/sda:10mb" \
  --device-read-iops="/dev/sda:1000" \
  --device-write-iops="/dev/sda:1000" \
  
  # 进程限制
  --pids-limit=200 \
  --ulimit nofile=65536:65536 \
  --ulimit nproc=65536:65536 \
  
  # 网络优化
  --network=host \
  --dns="8.8.8.8" \
  --dns-option="timeout:3" \
  --dns-option="attempts:2" \
  
  nginx:alpine

十四、企业级生产环境部署实战

14.1 完整部署脚本

#!/bin/bash
# deploy.sh - Docker生产环境部署脚本

set -e  # 遇到错误立即退出

# 配置变量
APP_NAME="myapp"
VERSION="1.0.0"
REGISTRY="registry.mycompany.com"
ENVIRONMENT="production"

# 1. 清理旧容器和镜像
echo "清理旧资源..."
docker stop ${APP_NAME} 2>/dev/null || true
docker rm ${APP_NAME} 2>/dev/null || true
docker rmi ${REGISTRY}/${APP_NAME}:${VERSION} 2>/dev/null || true

# 2. 拉取最新镜像
echo "拉取镜像..."
docker pull ${REGISTRY}/${APP_NAME}:${VERSION}

# 3. 检查镜像安全
echo "安全扫描..."
docker scan ${REGISTRY}/${APP_NAME}:${VERSION} --json > scan-report.json

# 4. 运行容器
echo "启动容器..."
docker run -d \
  --name ${APP_NAME} \
  --hostname ${APP_NAME}-$(hostname) \
  --restart=always \
  --log-driver=json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  --memory="2g" \
  --memory-swap="3g" \
  --cpus="2.0" \
  --cpu-quota=200000 \
  --cpu-period=100000 \
  --pids-limit=200 \
  --ulimit nofile=65536:65536 \
  --ulimit nproc=65536:65536 \
  --security-opt=no-new-privileges \
  --cap-drop=ALL \
  --cap-add=NET_BIND_SERVICE \
  --health-cmd="curl -f http://localhost:8080/health || exit 1" \
  --health-interval=30s \
  --health-timeout=5s \
  --health-retries=3 \
  --health-start-period=60s \
  -p 8080:8080 \
  -p 8443:8443 \
  -v /data/${APP_NAME}/logs:/app/logs \
  -v /data/${APP_NAME}/data:/app/data \
  -v /etc/localtime:/etc/localtime:ro \
  -v /etc/timezone:/etc/timezone:ro \
  -e NODE_ENV=${ENVIRONMENT} \
  -e TZ=Asia/Shanghai \
  -e APP_VERSION=${VERSION} \
  --env-file .env.production \
  --label "com.mycompany.app=${APP_NAME}" \
  --label "com.mycompany.version=${VERSION}" \
  --label "com.mycompany.environment=${ENVIRONMENT}" \
  --label "com.mycompany.maintainer=devops@mycompany.com" \
  ${REGISTRY}/${APP_NAME}:${VERSION}

# 5. 等待健康检查
echo "等待应用启动..."
for i in {1..30}; do
  if docker inspect --format='{{.State.Health.Status}}' ${APP_NAME} | grep -q "healthy"; then
    echo "应用健康检查通过"
    break
  fi
  echo "等待应用就绪... ($i/30)"
  sleep 2
done

# 6. 验证部署
echo "验证部署..."
CONTAINER_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ${APP_NAME})
if curl -sf http://${CONTAINER_IP}:8080/health > /dev/null; then
  echo "✅ 部署成功!应用运行在: http://$(hostname -I | awk '{print $1}'):8080"
else
  echo "❌ 部署失败!"
  docker logs ${APP_NAME} --tail 50
  exit 1
fi

# 7. 清理旧镜像
echo "清理无用镜像..."
docker image prune -f

echo "部署完成!"

14.2 监控与告警配置

# docker-compose.monitoring.yml
version: '3.8'

services:
  # 指标收集
  node-exporter:
    image: prom/node-exporter:latest
    container_name: node-exporter
    restart: unless-stopped
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.rootfs=/rootfs'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
    ports:
      - "9100:9100"
    networks:
      - monitoring

  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    container_name: cadvisor
    restart: unless-stopped
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
      - /dev/disk/:/dev/disk:ro
    ports:
      - "8080:8080"
    networks:
      - monitoring

  # 日志收集
  loki:
    image: grafana/loki:latest
    container_name: loki
    restart: unless-stopped
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml
    networks:
      - monitoring

  promtail:
    image: grafana/promtail:latest
    container_name: promtail
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
    command: -config.file=/etc/promtail/config.yml
    networks:
      - monitoring

  # 告警管理
  alertmanager:
    image: prom/alertmanager:latest
    container_name: alertmanager
    restart: unless-stopped
    ports:
      - "9093:9093"
    volumes:
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
    command:
      - '--config.file=/etc/alertmanager/alertmanager.yml'
      - '--storage.path=/alertmanager'
    networks:
      - monitoring

  # 可视化
  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    restart: unless-stopped
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
      - GF_INSTALL_PLUGINS=grafana-piechart-panel
    volumes:
      - grafana-data:/var/lib/grafana
      - ./dashboards:/etc/grafana/provisioning/dashboards
      - ./datasources:/etc/grafana/provisioning/datasources
    ports:
      - "3000:3000"
    networks:
      - monitoring
    depends_on:
      - prometheus
      - loki

networks:
  monitoring:
    driver: bridge

volumes:
  grafana-data:
    driver: local

十五、Docker故障排查与调试

15.1 常见问题排查命令

# 1. 容器启动失败排查
docker run -d --name test nginx:latest
# 如果启动失败,查看日志
docker logs test
# 输出错误信息

# 2. 容器无法连接网络
docker exec test ping 8.8.8.8
# 如果ping不通,检查网络配置
docker network inspect bridge
docker inspect test | grep -A 20 "NetworkSettings"

# 3. 容器性能问题
# 查看容器资源使用
docker stats test
# 查看容器内进程
docker top test
# 进入容器查看
docker exec -it test bash
# 在容器内执行:
top
free -m
df -h
netstat -tulpn

# 4. 镜像构建失败
docker build -t myapp .
# 如果失败,使用--no-cache重新构建
docker build --no-cache -t myapp .
# 或者查看中间层
docker history myapp

# 5. 数据卷问题
# 查看数据卷挂载
docker inspect test | grep -A 10 Mounts
# 检查数据卷权限
docker exec test ls -la /data

# 6. 端口冲突
# 查看已占用端口
netstat -tulpn | grep :80
# 或者使用lsof
lsof -i :80
# 修改端口映射
docker run -d -p 8080:80 nginx

# 7. DNS解析问题
# 检查容器DNS配置
docker run --rm alpine nslookup google.com
# 如果解析失败,检查宿主机DNS
cat /etc/resolv.conf
# 或者指定DNS
docker run --dns=8.8.8.8 --rm alpine nslookup google.com

15.2 调试工具使用

# 1. 使用docker events监控事件
docker events --filter 'type=container' --since '2023-10-01'
# 输出结果:
# 2023-10-01T10:00:00.000000000Z container create a1b2c3d4e5f6 (image=nginx, name=web)
# 2023-10-01T10:00:01.000000000Z container start a1b2c3d4e5f6 (image=nginx, name=web)

# 2. 使用docker diff查看容器文件变化
docker diff test-container
# 输出结果:
# A /app/newfile.txt   # 新增文件
# C /etc/nginx/nginx.conf  # 修改文件
# D /tmp/oldfile.txt  # 删除文件

# 3. 使用docker checkpoint进行检查点
# 创建检查点
docker checkpoint create my-container checkpoint1
# 恢复检查点
docker start --checkpoint checkpoint1 my-container

# 4. 使用docker system df查看磁盘使用
docker system df
# 输出结果:
# TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
# Images          5         3         1.5GB     800MB (53%)
# Containers      3         2         200MB     0B (0%)
# Local Volumes   2         1         300MB     150MB (50%)
# Build Cache     0         0         0B        0B

# 5. 使用docker system prune清理资源
docker system prune -a
# 输出结果:
# Total reclaimed space: 2.1GB

十六、Docker与其他技术集成

16.1 Docker与Kubernetes集成

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.23.0
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "128Mi"
            cpu: "250m"
          limits:
            memory: "256Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 10
        volumeMounts:
        - name: nginx-config
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
      volumes:
      - name: nginx-config
        configMap:
          name: nginx-config

16.2 Docker与CI/CD集成

# .gitlab-ci.yml
stages:
  - build
  - test
  - scan
  - deploy

variables:
  DOCKER_HOST: tcp://docker:2375
  DOCKER_DRIVER: overlay2
  CONTAINER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA

build:
  stage: build
  image: docker:20.10
  services:
    - docker:20.10-dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $CONTAINER_IMAGE .
    - docker push $CONTAINER_IMAGE
  only:
    - main
    - develop

test:
  stage: test
  image: $CONTAINER_IMAGE
  script:
    - echo "Running tests..."
    - npm test
  needs: ["build"]

scan:
  stage: scan
  image: docker:20.10
  services:
    - docker:20.10-dind
  script:
    - docker pull $CONTAINER_IMAGE
    - docker scan $CONTAINER_IMAGE --json > scan-report.json
    - cat scan-report.json
  allow_failure: true
  needs: ["build"]

deploy:
  stage: deploy
  image: alpine:latest
  script:
    - apk add --no-cache curl
    - |
      curl -X POST \
        -H "Content-Type: application/json" \
        -d '{"image": "'$CONTAINER_IMAGE'"}' \
        https://deploy.mycompany.com/api/deploy
  environment:
    name: production
    url: https://myapp.mycompany.com
  when: manual
  only:
    - main

十七、总结与最佳实践

17.1 Docker使用总结

通过本指南,你应该已经掌握了:

  1. 基础概念:镜像、容器、仓库的核心概念
  2. 常用命令:完整的Docker命令分类和使用
  3. 高级特性:网络、存储、安全、监控
  4. 生产实践:企业级部署、监控、故障排查
  5. 生态集成:与Kubernetes、CI/CD的集成

17.2 最佳实践清单

镜像管理

  • 使用官方基础镜像
  • 保持镜像最小化(使用Alpine版本)
  • 多阶段构建减少镜像大小
  • 定期更新基础镜像安全补丁

容器运行

  • 使用非root用户运行
  • 设置资源限制
  • 配置健康检查
  • 使用只读文件系统

网络配置

  • 使用自定义网络
  • 避免使用host网络模式
  • 合理规划IP段
  • 配置DNS解析

存储管理

  • 使用数据卷持久化重要数据
  • 备份数据卷
  • 监控存储使用
  • 合理选择存储驱动

安全实践

  • 最小权限原则
  • 定期安全扫描
  • 使用安全上下文
  • 配置网络策略

监控告警

  • 配置资源监控
  • 设置日志收集
  • 配置告警规则
  • 定期审计

17.3 下一步学习路径

  1. Docker Compose高级用法
  2. Docker Swarm集群管理
  3. Kubernetes容器编排
  4. Service Mesh服务网格
  5. 云原生全栈技术

从简单的单容器应用开始,逐步尝试多容器编排,最终实现完整的CI/CD流水线。

更多推荐