Docker和Docker-Compose完全指南

Docker与Compose实用指南

ModelEngine·创作计划征文活动 10w+人浏览 1.4k人参与

Docker 和 Docker Compose 完全指南

在这里插入图片描述

目录

  1. Docker 简介
  2. Docker 安装
  3. Docker 核心概念
  4. Docker 基础使用
  5. Dockerfile 编写
  6. Docker Compose 简介
  7. Docker Compose 安装
  8. Docker Compose 使用
  9. 实战案例
  10. 最佳实践
  11. 常见问题

Docker 简介

什么是 Docker

Docker 是一个开源的容器化平台,它允许开发者将应用程序及其所有依赖项打包到一个轻量级、可移植的容器中。容器可以在任何支持 Docker 的系统上运行,确保应用在不同环境中的一致性。

Docker 的优势

  • 环境一致性: 消除"在我的机器上可以运行"的问题
  • 快速部署: 容器启动速度快,通常只需几秒钟
  • 资源隔离: 每个容器相互独立,互不影响
  • 轻量级: 相比虚拟机,容器共享主机内核,占用资源更少
  • 版本控制: 镜像可以进行版本管理
  • 可移植性: 一次构建,到处运行

Docker vs 虚拟机

特性Docker 容器虚拟机
启动时间秒级分钟级
磁盘占用MB 级别GB 级别
性能接近原生有性能损耗
系统支持每台主机支持数千个容器每台主机支持几十个虚拟机
隔离性进程级隔离操作系统级隔离

Docker 安装

Windows 安装

系统要求
  • Windows 10 64-bit: Pro, Enterprise, or Education (Build 19041 或更高)
  • 启用 WSL 2 功能
  • 启用虚拟化功能
安装步骤
  1. 启用 WSL 2

    打开 PowerShell(管理员模式):

    # 启用 WSL
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    
    # 启用虚拟机平台
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    
    # 重启计算机
    
  2. 下载并安装 WSL 2 Linux 内核更新包

    访问 Microsoft WSL 2 更新页面 下载并安装

  3. 设置 WSL 2 为默认版本

    wsl --set-default-version 2
    
  4. 下载 Docker Desktop for Windows

    访问 Docker 官网 下载安装程序

  5. 安装 Docker Desktop

    • 双击下载的 Docker Desktop Installer.exe
    • 按照向导完成安装
    • 安装完成后重启计算机
  6. 验证安装

    打开命令行工具(CMD 或 PowerShell):

    docker --version
    docker run hello-world
    

macOS 安装

系统要求
  • macOS 10.15 或更高版本
安装步骤
  1. 下载 Docker Desktop for Mac

    • Intel 芯片: 下载 Docker Desktop for Mac (Intel chip)
    • Apple 芯片: 下载 Docker Desktop for Mac (Apple chip)
  2. 安装

    • 打开下载的 .dmg 文件
    • 将 Docker 图标拖到 Applications 文件夹
    • 从 Applications 文件夹启动 Docker
  3. 验证安装

    docker --version
    docker run hello-world
    

Linux 安装 (以 Ubuntu 为例)

卸载旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc
安装步骤
  1. 更新软件包索引

    sudo apt-get update
    
  2. 安装依赖包

    sudo apt-get install \
        ca-certificates \
        curl \
        gnupg \
        lsb-release
    
  3. 添加 Docker 官方 GPG 密钥

    sudo mkdir -p /etc/apt/keyrings
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    
  4. 设置 Docker 仓库

    echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
      $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    
  5. 安装 Docker Engine

    sudo apt-get update
    sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    
  6. 启动 Docker 服务

    sudo systemctl start docker
    sudo systemctl enable docker
    
  7. 将当前用户添加到 docker 组(避免每次使用 sudo)

    sudo usermod -aG docker $USER
    newgrp docker
    
  8. 验证安装

    docker --version
    docker run hello-world
    

Docker 核心概念

镜像 (Image)

镜像是一个只读的模板,包含了运行应用所需的代码、运行时、库、环境变量和配置文件。可以把镜像理解为一个"类",它定义了容器应该是什么样子。

特点:

  • 分层存储
  • 只读
  • 可以被共享和重用

容器 (Container)

容器是镜像的运行实例。如果镜像是"类",那么容器就是"对象"。容器可以被创建、启动、停止、删除和暂停。

特点:

  • 可读写
  • 相互隔离
  • 可以连接网络
  • 可以挂载存储

仓库 (Repository)

仓库是集中存放镜像的地方。Docker Hub 是最大的公共仓库,用户也可以搭建私有仓库。

常见仓库:

  • Docker Hub: https://hub.docker.com/
  • 阿里云镜像仓库
  • 腾讯云镜像仓库
  • Harbor(企业私有仓库)

数据卷 (Volume)

数据卷是容器持久化数据的机制,数据卷的生命周期独立于容器。

网络 (Network)

Docker 提供了多种网络模式,使容器之间以及容器与外部网络能够通信。


Docker 基础使用

镜像操作

搜索镜像
# 从 Docker Hub 搜索镜像
docker search nginx

# 搜索并限制结果数量
docker search --limit 5 nginx
拉取镜像
# 拉取最新版本
docker pull nginx

# 拉取指定版本
docker pull nginx:1.21.0

# 拉取指定架构的镜像
docker pull --platform linux/amd64 nginx
查看本地镜像
# 列出所有镜像
docker images

# 或使用
docker image ls

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

# 查看镜像历史
docker history nginx
删除镜像
# 删除单个镜像
docker rmi nginx:1.21.0

# 删除多个镜像
docker rmi nginx:1.21.0 nginx:1.20.0

# 强制删除
docker rmi -f nginx

# 删除所有未使用的镜像
docker image prune

# 删除所有镜像
docker rmi $(docker images -q)
导出和导入镜像
# 导出镜像为 tar 文件
docker save -o nginx.tar nginx:latest

# 从 tar 文件导入镜像
docker load -i nginx.tar

容器操作

创建并运行容器
# 基础运行
docker run nginx

# 后台运行
docker run -d nginx

# 指定容器名称
docker run -d --name my-nginx nginx

# 端口映射 (主机端口:容器端口)
docker run -d -p 8080:80 --name my-nginx nginx

# 环境变量
docker run -d -e "ENV=production" nginx

# 挂载数据卷
docker run -d -v /host/path:/container/path nginx

# 完整示例
docker run -d \
  --name my-nginx \
  -p 8080:80 \
  -v /usr/share/nginx/html:/usr/share/nginx/html \
  -e "NGINX_HOST=example.com" \
  --restart=always \
  nginx:latest

常用参数说明:

  • -d: 后台运行
  • -p: 端口映射
  • -v: 挂载数据卷
  • -e: 设置环境变量
  • --name: 指定容器名称
  • --rm: 容器停止后自动删除
  • -it: 交互式运行(分配伪终端)
  • --restart: 重启策略 (no/always/on-failure/unless-stopped)
查看容器
# 查看运行中的容器
docker ps

# 查看所有容器(包括停止的)
docker ps -a

# 查看容器详细信息
docker inspect my-nginx

# 查看容器资源使用情况
docker stats my-nginx

# 查看容器进程
docker top my-nginx
容器日志
# 查看容器日志
docker logs my-nginx

# 实时查看日志
docker logs -f my-nginx

# 查看最后 100 行日志
docker logs --tail 100 my-nginx

# 查看带时间戳的日志
docker logs -t my-nginx
进入容器
# 使用 exec 进入容器(推荐)
docker exec -it my-nginx bash

# 或使用 sh(如果容器没有 bash)
docker exec -it my-nginx sh

# 以 root 用户进入
docker exec -it -u root my-nginx bash

# 在容器中执行命令
docker exec my-nginx ls /usr/share/nginx/html
容器控制
# 启动容器
docker start my-nginx

# 停止容器
docker stop my-nginx

# 重启容器
docker restart my-nginx

# 暂停容器
docker pause my-nginx

# 恢复容器
docker unpause my-nginx

# 杀死容器
docker kill my-nginx
删除容器
# 删除已停止的容器
docker rm my-nginx

# 强制删除运行中的容器
docker rm -f my-nginx

# 删除所有停止的容器
docker container prune

# 删除所有容器
docker rm -f $(docker ps -aq)
容器和镜像互转
# 将容器提交为新镜像
docker commit my-nginx my-custom-nginx:v1

# 导出容器为 tar 文件
docker export my-nginx > nginx-container.tar

# 从 tar 文件导入为镜像
cat nginx-container.tar | docker import - my-nginx:imported

数据卷管理

创建数据卷
# 创建命名数据卷
docker volume create my-volume

# 查看所有数据卷
docker volume ls

# 查看数据卷详情
docker volume inspect my-volume
使用数据卷
# 使用命名数据卷
docker run -d -v my-volume:/usr/share/nginx/html nginx

# 使用主机路径(绑定挂载)
docker run -d -v /host/path:/container/path nginx

# 只读挂载
docker run -d -v my-volume:/usr/share/nginx/html:ro nginx

# 使用 --mount 语法(更明确)
docker run -d \
  --mount type=volume,source=my-volume,target=/usr/share/nginx/html \
  nginx
删除数据卷
# 删除指定数据卷
docker volume rm my-volume

# 删除所有未使用的数据卷
docker volume prune

网络管理

查看网络
# 列出所有网络
docker network ls

# 查看网络详情
docker network inspect bridge
创建网络
# 创建桥接网络
docker network create my-network

# 创建自定义子网的网络
docker network create --subnet=172.18.0.0/16 my-custom-network

# 创建指定驱动的网络
docker network create -d bridge my-bridge-network
使用网络
# 容器连接到网络
docker run -d --name web --network my-network nginx

# 将运行中的容器连接到网络
docker network connect my-network my-nginx

# 断开容器与网络的连接
docker network disconnect my-network my-nginx
删除网络
# 删除指定网络
docker network rm my-network

# 删除所有未使用的网络
docker network prune

Dockerfile 编写

什么是 Dockerfile

Dockerfile 是一个文本文件,包含了一系列指令,用于自动化构建 Docker 镜像。

Dockerfile 基本结构

# 基础镜像
FROM ubuntu:20.04

# 维护者信息
LABEL maintainer="yourname@example.com"

# 设置环境变量
ENV APP_HOME=/app \
    PORT=8080

# 设置工作目录
WORKDIR $APP_HOME

# 复制文件
COPY package.json .
COPY src/ ./src/

# 执行命令
RUN apt-get update && \
    apt-get install -y nodejs npm && \
    npm install && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# 暴露端口
EXPOSE $PORT

# 数据卷
VOLUME ["/app/data"]

# 启动命令
CMD ["node", "src/app.js"]

常用指令详解

FROM - 指定基础镜像
# 使用官方镜像
FROM node:16

# 使用特定版本
FROM python:3.9.7-slim

# 使用 scratch(空白镜像,最小化)
FROM scratch

# 多阶段构建
FROM node:16 AS builder
LABEL - 添加元数据
LABEL version="1.0"
LABEL description="This is a web application"
LABEL maintainer="developer@example.com"
ENV - 设置环境变量
# 单个环境变量
ENV NODE_ENV=production

# 多个环境变量
ENV APP_HOME=/app \
    PORT=3000 \
    USER=appuser
WORKDIR - 设置工作目录
# 设置工作目录(如果不存在会自动创建)
WORKDIR /app

# 可以使用环境变量
ENV APP_DIR=/application
WORKDIR $APP_DIR
COPY 和 ADD - 复制文件
# COPY 基本用法
COPY package.json /app/
COPY src/ /app/src/

# 复制并重命名
COPY config.json /app/configuration.json

# ADD 可以自动解压缩
ADD archive.tar.gz /app/

# ADD 可以从 URL 下载
ADD https://example.com/file.txt /app/

# 推荐使用 COPY(更透明)
RUN - 执行命令
# Shell 格式
RUN apt-get update

# Exec 格式
RUN ["/bin/bash", "-c", "echo hello"]

# 合并命令减少层数
RUN apt-get update && \
    apt-get install -y \
        python3 \
        python3-pip && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
EXPOSE - 暴露端口
# 暴露单个端口
EXPOSE 80

# 暴露多个端口
EXPOSE 80 443

# 指定协议
EXPOSE 53/udp
EXPOSE 53/tcp
VOLUME - 创建挂载点
# 单个挂载点
VOLUME /data

# 多个挂载点
VOLUME ["/var/log", "/var/db"]
CMD - 容器启动命令
# Exec 格式(推荐)
CMD ["nginx", "-g", "daemon off;"]

# Shell 格式
CMD npm start

# 提供默认参数给 ENTRYPOINT
CMD ["--help"]
ENTRYPOINT - 容器入口点
# Exec 格式
ENTRYPOINT ["python", "app.py"]

# 与 CMD 结合使用
ENTRYPOINT ["python", "app.py"]
CMD ["--port", "8080"]

# 可以通过 docker run 覆盖 CMD 参数
# docker run myimage --port 9000
ARG - 构建参数
# 定义构建参数
ARG VERSION=latest
ARG BUILD_DATE

# 使用构建参数
FROM ubuntu:${VERSION}
LABEL build_date=${BUILD_DATE}

# 构建时传递参数
# docker build --build-arg VERSION=20.04 --build-arg BUILD_DATE=$(date) .
USER - 指定运行用户
# 创建用户并切换
RUN useradd -m -u 1000 appuser
USER appuser

# 切换回 root
USER root
HEALTHCHECK - 健康检查
# 基本健康检查
HEALTHCHECK CMD curl -f http://localhost/ || exit 1

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

实战示例

Node.js 应用 Dockerfile
# 多阶段构建 - 构建阶段
FROM node:16-alpine AS builder

WORKDIR /app

# 复制依赖文件
COPY package*.json ./

# 安装依赖
RUN npm ci --only=production

# 复制源代码
COPY . .

# 构建应用
RUN npm run build

# 多阶段构建 - 运行阶段
FROM node:16-alpine

# 设置环境变量
ENV NODE_ENV=production \
    PORT=3000

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

WORKDIR /app

# 从构建阶段复制文件
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
COPY --from=builder --chown=nodejs:nodejs /app/package.json ./

# 切换到非 root 用户
USER nodejs

# 暴露端口
EXPOSE $PORT

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD node -e "require('http').get('http://localhost:$PORT/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"

# 启动命令
CMD ["node", "dist/main.js"]
Python Flask 应用 Dockerfile
FROM python:3.9-slim

# 设置环境变量
ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    APP_HOME=/app

WORKDIR $APP_HOME

# 安装系统依赖
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        gcc \
        postgresql-client && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# 复制依赖文件
COPY requirements.txt .

# 安装 Python 依赖
RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY . .

# 创建非 root 用户
RUN useradd -m -u 1000 appuser && \
    chown -R appuser:appuser $APP_HOME

USER appuser

EXPOSE 5000

HEALTHCHECK --interval=30s --timeout=3s \
  CMD python -c "import requests; requests.get('http://localhost:5000/health')"

CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "4", "app:app"]
Nginx 静态网站 Dockerfile
FROM nginx:alpine

# 删除默认配置
RUN rm /etc/nginx/conf.d/default.conf

# 复制自定义配置
COPY nginx.conf /etc/nginx/conf.d/

# 复制静态文件
COPY dist/ /usr/share/nginx/html/

# 设置权限
RUN chown -R nginx:nginx /usr/share/nginx/html && \
    chmod -R 755 /usr/share/nginx/html

EXPOSE 80

HEALTHCHECK --interval=30s --timeout=3s \
  CMD wget --quiet --tries=1 --spider http://localhost/ || exit 1

CMD ["nginx", "-g", "daemon off;"]

构建镜像

# 基本构建
docker build -t myapp:latest .

# 指定 Dockerfile
docker build -f Dockerfile.dev -t myapp:dev .

# 传递构建参数
docker build --build-arg VERSION=1.0 -t myapp:1.0 .

# 不使用缓存
docker build --no-cache -t myapp:latest .

# 指定平台
docker build --platform linux/amd64 -t myapp:latest .

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

Dockerfile 最佳实践

  1. 使用 .dockerignore 文件

    node_modules
    npm-debug.log
    .git
    .env
    *.md
    .vscode
    
  2. 最小化层数 - 合并 RUN 命令

    # 不好的做法
    RUN apt-get update
    RUN apt-get install -y python
    RUN apt-get clean
    
    # 好的做法
    RUN apt-get update && \
        apt-get install -y python && \
        apt-get clean
    
  3. 使用多阶段构建 - 减小最终镜像大小

  4. 利用构建缓存 - 将不常改变的指令放在前面

  5. 使用非 root 用户 - 提高安全性

  6. 明确指定版本 - 不要使用 latest 标签


Docker Compose 简介

什么是 Docker Compose

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。使用 YAML 文件来配置应用的服务,然后使用一个命令就可以创建并启动所有服务。

Docker Compose 的优势

  • 单一配置文件: 所有服务配置集中管理
  • 一键部署: 通过一个命令启动所有服务
  • 服务编排: 自动管理服务间的依赖关系
  • 网络隔离: 自动创建独立的网络环境
  • 环境管理: 支持多环境配置
  • 开发效率: 简化开发环境的搭建

Docker Compose 安装

Windows 和 macOS

Docker Desktop 已经包含了 Docker Compose,无需单独安装。

验证安装:

docker compose version

Linux 安装

方法一: 使用 Docker 插件(推荐)

如果你安装的是最新版 Docker Engine,Compose 已经作为插件包含在内。

验证:

docker compose version
方法二: 独立安装 Compose V2
# 下载 Compose 二进制文件
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose

# 添加执行权限
chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose

# 验证安装
docker compose version
方法三: 使用 pip 安装(旧版本)
sudo pip install docker-compose

# 验证
docker-compose --version

Docker Compose 使用

docker-compose.yml 基本结构

version: '3.8'  # Compose 文件版本

services:       # 定义服务
  web:
    image: nginx:latest
    ports:
      - "8080:80"

  db:
    image: postgres:13
    environment:
      POSTGRES_PASSWORD: example

networks:       # 定义网络(可选)
  default:
    driver: bridge

volumes:        # 定义数据卷(可选)
  db-data:
    driver: local

服务配置详解

image - 指定镜像
services:
  web:
    image: nginx:latest

  app:
    image: myregistry.com/myapp:1.0
build - 构建镜像
services:
  web:
    build: .  # 使用当前目录的 Dockerfile

  app:
    build:
      context: ./app          # 构建上下文
      dockerfile: Dockerfile.dev  # 指定 Dockerfile
      args:                   # 构建参数
        VERSION: "1.0"
        BUILD_ENV: production
      target: production      # 多阶段构建的目标阶段
ports - 端口映射
services:
  web:
    ports:
      - "8080:80"           # HOST:CONTAINER
      - "443:443"
      - "127.0.0.1:3000:3000"  # 绑定到特定 IP
      - "9000-9002:9000-9002"  # 端口范围
environment - 环境变量
services:
  db:
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: mydb

    # 或使用数组格式
    environment:
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=secret
env_file - 环境变量文件
services:
  web:
    env_file:
      - .env
      - .env.local

.env 文件内容:

DATABASE_URL=postgresql://localhost/mydb
API_KEY=your-api-key
DEBUG=true
volumes - 数据卷
services:
  web:
    volumes:
      # 命名卷
      - data-volume:/var/lib/mysql

      # 绑定挂载
      - ./src:/app/src
      - /host/path:/container/path

      # 只读挂载
      - ./config:/etc/config:ro

      # 匿名卷
      - /app/node_modules

volumes:
  data-volume:  # 定义命名卷
networks - 网络配置
services:
  web:
    networks:
      - frontend
      - backend

  db:
    networks:
      - backend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # 内部网络,不对外
depends_on - 依赖关系
services:
  web:
    depends_on:
      - db
      - redis

  db:
    image: postgres

  redis:
    image: redis

高级依赖(等待服务健康):

services:
  web:
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
restart - 重启策略
services:
  web:
    restart: always          # 总是重启
    # restart: unless-stopped  # 除非手动停止
    # restart: on-failure      # 失败时重启
    # restart: no              # 不重启(默认)
command - 覆盖默认命令
services:
  web:
    image: nginx
    command: nginx -g 'daemon off;'

  app:
    image: python:3.9
    command: ["python", "app.py", "--port", "8000"]
entrypoint - 覆盖入口点
services:
  web:
    entrypoint: /app/entrypoint.sh

  app:
    entrypoint: ["python", "-u", "app.py"]
container_name - 容器名称
services:
  web:
    container_name: my-web-container
healthcheck - 健康检查
services:
  web:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
labels - 标签
services:
  web:
    labels:
      com.example.description: "Web application"
      com.example.department: "IT"
      com.example.version: "1.0"
logging - 日志配置
services:
  web:
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

Docker Compose 命令

启动服务
# 启动所有服务
docker compose up

# 后台启动
docker compose up -d

# 启动特定服务
docker compose up web db

# 重新构建并启动
docker compose up --build

# 强制重新创建容器
docker compose up --force-recreate

# 不启动依赖服务
docker compose up --no-deps web
停止服务
# 停止所有服务
docker compose stop

# 停止特定服务
docker compose stop web

# 停止并删除容器、网络
docker compose down

# 停止并删除容器、网络、卷
docker compose down -v

# 停止并删除容器、网络、镜像
docker compose down --rmi all
查看服务
# 查看运行中的服务
docker compose ps

# 查看所有服务(包括停止的)
docker compose ps -a

# 查看服务日志
docker compose logs

# 实时查看日志
docker compose logs -f

# 查看特定服务日志
docker compose logs web

# 查看最后 100 行日志
docker compose logs --tail=100
执行命令
# 在运行的容器中执行命令
docker compose exec web bash

# 在新容器中运行一次性命令
docker compose run web python manage.py migrate

# 不启动依赖服务
docker compose run --no-deps web npm test
服务管理
# 启动已存在的容器
docker compose start

# 重启服务
docker compose restart

# 暂停服务
docker compose pause

# 恢复服务
docker compose unpause

# 查看服务进程
docker compose top
构建和推送
# 构建服务镜像
docker compose build

# 构建时不使用缓存
docker compose build --no-cache

# 并行构建
docker compose build --parallel

# 推送镜像到仓库
docker compose push
配置验证
# 验证 compose 文件
docker compose config

# 查看最终配置(包含变量替换)
docker compose config --services

# 查看服务列表
docker compose config --volumes

实战案例

案例 1: WordPress + MySQL

创建 docker-compose.yml:

version: '3.8'

services:
  db:
    image: mysql:8.0
    container_name: wordpress-db
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wpuser
      MYSQL_PASSWORD: wppassword
    volumes:
      - db-data:/var/lib/mysql
    networks:
      - wordpress-network

  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    container_name: wordpress-app
    restart: always
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wpuser
      WORDPRESS_DB_PASSWORD: wppassword
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - wordpress-data:/var/www/html
    networks:
      - wordpress-network

volumes:
  db-data:
  wordpress-data:

networks:
  wordpress-network:
    driver: bridge

启动:

docker compose up -d

访问: http://localhost:8080

案例 2: NGINX + Flask + PostgreSQL + Redis

项目结构:

.
├── docker-compose.yml
├── .env
├── nginx/
│   ├── Dockerfile
│   └── nginx.conf
└── app/
    ├── Dockerfile
    ├── requirements.txt
    └── app.py

docker-compose.yml:

version: '3.8'

services:
  nginx:
    build: ./nginx
    container_name: nginx-proxy
    ports:
      - "80:80"
    depends_on:
      - web
    networks:
      - frontend
    restart: unless-stopped

  web:
    build: ./app
    container_name: flask-app
    command: gunicorn -w 4 -b 0.0.0.0:5000 app:app
    environment:
      - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
      - REDIS_URL=redis://redis:6379/0
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - frontend
      - backend
    restart: unless-stopped

  db:
    image: postgres:13-alpine
    container_name: postgres-db
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    container_name: redis-cache
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data
    networks:
      - backend
    restart: unless-stopped

volumes:
  postgres-data:
  redis-data:

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true

.env 文件:

POSTGRES_USER=appuser
POSTGRES_PASSWORD=apppassword
POSTGRES_DB=appdb

app/Dockerfile:

FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 5000

CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "app:app"]

app/requirements.txt:

Flask==2.3.0
gunicorn==20.1.0
psycopg2-binary==2.9.6
redis==4.5.5

app/app.py:

from flask import Flask, jsonify
import os
import redis
import psycopg2

app = Flask(__name__)

# Redis 连接
redis_client = redis.from_url(os.getenv('REDIS_URL', 'redis://localhost:6379/0'))

@app.route('/')
def hello():
    return jsonify({"message": "Hello from Flask!"})

@app.route('/health')
def health():
    return jsonify({"status": "healthy"}), 200

@app.route('/redis-test')
def redis_test():
    redis_client.incr('hits')
    hits = redis_client.get('hits').decode('utf-8')
    return jsonify({"hits": hits})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

nginx/Dockerfile:

FROM nginx:alpine

RUN rm /etc/nginx/conf.d/default.conf

COPY nginx.conf /etc/nginx/conf.d/

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

nginx/nginx.conf:

upstream flask_app {
    server web:5000;
}

server {
    listen 80;
    server_name localhost;

    location / {
        proxy_pass http://flask_app;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

启动应用:

docker compose up -d --build

案例 3: 微服务架构监控栈

使用 Prometheus + Grafana + Node Exporter

docker-compose.yml:

version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus
    networks:
      - monitoring
    restart: unless-stopped

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
      - GF_USERS_ALLOW_SIGN_UP=false
    volumes:
      - grafana-data:/var/lib/grafana
    depends_on:
      - prometheus
    networks:
      - monitoring
    restart: unless-stopped

  node-exporter:
    image: prom/node-exporter:latest
    container_name: node-exporter
    ports:
      - "9100:9100"
    networks:
      - monitoring
    restart: unless-stopped

volumes:
  prometheus-data:
  grafana-data:

networks:
  monitoring:
    driver: bridge

prometheus/prometheus.yml:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node-exporter'
    static_configs:
      - targets: ['node-exporter:9100']

案例 4: 开发环境配置

使用不同的 compose 文件管理多环境:

docker-compose.yml (基础配置):

version: '3.8'

services:
  web:
    build: .
    environment:
      - NODE_ENV=production
    networks:
      - app-network

networks:
  app-network:

docker-compose.dev.yml (开发环境覆盖):

version: '3.8'

services:
  web:
    build:
      target: development
    environment:
      - NODE_ENV=development
      - DEBUG=true
    volumes:
      - ./src:/app/src
    ports:
      - "3000:3000"
    command: npm run dev

docker-compose.prod.yml (生产环境覆盖):

version: '3.8'

services:
  web:
    build:
      target: production
    environment:
      - NODE_ENV=production
    restart: always
    command: npm start

使用:

# 开发环境
docker compose -f docker-compose.yml -f docker-compose.dev.yml up

# 生产环境
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

最佳实践

1. 镜像优化

使用轻量级基础镜像

# 优先使用 Alpine 版本
FROM node:16-alpine
FROM python:3.9-slim

多阶段构建

# 构建阶段
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# 运行阶段
FROM node:16-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/main.js"]

最小化层数

# 合并 RUN 命令
RUN apt-get update && \
    apt-get install -y package1 package2 && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

2. 安全实践

使用非 root 用户

RUN addgroup -g 1001 -S appgroup && \
    adduser -S appuser -u 1001 -G appgroup
USER appuser

不在镜像中存储敏感信息

# 使用环境变量
services:
  app:
    env_file:
      - .env.local

扫描镜像漏洞

# 使用 Docker Scan
docker scan myimage:latest

# 使用 Trivy
trivy image myimage:latest

3. 性能优化

利用构建缓存

# 先复制依赖文件
COPY package.json package-lock.json ./
RUN npm install

# 再复制源代码
COPY . .

使用 .dockerignore

node_modules
.git
.env
*.md
test/

并行构建

docker compose build --parallel

4. 开发效率

使用卷进行热重载

services:
  web:
    volumes:
      - ./src:/app/src
    command: npm run dev

使用命名卷持久化数据

volumes:
  db-data:
    driver: local

5. 日志管理

限制日志大小

services:
  web:
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

6. 健康检查

配置健康检查

services:
  web:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

7. 资源限制

限制容器资源使用

services:
  web:
    deploy:
      resources:
        limits:
          cpus: '0.50'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M

常见问题

1. 容器无法启动

检查日志

docker logs <container-id>
docker compose logs

检查容器状态

docker ps -a
docker inspect <container-id>

2. 端口已被占用

查找占用端口的进程

# Windows
netstat -ano | findstr :8080

# Linux/Mac
lsof -i :8080

更改映射端口

ports:
  - "8081:80"  # 使用不同的主机端口

3. 数据持久化问题

使用命名卷

volumes:
  my-data:/var/lib/data

volumes:
  my-data:

查看卷内容

docker volume inspect my-data
docker run --rm -v my-data:/data alpine ls /data

4. 网络连接问题

检查容器网络

docker network ls
docker network inspect <network-name>

容器间通信

# 使用服务名作为主机名
services:
  web:
    environment:
      - DATABASE_URL=postgresql://db:5432/mydb
  db:
    image: postgres

5. 镜像拉取缓慢

配置镜像加速器

编辑 /etc/docker/daemon.json:

{
  "registry-mirrors": [
    "https://mirror.ccs.tencentyun.com",
    "https://docker.mirrors.ustc.edu.cn"
  ]
}

重启 Docker:

sudo systemctl restart docker

6. 容器时间不同步

设置时区

services:
  web:
    environment:
      - TZ=Asia/Shanghai
    volumes:
      - /etc/localtime:/etc/localtime:ro

7. 权限问题

设置文件权限

RUN chown -R appuser:appuser /app
USER appuser

挂载卷权限

volumes:
  - ./data:/app/data:rw  # 读写权限

8. 清理无用资源

清理停止的容器

docker container prune

清理无用镜像

docker image prune
docker image prune -a  # 删除所有未使用的镜像

清理无用卷

docker volume prune

一键清理

docker system prune
docker system prune -a --volumes  # 全部清理

总结

Docker 和 Docker Compose 是现代应用开发和部署的重要工具。通过本文,你应该掌握了:

  1. Docker 基础

    • 安装和配置
    • 镜像和容器管理
    • 数据卷和网络配置
    • Dockerfile 编写
  2. Docker Compose

    • 安装和配置
    • docker-compose.yml 编写
    • 多容器应用编排
    • 多环境管理
  3. 实战应用

    • Web 应用部署
    • 微服务架构
    • 开发环境配置
  4. 最佳实践

    • 镜像优化
    • 安全加固
    • 性能调优

继续实践和探索,你将能够更熟练地使用 Docker 和 Docker Compose 来简化开发、测试和部署流程。


参考资源


最后更新时间: 2025-11-04

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值