Docker 和 Docker Compose 完全指南

目录
- Docker 简介
- Docker 安装
- Docker 核心概念
- Docker 基础使用
- Dockerfile 编写
- Docker Compose 简介
- Docker Compose 安装
- Docker Compose 使用
- 实战案例
- 最佳实践
- 常见问题
Docker 简介
什么是 Docker
Docker 是一个开源的容器化平台,它允许开发者将应用程序及其所有依赖项打包到一个轻量级、可移植的容器中。容器可以在任何支持 Docker 的系统上运行,确保应用在不同环境中的一致性。
Docker 的优势
- 环境一致性: 消除"在我的机器上可以运行"的问题
- 快速部署: 容器启动速度快,通常只需几秒钟
- 资源隔离: 每个容器相互独立,互不影响
- 轻量级: 相比虚拟机,容器共享主机内核,占用资源更少
- 版本控制: 镜像可以进行版本管理
- 可移植性: 一次构建,到处运行
Docker vs 虚拟机
| 特性 | Docker 容器 | 虚拟机 |
|---|---|---|
| 启动时间 | 秒级 | 分钟级 |
| 磁盘占用 | MB 级别 | GB 级别 |
| 性能 | 接近原生 | 有性能损耗 |
| 系统支持 | 每台主机支持数千个容器 | 每台主机支持几十个虚拟机 |
| 隔离性 | 进程级隔离 | 操作系统级隔离 |
Docker 安装
Windows 安装
系统要求
- Windows 10 64-bit: Pro, Enterprise, or Education (Build 19041 或更高)
- 启用 WSL 2 功能
- 启用虚拟化功能
安装步骤
-
启用 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 # 重启计算机 -
下载并安装 WSL 2 Linux 内核更新包
访问 Microsoft WSL 2 更新页面 下载并安装
-
设置 WSL 2 为默认版本
wsl --set-default-version 2 -
下载 Docker Desktop for Windows
访问 Docker 官网 下载安装程序
-
安装 Docker Desktop
- 双击下载的
Docker Desktop Installer.exe - 按照向导完成安装
- 安装完成后重启计算机
- 双击下载的
-
验证安装
打开命令行工具(CMD 或 PowerShell):
docker --version docker run hello-world
macOS 安装
系统要求
- macOS 10.15 或更高版本
安装步骤
-
下载 Docker Desktop for Mac
- Intel 芯片: 下载 Docker Desktop for Mac (Intel chip)
- Apple 芯片: 下载 Docker Desktop for Mac (Apple chip)
-
安装
- 打开下载的
.dmg文件 - 将 Docker 图标拖到 Applications 文件夹
- 从 Applications 文件夹启动 Docker
- 打开下载的
-
验证安装
docker --version docker run hello-world
Linux 安装 (以 Ubuntu 为例)
卸载旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc
安装步骤
-
更新软件包索引
sudo apt-get update -
安装依赖包
sudo apt-get install \ ca-certificates \ curl \ gnupg \ lsb-release -
添加 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 -
设置 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 -
安装 Docker Engine
sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -
启动 Docker 服务
sudo systemctl start docker sudo systemctl enable docker -
将当前用户添加到 docker 组(避免每次使用 sudo)
sudo usermod -aG docker $USER newgrp docker -
验证安装
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 最佳实践
-
使用 .dockerignore 文件
node_modules npm-debug.log .git .env *.md .vscode -
最小化层数 - 合并 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 -
使用多阶段构建 - 减小最终镜像大小
-
利用构建缓存 - 将不常改变的指令放在前面
-
使用非 root 用户 - 提高安全性
-
明确指定版本 - 不要使用
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 是现代应用开发和部署的重要工具。通过本文,你应该掌握了:
-
Docker 基础
- 安装和配置
- 镜像和容器管理
- 数据卷和网络配置
- Dockerfile 编写
-
Docker Compose
- 安装和配置
- docker-compose.yml 编写
- 多容器应用编排
- 多环境管理
-
实战应用
- Web 应用部署
- 微服务架构
- 开发环境配置
-
最佳实践
- 镜像优化
- 安全加固
- 性能调优
继续实践和探索,你将能够更熟练地使用 Docker 和 Docker Compose 来简化开发、测试和部署流程。
参考资源
最后更新时间: 2025-11-04
Docker与Compose实用指南
2万+

被折叠的 条评论
为什么被折叠?



