本文是一份全面的 Docker 技术指南,涵盖了从基础概念到高级实践的完整知识体系。文档系统性地介绍了 Docker 的核心技术、安装配置、日常操作、网络与存储管理、安全实践以及生产环境部署等关键内容。
主要特点:
适用读者:
Docker 是一个开源的应用容器引擎,基于 Go 语言开发。它允许开发者将应用及其依赖打包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器或 Windows 机器上。
docker history
查看镜像的构建历史和各层信息docker save
将镜像导出为tar归档文件,便于传输或备份docker load
从tar文件加载镜像到本地仓库# 查看镜像分层结构
docker history <image_name>
# 导出镜像为tar文件
docker save -o myimage.tar <image_name>
# 从tar文件加载镜像
docker load -i myimage.tar
实际案例:某电商平台使用容器处理黑色星期五流量高峰,可快速扩展至5000个容器实例。
docker run
启动一个本地registry容器作为私有仓库docker tag
为镜像打上私有仓库地址的标签docker push
将镜像推送到私有仓库注意:默认情况下私有仓库没有认证,生产环境需要配置HTTPS和认证
# 启动私有仓库
docker run -d -p 5000:5000 --name registry registry:2
# 推送镜像到私有仓库
docker tag myimage localhost:5000/myimage
docker push localhost:5000/myimage
Docker在不同Linux发行版上的安装命令:
sudo systemctl start docker
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
# CentOS/RHEL
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io
从 Docker 官网下载 Docker Desktop 安装包: https://www.docker.com/products/docker-desktop
镜像基本操作命令说明:
docker pull
从仓库下载镜像到本地docker images
列出本地已下载的镜像docker rmi
删除本地镜像,释放磁盘空间注意:删除镜像前需确保没有容器在使用该镜像
# 拉取镜像
docker pull ubuntu:20.04
# 列出本地镜像
docker images
# 删除镜像
docker rmi <image_id>
容器操作命令详解:
docker run
创建并启动容器--cpus
限制CPU核心数--memory
限制内存使用量-it
以交互模式运行docker ps
查看容器状态--format
自定义输出格式-a
显示所有容器-s
显示容器大小docker stop
优雅停止容器docker rm
删除容器-f
强制操作运行中的容器docker stats
实时查看资源使用docker exec
在容器内执行命令top/free/df
查看进程/内存/磁盘docker cp
容器与主机间文件传输docker logs
查看容器日志-f
跟踪日志输出-t
显示时间戳docker update
动态调整资源限制--restart
配置重启策略docker inspect
检查容器健康状态# 运行容器(带资源限制)
docker run -it --cpus=2 --memory=1g --name myapp ubuntu:20.04 /bin/bash
# 列出运行中的容器(自定义格式)
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Ports}}"
# 列出所有容器(包括大小信息)
docker ps -as
# 停止容器(优雅停止)
docker stop -t 30 <container_id> # 30秒超时
# 删除容器(强制删除运行中的容器)
docker rm -f <container_id>
# 容器资源使用统计
docker stats --no-stream
# 容器性能分析
docker exec <container> top
docker exec <container> free -m
docker exec <container> df -h
# 容器与主机文件互传
docker cp <container_id>:/path/to/file /host/path
docker cp /host/path <container_id>:/container/path
# 容器日志查看(带时间戳和跟踪)
docker logs -ft <container_id>
# 容器资源限制更新
docker update --cpus=2 --memory=2g <container_id>
# 容器重启策略配置
docker run --restart unless-stopped -d myapp
# 容器健康检查
docker inspect --format='{{json .State.Health}}' <container_id>
-v
挂载主机目录到容器-p
映射主机端口到容器# 启动开发容器(挂载代码目录)
docker run -it -v $(pwd):/app -p 3000:3000 node:14 bash
-v
使用命名卷持久化数据-e
设置环境变量-d
后台运行# 启动MySQL容器(持久化数据)
docker run -d --name mysql -v mysql_data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret -p 3306:3306 mysql:5.7
--rm
运行后自动删除容器# 使用curl容器测试API
docker run --rm curlimages/curl https://api.example.com
# 运行一次性任务容器
docker run --rm python:3 python -c "print('Hello World')"
--network=host
使用主机网络# 使用网络工具容器诊断
docker run --network=host --rm nicolaka/netshoot \
ping google.com
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y python3
COPY . /app
WORKDIR /app
CMD ["python3", "app.py"]
# 第一阶段:构建环境
FROM golang:1.16 AS builder
WORKDIR /src
COPY . .
RUN go build -o /app/myapp .
# 第二阶段:运行环境
FROM alpine:3.13
WORKDIR /app
COPY --from=builder /app/myapp .
COPY --from=builder /src/config.yaml .
RUN chmod +x myapp
USER nobody
CMD ["./myapp"]
ARG APP_VERSION=1.0.0
ENV APP_VERSION=${APP_VERSION}
# 构建时传递参数
# docker build --build-arg APP_VERSION=2.0.0 -t myapp .
# 使用非root用户
RUN groupadd -r appuser && useradd -r -g appuser appuser
USER appuser
# 最小化权限
RUN chmod -R 755 /app && \
chown -R appuser:appuser /app
# 移除不必要的工具
RUN apt-get purge -y curl && \
apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/*
# 合理利用缓存层
COPY package.json .
RUN npm install
COPY . .
# 合并RUN命令
RUN apt-get update && \
apt-get install -y \
python3 \
python3-pip && \
pip install --no-cache-dir -r requirements.txt && \
rm -rf /var/lib/apt/lists/*
# 使用.dockerignore
# 示例内容:
.git
node_modules
*.log
*.md
# 第一阶段:依赖安装
FROM node:14 as dependencies
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# 第二阶段:构建应用
FROM node:14 as builder
WORKDIR /app
COPY . .
COPY --from=dependencies /app/node_modules ./node_modules
RUN npm run build
# 第三阶段:生产镜像
FROM node:14-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
EXPOSE 3000
CMD ["node", "dist/main.js"]
# 查看构建过程
docker history <image>
# 调试构建失败
docker run -it <failed_image_id> sh
# 分析镜像大小
docker image ls --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
容器网络管理命令说明:
bridge
:默认NAT模式,适合单机容器通信host
:直接使用主机网络,性能最佳none
:无网络连接,安全隔离overlay
:多主机网络,适合集群macvlan
:MAC直通,直接暴露到物理网络docker network create
创建自定义网络docker network connect
连接容器到网络docker network inspect
查看网络详情docker network prune
清理未使用网络最佳实践:
网络模式 | 特点 | 适用场景 |
---|---|---|
bridge | 默认模式,NAT转发 | 单机容器通信 |
host | 直接使用主机网络栈 | 高性能需求 |
none | 无网络连接 | 安全隔离场景 |
overlay | 多主机网络 | Swarm/K8s集群 |
macvlan | MAC地址直通 | 需要直接暴露到物理网络 |
# 创建带子网和网关的网络
docker network create \
--driver=bridge \
--subnet=172.28.0.0/16 \
--gateway=172.28.0.1 \
--ip-range=172.28.5.0/24 \
my-network
# 指定静态IP运行容器
docker run --network=my-network --ip=172.28.5.10 -d nginx
# 连接多个网络
docker network connect other-network my-container
# 初始化Swarm集群
docker swarm init
# 创建Overlay网络
docker network create --driver=overlay my-overlay
# 跨节点服务部署
docker service create --network=my-overlay --name web -p 80:80 nginx
# 创建Macvlan网络
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 \
my-macvlan
# 查看网络吞吐量
docker run --rm --net=host nicolaka/netshoot \
iperf3 -s # 服务端
docker run --rm --net=host nicolaka/netshoot \
iperf3 -c host-ip # 客户端
# 网络QoS限制
docker run --network=my-network \
--blkio-weight=300 \
-d nginx
# 检查容器网络配置
docker exec -it my-container ip addr
# 网络连通性测试
docker run --rm --net=container:my-container \
nicolaka/netshoot ping google.com
# 抓包分析
docker run --rm --net=container:my-container \
nicolaka/netshoot tcpdump -i eth0 -w capture.pcap
# 为每个服务创建独立网络
docker network create product-network
docker network create order-network
# 通过网关容器实现网络隔离
docker run -d --name gateway --network=product-network nginx
docker network connect order-network gateway
# 为每个构建创建临时网络
docker network create build-${BUILD_ID}
docker run --network=build-${BUILD_ID} -d test-db
docker run --network=build-${BUILD_ID} test-runner
数据管理命令说明:
docker volume create
创建持久化数据卷docker volume inspect
查看卷详情docker volume prune
清理未使用的卷docker run -v
挂载数据卷到容器最佳实践:
# 创建带驱动选项的数据卷
docker volume create \
--driver local \
--opt type=nfs \
--opt device=:/nfs/share \
--opt o=addr=10.0.0.1,rw \
nfs-volume
# 查看数据卷详情
docker volume inspect my-vol
# 清理未使用的数据卷
docker volume prune
# 数据卷备份
docker run --rm -v my-vol:/data -v $(pwd):/backup \
ubuntu tar cvf /backup/backup.tar /data
docker run -d \
--mount 'type=volume,src=nfs-vol,dst=/app,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/nfs/share,"volume-opt=o=addr=10.0.0.1,rw"' \
nginx
docker plugin install --alias ceph \
--grant-all-permissions \
ceph/plugin:latest
docker volume create --driver ceph \
--name my-ceph-volume \
-o size=10GB
# MySQL备份
docker exec mysql sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > backup.sql
# PostgreSQL备份
docker exec postgres pg_dumpall -U postgres > backup.sql
# 导出容器文件系统
docker export <container> > container.tar
# 导入为镜像
cat container.tar | docker import - migrated-image
# 使用本地SSD存储
docker run -v /mnt/ssd:/data --mount type=tmpfs,destination=/tmp \
myapp
# 存储驱动选择
# 修改/etc/docker/daemon.json
{
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
# GlusterFS配置示例
docker volume create \
--driver=local \
--opt type=glusterfs \
--opt device=10.0.0.1:/gvol \
--opt o=log-level=DEBUG \
gluster-vol
# AWS EBS卷
docker volume create \
--driver=rexray/ebs \
--name=ebs-vol \
--opt=size=50
# 加密数据卷
docker volume create \
--driver=local \
--opt type=encrypted \
--opt key=my-secret-key \
secure-vol
# 只读挂载
docker run -v /data:/app:ro \
myapp
# 查看存储使用情况
docker system df
# 分析容器存储
docker diff <container>
# 清理无用数据
docker system prune --volumes
FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp .
FROM alpine:latest
WORKDIR /root/
COPY --from=builder /app/myapp .
CMD ["./myapp"]
version: '3'
services:
web:
image: nginx
ports:
- "80:80"
db:
image: postgres
environment:
POSTGRES_PASSWORD: example
docker logs <container_id>
docker run -it --entrypoint /bin/sh <image>
netstat -tulnp | grep <port>
docker inspect <container> | grep -i memory
docker network inspect <network_name>
docker exec <container> ping <target>
docker exec <container> cat /etc/resolv.conf
iptables -L -n
docker stats
--memory
, --cpus
参数docker exec <container> top
docker info | grep "Storage Driver"
# 使用非root用户运行容器
docker run -u 1000:1000 myapp
# 限制内核能力
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE nginx
# 资源限制
docker run --memory 512m --cpus 1 --pids-limit 100 myapp
# 只读文件系统
docker run --read-only --tmpfs /tmp:rw,size=50m myapp
# 安全配置文件
docker run --security-opt no-new-privileges \
--security-opt seccomp=unconfined \
--security-opt apparmor=docker-default \
myapp
# 使用Snyk扫描镜像
docker scan --file Dockerfile myimage
# 漏洞数据库更新
docker scout cves myimage
# 镜像签名验证
docker trust inspect --pretty myimage
# 构建时扫描
docker build --secret id=mysecret,src=secret.txt \
--no-cache -t myimage .
# 运行时行为监控
docker run --security-opt apparmor=my-profile \
--security-opt seccomp=my-seccomp.json \
myapp
# 审计日志
docker events --filter 'event=container' --since 1h
# 运行时检查
docker container checkpoint create \
--leave-running mycontainer checkpoint1
# 网络策略限制
docker network create --internal secure-net
# 容器间TLS加密
docker run --network secure-net \
-e SSL_CERT=/certs/cert.pem \
-e SSL_KEY=/certs/key.pem \
myapp
# 防火墙规则
docker run --network host --cap-add NET_ADMIN \
nicolaka/netshoot iptables -A INPUT -p tcp --dport 80 -j DROP
# 启用Docker内容信任
export DOCKER_CONTENT_TRUST=1
docker push myrepo/myimage
# 使用CIS基准检查
docker run -it --net host --pid host --userns host --cap-add audit_control \
-v /etc:/etc:ro \
-v /usr/bin/containerd:/usr/bin/containerd:ro \
-v /usr/bin/runc:/usr/bin/runc:ro \
aquasec/kube-bench:latest
# Falco实时监控
docker run -d --name falco \
--privileged \
-v /var/run/docker.sock:/host/var/run/docker.sock \
-v /dev:/host/dev \
-v /proc:/host/proc:ro \
-v /boot:/host/boot:ro \
-v /lib/modules:/host/lib/modules:ro \
-v /usr:/host/usr:ro \
falcosecurity/falco
# 实时监控容器资源
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}"
# 获取容器指标API
curl --unix-socket /var/run/docker.sock \
http://localhost/containers/<container_id>/stats?stream=false
# 使用cAdvisor收集指标
docker run -d \
--name=cadvisor \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:ro \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--publish=8080:8080 \
gcr.io/cadvisor/cadvisor:v0.47.0
# prometheus.yml
scrape_configs:
- job_name: 'docker'
static_configs:
- targets: ['localhost:9323']
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
container_cpu_usage_seconds_total
container_memory_usage_bytes
container_network_receive_bytes_total
container_fs_writes_bytes_total
<source>
@type forward
port 24224
</source>
<match docker.**>
@type elasticsearch
host elasticsearch
port 9200
logstash_format true
</match>
# 使用Fluentd驱动
docker run --log-driver=fluentd \
--log-opt fluentd-address=fluentd:24224 \
--log-opt tag="docker.{{.Name}}" \
nginx
groups:
- name: docker-alerts
rules:
- alert: HighMemoryUsage
expr: container_memory_usage_bytes{name!=""} / container_spec_memory_limit_bytes > 0.8
for: 5m
labels:
severity: warning
annotations:
summary: "High memory usage on {{ $labels.name }}"
docker events --filter 'event=die'
docker run --restart unless-stopped myapp
docker events --format '{{json .}}' | while read event; do
echo "Event: $event"
# 触发自定义处理逻辑
done
# 使用perf分析容器性能
docker run --privileged --pid=host -it \
brendangregg/perf stat -a
# 火焰图生成
docker run --privileged --pid=host -it \
brendangregg/perf record -F 99 -a -g -- sleep 30
Throttled CPU Time
OOM Kill Count
I/O Wait Percentage
Packet Drop Rate
{
"timestamp": "2023-01-01T12:00:00Z",
"level": "ERROR",
"message": "Failed to connect",
"container": "webapp",
"trace_id": "abc123"
}
# 配置日志轮转
docker run --log-driver=json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
nginx
# 使用log-driver过滤敏感数据
docker run --log-driver=syslog \
--log-opt syslog-format=rfc5424 \
--log-opt tag="{{.ImageName}}/{{.Name}}" \
--log-opt env=SECRET_KEY \
myapp
.gitlab-ci.yml
配置--cpu-shares
--memory
--blkio-weight
进入运行中容器:
docker exec -it <container> /bin/bash
检查容器进程:
docker top <container>
分析镜像历史:
docker history <image>
批量操作:
# 停止所有容器
docker stop $(docker ps -aq)
# 删除所有容器
docker rm $(docker ps -aq)
# 删除所有镜像
docker rmi $(docker images -q)
导出/导入:
# 导出容器
docker export <container> > container.tar
# 导入为镜像
cat container.tar | docker import - new-image