Docker 详细介绍

Docker 是什么?

Docker 是一个开源的容器化平台,用于开发、部署和运行应用程序。它将应用程序及其依赖项打包到一个标准化的单元(容器)中,确保在任何环境中都能一致运行。

Docker 的核心概念

1. 容器(Container)

  • 轻量级、可执行的软件包

  • 包含运行应用程序所需的一切

  • 与宿主机和其他容器隔离

2. 镜像(Image)

  • 容器的只读模板

  • 包含应用程序代码、运行时、库、环境变量和配置文件

  • 多层结构,便于复用和增量更新

3. 仓库(Registry)

  • 存储和分发 Docker 镜像的地方

  • 公共仓库:Docker Hub

  • 私有仓库:企业自建

4. Dockerfile

  • 用于构建 Docker 镜像的文本文件

  • 包含一系列指令

Docker 的优势

1. 环境一致性

  • "一次构建,到处运行"

  • 消除"在我机器上能运行"的问题

2. 快速部署

  • 秒级启动和停止

  • 轻量级,资源占用少

3. 隔离性

  • 进程级别的隔离

  • 资源限制和控制

4. 版本控制和组件重用

  • 镜像版本管理

  • 基础镜像复用

5. 微服务友好

  • 每个服务独立容器化

  • 便于扩展和更新

Docker 安装

1. Linux 安装

bash

# Ubuntu/Debian
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# 验证安装
sudo docker --version

# 将当前用户添加到 docker 组(避免每次使用 sudo)
sudo usermod -aG docker $USER
# 重新登录或执行以下命令
newgrp docker

2. macOS 安装

bash

# 使用 Homebrew
brew install --cask docker

# 或从 Docker 官网下载 Docker Desktop
# https://www.docker.com/products/docker-desktop/

3. Windows 安装

bash

# 从 Docker 官网下载 Docker Desktop
# 需要 Windows 10/11 Pro 或 Enterprise 版本
# 或使用 WSL2

Docker 基础命令

1. 镜像管理

bash

# 搜索镜像
docker search nginx
docker search ubuntu --filter "is-official=true"

# 拉取镜像
docker pull ubuntu:20.04
docker pull nginx:latest
docker pull python:3.9-slim

# 列出本地镜像
docker images
docker image ls
docker images -a  # 显示所有镜像(包括中间层)

# 删除镜像
docker rmi ubuntu:20.04
docker image rm nginx:latest
docker image prune  # 删除未使用的镜像
docker image prune -a  # 删除所有未使用的镜像

# 镜像标签
docker tag ubuntu:20.04 my-ubuntu:v1

# 查看镜像详情
docker image inspect ubuntu:20.04

# 保存镜像到文件
docker save -o ubuntu.tar ubuntu:20.04

# 从文件加载镜像
docker load -i ubuntu.tar

2. 容器管理

bash

# 运行容器
docker run ubuntu:20.04 echo "Hello Docker"
docker run -it ubuntu:20.04 /bin/bash  # 交互式运行
docker run -d -p 80:80 --name my-nginx nginx  # 后台运行
docker run -d --name myapp -v $(pwd):/app -w /app python:3.9 python app.py

# 常用运行选项
docker run \
  -d \                    # 后台运行
  --name mycontainer \    # 容器名称
  -p 8080:80 \            # 端口映射 主机:容器
  -v /host/path:/container/path \  # 卷挂载
  -e ENV_VAR=value \      # 环境变量
  --network mynetwork \   # 网络
  --restart=always \      # 重启策略
  --memory="512m" \       # 内存限制
  --cpus="1.5" \          # CPU限制
  image:tag

# 列出容器
docker ps          # 运行中的容器
docker ps -a       # 所有容器
docker ps -q       # 只显示容器ID
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

# 启动/停止/重启容器
docker start mycontainer
docker stop mycontainer
docker restart mycontainer
docker pause mycontainer
docker unpause mycontainer

# 进入容器
docker exec -it mycontainer /bin/bash
docker exec mycontainer ls /app

# 查看容器日志
docker logs mycontainer
docker logs -f mycontainer  # 实时查看
docker logs --tail 100 mycontainer
docker logs --since 10m mycontainer

# 查看容器进程
docker top mycontainer

# 查看容器详情
docker inspect mycontainer

# 容器与主机文件复制
docker cp mycontainer:/app/config.json ./config.json
docker cp ./data.txt mycontainer:/tmp/data.txt

# 删除容器
docker rm mycontainer
docker rm -f mycontainer  # 强制删除运行中的容器
docker container prune    # 删除所有停止的容器

3. 容器状态管理

bash

# 查看容器资源使用
docker stats
docker stats mycontainer
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"

# 查看容器端口映射
docker port mycontainer

# 重命名容器
docker rename old_name new_name

# 更新容器配置
docker update --restart=always mycontainer
docker update --memory=1g mycontainer

Dockerfile 详解

1. 基本结构

dockerfile

# 基础镜像
FROM ubuntu:20.04

# 维护者信息(可选)
LABEL maintainer="your.email@example.com"
LABEL version="1.0"
LABEL description="My application"

# 设置环境变量
ENV DEBIAN_FRONTEND=noninteractive
ENV APP_HOME=/app
ENV PYTHONUNBUFFERED=1

# 设置工作目录
WORKDIR $APP_HOME

# 复制文件
COPY requirements.txt .
COPY src/ ./src/
COPY --from=stage0 /build/output /app  # 多阶段构建

# 添加文件(支持URL和解压)
ADD https://example.com/data.tar.gz /tmp/
ADD app.tar.gz /app/

# 运行命令
RUN apt update && apt install -y \
    python3 \
    python3-pip \
    && pip3 install --no-cache-dir -r requirements.txt \
    && apt clean \
    && rm -rf /var/lib/apt/lists/*

# 暴露端口
EXPOSE 8080

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:8080/health || exit 1

# 用户切换
USER appuser

# 入口点
ENTRYPOINT ["python3"]

# 命令参数
CMD ["app.py"]

2. 最佳实践示例

dockerfile

# 多阶段构建示例
# 第一阶段:构建环境
FROM python:3.9-slim AS builder

WORKDIR /app
COPY requirements.txt .
RUN pip install --user -r requirements.txt

# 第二阶段:运行环境
FROM python:3.9-slim

# 创建非root用户
RUN groupadd -r appgroup && useradd -r -g appgroup appuser

WORKDIR /app

# 从构建阶段复制已安装的包
COPY --from=builder /root/.local /home/appuser/.local
COPY --chown=appuser:appgroup . .

# 设置用户
USER appuser

# 添加到PATH
ENV PATH=/home/appuser/.local/bin:$PATH

# 健康检查
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s \
  CMD python healthcheck.py

EXPOSE 8080

CMD ["python", "app.py"]

3. 构建镜像

bash

# 构建镜像
docker build -t myapp:latest .
docker build -t myapp:v1.0 -f Dockerfile.prod .

# 构建参数
docker build \
  --build-arg VERSION=1.0 \
  --no-cache \          # 不使用缓存
  --progress=plain \    # 详细输出
  -t myapp:latest .

# 查看构建历史
docker history myapp:latest

Docker Compose

1. docker-compose.yml 示例

yaml

version: '3.8'

services:
  web:
    image: nginx:alpine
    container_name: my-nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./html:/usr/share/nginx/html
      - ./logs:/var/log/nginx
    environment:
      - NGINX_HOST=localhost
      - NGINX_PORT=80
    env_file:
      - .env
    networks:
      - frontend
    depends_on:
      - app
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 30s
      timeout: 10s
      retries: 3

  app:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        VERSION: 1.0
    image: myapp:latest
    container_name: my-app
    ports:
      - "8080:8080"
    volumes:
      - ./app:/app
      - app-data:/data
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
      - REDIS_URL=redis://redis:6379/0
    networks:
      - frontend
      - backend
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    command: ["python", "app.py"]
    deploy:
      resources:
        limits:
          cpus: '0.50'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M

  db:
    image: postgres:13-alpine
    container_name: postgres-db
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_INITDB_ARGS: "--encoding=UTF8 --lc-collate=C --lc-ctype=C"
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - backend
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:6-alpine
    container_name: redis-cache
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data
    networks:
      - backend
    ports:
      - "6379:6379"

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: phpmyadmin
    environment:
      PMA_HOST: db
      PMA_PORT: 5432
    ports:
      - "8081:80"
    networks:
      - backend
    depends_on:
      - db

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

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

2. Docker Compose 命令

bash

# 启动服务
docker-compose up
docker-compose up -d           # 后台运行
docker-compose up --build      # 重新构建并启动
docker-compose up web db       # 启动指定服务

# 停止服务
docker-compose down
docker-compose down -v         # 同时删除卷
docker-compose down --rmi all  # 同时删除镜像

# 查看状态
docker-compose ps
docker-compose top
docker-compose logs
docker-compose logs -f web     # 实时查看指定服务日志

# 服务管理
docker-compose start
docker-compose stop
docker-compose restart
docker-compose pause
docker-compose unpause

# 执行命令
docker-compose exec web bash
docker-compose exec db psql -U user -d mydb

# 构建
docker-compose build
docker-compose build --no-cache

# 其他
docker-compose config          # 验证配置
docker-compose pull            # 拉取镜像
docker-compose images          # 查看镜像
docker-compose port web 80     # 查看端口映射

Docker 网络

1. 网络类型

bash

# 查看网络
docker network ls

# 创建网络
docker network create my-network
docker network create --driver bridge --subnet 172.20.0.0/16 --gateway 172.20.0.1 my-network

# 容器连接网络
docker run --network my-network --name container1 nginx
docker network connect my-network existing-container
docker network disconnect my-network container1

# 查看网络详情
docker network inspect my-network

# 删除网络
docker network rm my-network
docker network prune  # 删除未使用的网络

2. 网络模式

bash

# bridge (默认)
docker run --network bridge nginx

# host (使用主机网络)
docker run --network host nginx

# none (无网络)
docker run --network none nginx

# container (共享其他容器网络)
docker run --network container:other-container nginx

# 自定义网络 (推荐)
docker network create app-network
docker run --network app-network --name service1 nginx
docker run --network app-network --name service2 nginx
# service1 和 service2 可以通过容器名互相访问

Docker 存储

1. 数据卷(Volumes)

bash

# 创建卷
docker volume create my-volume

# 列出卷
docker volume ls

# 使用卷
docker run -v my-volume:/data nginx
docker run --mount source=my-volume,target=/data nginx

# 查看卷详情
docker volume inspect my-volume

# 删除卷
docker volume rm my-volume
docker volume prune  # 删除未使用的卷

2. 绑定挂载(Bind Mounts)

bash

# 挂载主机目录
docker run -v /host/path:/container/path nginx
docker run --mount type=bind,source=/host/path,target=/container/path nginx

# 只读挂载
docker run -v /host/path:/container/path:ro nginx

3. 临时文件系统(tmpfs)

bash

# 内存中的临时文件系统
docker run --tmpfs /app/temp nginx
docker run --mount type=tmpfs,target=/app/temp nginx

Docker 多阶段构建

1. 示例:Go 应用

dockerfile

# 第一阶段:构建
FROM golang:1.18 AS builder

WORKDIR /app
COPY . .

# 编译
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# 第二阶段:运行
FROM alpine:latest

RUN apk --no-cache add ca-certificates

WORKDIR /root/

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

# 运行
CMD ["./main"]

2. 示例:Node.js 应用

dockerfile

# 第一阶段:依赖安装
FROM node:16 AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

# 第二阶段:构建
FROM node:16 AS builder
WORKDIR /app
COPY . .
COPY --from=deps /app/node_modules ./node_modules
RUN npm run build

# 第三阶段:运行
FROM node:16-alpine
WORKDIR /app

ENV NODE_ENV=production
USER node

COPY --from=builder /app/dist ./dist
COPY --from=deps /app/node_modules ./node_modules
COPY package.json .

EXPOSE 3000
CMD ["node", "dist/index.js"]

Docker 安全最佳实践

1. 最小化镜像

dockerfile

# 使用官方精简镜像
FROM python:3.9-slim

# 合并 RUN 命令,减少层数
RUN apt update && apt install -y \
    build-essential \
    && rm -rf /var/lib/apt/lists/*

2. 非 root 用户运行

dockerfile

# 创建用户和组
RUN groupadd -r appgroup && useradd -r -g appgroup appuser

# 设置用户
USER appuser

3. 扫描镜像漏洞

bash

# 使用 Docker Scout
docker scout cve myapp:latest

# 使用 Trivy
docker run --rm aquasec/trivy image myapp:latest

4. 安全配置

bash

# 限制容器资源
docker run --memory="512m" --cpus="1.0" nginx

# 只读根文件系统
docker run --read-only nginx

# 安全选项
docker run --security-opt="no-new-privileges" nginx
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx

实际应用示例

1. 开发环境

yaml

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

services:
  web:
    build: .
    volumes:
      - .:/app
      - /app/node_modules  # 防止覆盖容器内的 node_modules
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
    command: npm run dev

  db:
    image: postgres:13
    environment:
      POSTGRES_PASSWORD: devpass
    volumes:
      - postgres-data:/var/lib/postgresql/data

  redis:
    image: redis:6-alpine
    ports:
      - "6379:6379"

volumes:
  postgres-data:

2. 生产环境

yaml

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

services:
  web:
    image: myregistry/myapp:${TAG:-latest}
    restart: always
    ports:
      - "80:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://user:${DB_PASSWORD}@db:5432/mydb
    depends_on:
      - db
    networks:
      - app-network
    deploy:
      resources:
        limits:
          memory: 512M

  db:
    image: postgres:13-alpine
    restart: always
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: mydb
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - app-network

networks:
  app-network:

volumes:
  postgres-data:

3. CI/CD 集成

yaml

# .gitlab-ci.yml 示例
stages:
  - build
  - test
  - deploy

variables:
  DOCKER_TLS_CERTDIR: ""

build:
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

test:
  stage: test
  script:
    - docker run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA npm test

deploy:
  stage: deploy
  script:
    - docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
    - docker push $CI_REGISTRY_IMAGE:latest
    - ssh deploy@server "cd /app && docker-compose pull && docker-compose up -d"

Docker 监控和日志

1. 日志管理

bash

# 日志驱动
docker run --log-driver=json-file nginx  # 默认
docker run --log-driver=syslog nginx
docker run --log-driver=journald nginx
docker run --log-driver=gelf nginx

# 日志选项
docker run --log-opt max-size=10m --log-opt max-file=3 nginx

# 查看日志
docker logs --tail 50 --follow --timestamps mycontainer

2. 监控工具

bash

# 使用 cAdvisor
docker run \
  --volume=/:/rootfs:ro \
  --volume=/var/run:/var/run:ro \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \
  --publish=8080:8080 \
  --detach=true \
  --name=cadvisor \
  google/cadvisor:latest

# 使用 Portainer(Web UI)
docker run -d -p 9000:9000 --name portainer \
  --restart=always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v portainer_data:/data \
  portainer/portainer-ce

常见问题解决

1. Docker 启动失败

bash

# 检查 Docker 服务状态
sudo systemctl status docker

# 查看 Docker 日志
sudo journalctl -u docker

# 常见问题:端口冲突
# 解决方案:修改 Docker 配置文件
sudo vim /etc/docker/daemon.json
{
  "hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]
}
sudo systemctl restart docker

2. 磁盘空间不足

bash

# 清理未使用的资源
docker system prune
docker system prune -a  # 更彻底
docker volume prune
docker image prune

# 查看磁盘使用
docker system df

# 清理特定资源
docker rm $(docker ps -aq)
docker rmi $(docker images -q)

3. 网络连接问题

bash

# 检查网络配置
docker network ls
docker network inspect bridge

# 重启 Docker 网络
sudo systemctl restart docker

# 自定义 DNS
# 在 /etc/docker/daemon.json 中添加
{
  "dns": ["8.8.8.8", "8.8.4.4"]
}

4. 权限问题

bash

# 将用户加入 docker 组
sudo usermod -aG docker $USER
newgrp docker

# 修复 Docker socket 权限
sudo chmod 666 /var/run/docker.sock

# 或者使用 sudo(不推荐长期使用)
sudo docker ps

Docker 高级特性

1. Docker Swarm(集群管理)

bash

# 初始化 Swarm
docker swarm init --advertise-addr <MANAGER-IP>

# 加入节点
docker swarm join --token <TOKEN> <MANAGER-IP>:2377

# 部署服务
docker service create --replicas 3 --name web nginx:alpine

# 查看服务
docker service ls
docker service ps web

# 更新服务
docker service update --image nginx:latest web

2. BuildKit(新一代构建工具)

bash

# 启用 BuildKit
export DOCKER_BUILDKIT=1

# 或修改 Docker 配置
# /etc/docker/daemon.json
{
  "features": {
    "buildkit": true
  }
}

# 使用 BuildKit 构建
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest .

3. Docker Content Trust(镜像签名)

bash

# 启用镜像签名
export DOCKER_CONTENT_TRUST=1

# 推送签名镜像
docker push myregistry/myapp:latest

# 拉取签名镜像
docker pull myregistry/myapp:latest

总结

Docker 已经成为现代软件开发和部署的标准工具,它通过容器化技术解决了环境一致性问题,提高了开发和运维效率。

学习建议

  1. 从基础命令开始,掌握镜像和容器的基本操作

  2. 学习编写 Dockerfile,理解镜像构建过程

  3. 掌握 Docker Compose,用于多容器应用管理

  4. 学习 Docker 网络和存储,理解容器间通信和数据持久化

  5. 实践安全最佳实践,确保生产环境安全

  6. 探索 Docker 生态,如 Kubernetes、监控工具等

Docker 的学习曲线相对平缓,但深度使用需要理解其背后的原理。建议在实际项目中应用所学知识,逐步掌握高级特性。

帮助文档和学习资源

官方文档

中文资源

学习平台

书籍推荐

  1. 《Docker 从入门到实践》 - 杨保华

  2. 《Docker 技术入门与实战》 - 杨保华

  3. 《Using Docker》 - Adrian Mouat

  4. 《Docker Deep Dive》 - Nigel Poulton

社区和论坛

视频教程

认证和培训

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐