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

社区和论坛

视频教程

认证和培训

更多推荐