1. Docker基础概念与架构解析
容器技术已经成为现代云计算和DevOps实践中不可或缺的一部分。Docker作为容器技术的代表,彻底改变了我们构建、分发和运行应用程序的方式。与传统的虚拟机相比,Docker容器更加轻量级,启动速度更快,资源利用率更高。
1.1 Docker核心组件
Docker采用客户端-服务器(C/S)架构设计,主要包含以下核心组件:
-
Docker守护进程(Daemon):运行在主机操作系统上的后台服务,负责管理容器生命周期、镜像存储和网络配置等核心功能。它监听来自客户端的API请求并执行相应操作。
-
Docker客户端(CLI):用户与Docker交互的主要界面。当我们执行
docker run等命令时,客户端会通过REST API与守护进程通信。有趣的是,客户端和守护进程可以运行在同一台机器上,也可以远程连接。 -
Docker镜像:容器的只读模板,采用分层存储结构。每个镜像由多个只读层叠加组成,这种设计使得镜像可以高效共享和复用。例如,当你拉取一个基于Ubuntu的Nginx镜像时,Docker会复用本地已有的Ubuntu层,只下载新增的Nginx相关层。
-
Docker容器:镜像的运行实例,包含应用程序及其运行环境。容器在镜像的只读层之上添加一个可写层,使得容器运行时可以修改文件系统而不影响基础镜像。
-
Docker仓库(Registry):用于存储和分发镜像的集中化服务。Docker Hub是默认的公共仓库,企业也可以搭建私有仓库(如Harbor)来管理内部镜像。
1.2 Docker与虚拟机的本质区别
虽然Docker容器和虚拟机都提供了隔离的运行环境,但它们的实现机制有根本不同:
| 特性 | Docker容器 | 传统虚拟机 |
|---|---|---|
| 虚拟化级别 | 操作系统级 | 硬件级 |
| 启动时间 | 秒级 | 分钟级 |
| 性能损耗 | 接近原生 | 15-20% |
| 磁盘占用 | MB级 | GB级 |
| 隔离性 | 进程级 | 完全隔离 |
| 运行密度 | 单机可运行数百个 | 通常数十个 |
容器直接共享主机内核,通过命名空间(Namespace)实现资源隔离,通过控制组(Cgroups)限制资源使用。这种设计使得容器极其轻量,但也意味着所有容器必须与主机使用相同的内核版本。
提示:在生产环境中,建议使用
--cpus和--memory参数限制容器的CPU和内存使用,避免单个容器耗尽主机资源。
2. Docker安装与配置实战
2.1 在不同系统上的安装方法
CentOS/RHEL系统安装
对于CentOS/RHEL系统,推荐使用以下步骤安装Docker CE:
bash复制# 安装依赖工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加Docker官方仓库
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 替换为国内镜像源加速下载
sudo sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo
# 安装Docker CE
sudo yum install -y docker-ce docker-ce-cli containerd.io
# 启动并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker
Ubuntu系统安装
Ubuntu用户可以使用apt包管理器安装:
bash复制# 更新apt索引
sudo apt-get update
# 安装依赖包
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
# 添加Docker官方GPG密钥
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"
# 安装Docker CE
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
2.2 配置Docker守护进程
生产环境中,我们通常需要调整Docker守护进程的默认配置。编辑/etc/docker/daemon.json文件:
json复制{
"registry-mirrors": ["https://registry.docker-cn.com"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
},
"data-root": "/data/docker",
"exec-opts": ["native.cgroupdriver=systemd"],
"storage-driver": "overlay2"
}
配置说明:
registry-mirrors:配置国内镜像加速器log-driver:设置容器日志驱动和轮转策略data-root:修改Docker数据存储路径storage-driver:推荐使用overlay2存储驱动
修改配置后需要重启Docker服务:
bash复制sudo systemctl daemon-reload
sudo systemctl restart docker
2.3 验证安装
安装完成后,运行以下命令验证Docker是否正常工作:
bash复制# 检查版本信息
docker version
# 运行测试容器
docker run hello-world
# 查看系统信息
docker info
如果看到"Hello from Docker!"的欢迎信息,说明安装成功。
注意事项:生产环境中建议禁用Docker的IPv6支持,因为某些网络插件可能与IPv6存在兼容性问题。可以通过在
daemon.json中添加"ipv6": false来禁用。
3. Docker核心命令深度解析
3.1 容器生命周期管理
容器创建与运行
docker run是最常用的命令之一,其核心参数包括:
bash复制# 基本运行
docker run -d --name my_nginx nginx
# 端口映射
docker run -d -p 8080:80 --name web nginx
# 数据卷挂载
docker run -d -v /host/path:/container/path --name db mysql
# 环境变量设置
docker run -d -e MYSQL_ROOT_PASSWORD=123456 --name mysql mysql
# 资源限制
docker run -d --memory=1g --cpus=2 --name resource-limited-app myapp
常用参数说明:
-d:后台运行容器-p:端口映射(主机端口:容器端口)-v:数据卷挂载-e:设置环境变量--restart:设置容器重启策略(always, on-failure等)
容器状态管理
bash复制# 启动/停止/重启容器
docker start my_nginx
docker stop my_nginx
docker restart my_nginx
# 暂停/恢复容器
docker pause my_nginx
docker unpause my_nginx
# 删除容器
docker rm my_nginx
docker rm -f my_nginx # 强制删除运行中的容器
3.2 镜像管理命令
镜像获取与查找
bash复制# 从仓库拉取镜像
docker pull nginx:1.21
# 搜索镜像
docker search mysql
# 查看本地镜像
docker images
docker image ls # 新语法
镜像构建与推送
bash复制# 构建镜像(使用当前目录的Dockerfile)
docker build -t myapp:v1 .
# 标记镜像
docker tag myapp:v1 registry.example.com/myapp:v1
# 推送镜像到仓库
docker push registry.example.com/myapp:v1
# 导出/导入镜像
docker save -o myapp.tar myapp:v1
docker load -i myapp.tar
3.3 容器运维与调试
容器信息查看
bash复制# 查看运行中的容器
docker ps
docker ps -a # 查看所有容器(包括已停止的)
# 查看容器日志
docker logs my_nginx
docker logs -f my_nginx # 实时跟踪日志
# 查看容器资源使用情况
docker stats my_nginx
# 查看容器详细信息
docker inspect my_nginx
容器内执行命令
bash复制# 在运行中的容器内执行命令
docker exec -it my_nginx bash
# 不进入容器直接执行命令
docker exec my_nginx ls /var/log/nginx
-it参数组合非常重要:
-i:保持STDIN打开-t:分配伪终端- 通常一起使用以实现交互式操作
3.4 网络与存储管理
网络管理
bash复制# 列出网络
docker network ls
# 创建自定义网络
docker network create my_network
# 将容器连接到网络
docker network connect my_network my_nginx
# 查看网络详情
docker network inspect my_network
数据卷管理
bash复制# 创建数据卷
docker volume create my_volume
# 列出数据卷
docker volume ls
# 使用数据卷
docker run -d -v my_volume:/data --name db mysql
# 删除未使用的数据卷
docker volume prune
经验分享:生产环境中建议始终使用命名数据卷(
-v volume_name:/path)而非主机目录绑定挂载,这样可以获得更好的性能和可管理性。Docker会自动管理这些卷的生命周期,并在容器删除时保留数据(除非明确删除卷)。
4. Dockerfile最佳实践
4.1 Dockerfile指令详解
一个完整的Dockerfile通常包含以下指令:
dockerfile复制# 指定基础镜像
FROM ubuntu:20.04
# 设置元数据
LABEL maintainer="devops@example.com"
LABEL version="1.0"
# 设置工作目录
WORKDIR /app
# 复制文件到镜像
COPY . .
# 安装依赖
RUN apt-get update && \
apt-get install -y python3 python3-pip && \
pip install -r requirements.txt && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# 暴露端口
EXPOSE 8000
# 定义环境变量
ENV FLASK_APP=app.py
ENV FLASK_ENV=production
# 定义启动命令
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]
关键指令对比
| 指令 | 执行时机 | 典型用途 | 是否可被覆盖 |
|---|---|---|---|
| RUN | 构建时 | 安装软件包、编译代码 | 否 |
| CMD | 运行时 | 指定容器默认启动命令 | 是 |
| ENTRYPOINT | 运行时 | 指定容器主进程 | 是(需--entrypoint) |
4.2 多阶段构建
多阶段构建是优化Docker镜像大小的关键技术:
dockerfile复制# 第一阶段:构建环境
FROM golang:1.16 AS builder
WORKDIR /go/src/app
COPY . .
RUN go get -d -v ./...
RUN go install -v ./...
# 第二阶段:运行环境
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/bin/app .
CMD ["./app"]
这种模式将构建工具和运行时环境分离,最终镜像只包含必要的运行文件,可以显著减小镜像体积。
4.3 构建缓存优化
Docker使用分层构建机制,合理利用缓存可以大幅加速构建过程:
- 将不经常变化的指令放在前面:如安装系统依赖
- 合并相关RUN命令:减少层数并利用缓存
- 使用.dockerignore文件:排除不必要的文件
- 固定基础镜像版本:避免使用latest标签
示例优化:
dockerfile复制# 不佳的做法
RUN apt-get update
RUN apt-get install -y package1
RUN apt-get install -y package2
# 优化的做法
RUN apt-get update && \
apt-get install -y package1 package2 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
4.4 安全最佳实践
-
不使用root用户运行容器:
dockerfile复制RUN groupadd -r appuser && useradd -r -g appuser appuser USER appuser -
定期更新基础镜像:修复安全漏洞
-
扫描镜像漏洞:
bash复制
docker scan myimage -
最小化安装原则:只安装必要的软件包
-
使用可信的基础镜像:优先选择官方镜像
避坑指南:避免在Dockerfile中硬编码密码或密钥。应该使用环境变量或Docker secrets机制。构建时使用
--build-arg传入敏感数据,但要注意这些数据会保留在构建历史中。
5. Docker高级特性与生产实践
5.1 Docker Compose编排
Docker Compose允许通过YAML文件定义和管理多容器应用:
yaml复制version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
depends_on:
- app
app:
build: ./app
environment:
- DB_HOST=db
- DB_PORT=3306
deploy:
resources:
limits:
cpus: '0.50'
memory: 512M
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: example
volumes:
- db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 3s
retries: 3
volumes:
db_data:
常用命令:
bash复制docker-compose up -d # 启动服务
docker-compose down # 停止并删除服务
docker-compose logs -f # 查看日志
docker-compose ps # 查看服务状态
5.2 容器资源限制
生产环境中必须对容器资源进行限制:
bash复制# CPU限制
docker run -d --cpus=1.5 --name app myapp # 限制使用1.5个CPU核心
docker run -d --cpuset-cpus="0-3" --name app myapp # 绑定到特定CPU核心
# 内存限制
docker run -d -m 512m --memory-swap=1g --name app myapp # 限制内存512MB,交换空间1GB
# IO限制
docker run -d --device-read-bps=/dev/sda:1mb --name app myapp # 限制磁盘读取速度
5.3 容器日志管理
Docker支持多种日志驱动,生产环境推荐使用json-file或journald:
bash复制# 查看日志
docker logs --tail 100 -f my_nginx
# 日志驱动配置
docker run --log-driver=json-file \
--log-opt max-size=100m \
--log-opt max-file=3 \
--name my_nginx nginx
对于大规模部署,建议将日志集中收集到ELK或类似系统中。
5.4 容器监控方案
常用监控工具组合:
-
cAdvisor:容器资源监控
bash复制
docker run -d --name=cadvisor \ -v /:/rootfs:ro \ -v /var/run:/var/run:ro \ -v /sys:/sys:ro \ -v /var/lib/docker/:/var/lib/docker:ro \ -p 8080:8080 \ google/cadvisor:latest -
Prometheus + Grafana:指标收集与可视化
-
ELK Stack:日志收集与分析
5.5 容器安全加固
-
启用用户命名空间:
bash复制
dockerd --userns-remap=default -
设置只读文件系统:
bash复制
docker run --read-only --tmpfs /run --name secure-container alpine -
限制容器能力:
bash复制
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE --name secure-nginx nginx -
使用Seccomp和AppArmor:
bash复制
docker run --security-opt seccomp=/path/to/profile.json --name secure-app myapp
生产经验:对于关键业务容器,建议至少实施以下安全措施:(1) 非root用户运行 (2) 只读根文件系统 (3) 删除所有非必要能力 (4) 资源限制 (5) 定期漏洞扫描。
6. 常见问题排查与调试技巧
6.1 容器启动失败排查
当容器无法启动时,可以按照以下步骤排查:
-
查看容器日志:
bash复制
docker logs <container_id> -
检查退出代码:
bash复制docker inspect -f '{{.State.ExitCode}}' <container_id> -
交互式调试:
bash复制
docker run -it --entrypoint=/bin/sh myimage -
检查端口冲突:
bash复制
netstat -tulnp | grep <port>
6.2 网络连接问题
常见网络问题排查命令:
bash复制# 检查容器网络配置
docker inspect -f '{{json .NetworkSettings}}' <container_id>
# 测试容器间连通性
docker exec -it container1 ping container2
# 检查DNS解析
docker exec -it container1 nslookup example.com
# 查看iptables规则
iptables -L -n -v --line-numbers
6.3 存储卷问题
当遇到数据卷相关问题时:
-
检查卷挂载:
bash复制docker inspect -f '{{json .Mounts}}' <container_id> -
修复权限问题:
bash复制
docker run -v /host/path:/container/path:Z myimage -
备份数据卷:
bash复制docker run --rm -v db_data:/volume -v /backup:/backup alpine \ tar czf /backup/db_backup.tar.gz -C /volume ./
6.4 性能问题分析
容器性能问题排查工具:
-
docker stats:实时资源监控
bash复制docker stats --all --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" -
top/htop:查看进程资源占用
bash复制docker exec -it <container_id> top -
perf/strace:性能分析和系统调用跟踪
6.5 镜像构建问题
构建失败时的调试技巧:
-
分阶段调试:
bash复制
docker build --target builder -t myapp:builder . -
检查构建上下文:
bash复制
docker build --no-cache -t myapp . -
分析镜像层:
bash复制docker history myimage -
检查.dockerignore:确保没有忽略必要文件
调试心得:当遇到难以解释的容器行为时,尝试使用
--net=host、--pid=host或--privileged临时提升权限进行调试,但切记不要在生产环境使用这些参数。