概述
Docker 是一个开源的容器化平台,用于构建、运行和管理应用程序容器。本指南提供了 Docker 的完整命令参考、实用示例和最佳实践。
核心优势
- 环境一致性:开发、测试、生产环境保持一致
- 快速部署:秒级启动,快速扩缩容
- 资源高效:比虚拟机更轻量级
- 易于管理:简化应用部署和维护
应用场景
| 场景 | 描述 | 示例 |
|---|---|---|
| 应用容器化 | 将应用打包成容器镜像 | Web 应用、微服务 |
| 环境隔离 | 多应用环境隔离部署 | 开发测试环境 |
| 持续集成 | CI/CD 流水线构建 | Jenkins、GitLab CI |
| 服务编排 | 多容器应用管理 | Docker Compose、Kubernetes |
💡 学习目标: 掌握 Docker 的核心命令,理解容器化的基本概念,能够独立进行容器化部署。
快速入门
基本操作流程
# 1. 获取镜像
docker pull nginx:latest
# 2. 运行容器
docker run -d -p 80:80 --name my-nginx nginx:latest
# 3. 查看运行状态
docker ps
# 4. 查看日志
docker logs my-nginx
# 5. 进入容器
docker exec -it my-nginx bash
# 6. 停止容器
docker stop my-nginx
# 7. 删除容器
docker rm my-nginx
核心概念
| 概念 | 说明 | 示例 |
|---|---|---|
| 镜像 (Image) | 容器的只读模板 | nginx:latest |
| 容器 (Container) | 镜像的运行实例 | 基于 nginx 镜像运行的容器 |
| 仓库 (Repository) | 存储镜像的地方 | Docker Hub |
| 数据卷 (Volume) | 持久化存储 | 挂载目录或文件 |
| 网络 (Network) | 容器间通信 | bridge、host、none |
镜像管理
查看镜像
# 列出本地镜像
docker images
docker image ls
# 查看镜像详细信息
docker inspect <image>
# 查看镜像历史
docker history <image>
# 查看镜像分层
docker image inspect --format='{{.RootFS.Layers}}' <image>
# 查看镜像占用空间
docker system df
获取镜像
# 从 Docker Hub 拉取镜像
docker pull <image>:<tag>
# 拉取指定版本
docker pull nginx:1.21-alpine
docker pull mysql:8.0
docker pull postgres:13
# 拉取所有标签
docker pull -a nginx
# 从私有仓库拉取
docker pull registry.example.com/myapp:latest
# 指定平台拉取
docker pull --platform linux/amd64 nginx:alpine
搜索镜像
# 搜索镜像
docker search nginx
# 限制搜索结果数量
docker search --limit 10 nginx
# 只显示官方镜像
docker search --filter is-official=true nginx
# 按星级过滤
docker search --filter stars=3 nginx
# 显示完整描述
docker search --no-trunc nginx
构建镜像
# 从 Dockerfile 构建镜像
docker build -t my-app:latest .
# 指定 Dockerfile 路径
docker build -f /path/to/Dockerfile -t my-app .
# 构建时传递参数
docker build --build-arg VERSION=1.0 --build-arg ENV=prod -t my-app .
# 不使用缓存构建
docker build --no-cache -t my-app .
# 设置构建上下文
docker build --file=Dockerfile --tag=my-app:latest /path/to/context
# 多平台构建
docker buildx build --platform linux/amd64,linux/arm64 -t my-app:latest .
# 把容器当前状态保存为新镜像(适合临时留存,正式环境优先用 Dockerfile)
docker commit -m "add tools" -a "author" <container> my-app:debug
推送镜像
# 登录 Docker Hub
docker login
# 推送镜像到仓库
docker push username/my-app:latest
# 推送所有标签
docker push -a username/my-app
# 登录私有仓库
docker login registry.example.com
# 推送到私有仓库
docker push registry.example.com/my-app:latest
标签管理
# 给镜像打标签
docker tag my-app:latest my-app:v1.0
docker tag my-app:latest registry.example.com/my-app:latest
# 列出镜像标签
docker images my-app
# 删除标签
docker rmi my-app:v1.0
保存和加载镜像
# 保存镜像到文件
docker save nginx:latest -o nginx.tar
docker save nginx:latest | gzip > nginx.tar.gz
# 从文件加载镜像
docker load -i nginx.tar
docker load < nginx.tar
# 导出容器为镜像
docker export <container> > container.tar
# 从容器快照导入镜像
docker import container.tar my-app:latest
cat container.tar | docker import - my-app:latest
删除镜像
# 删除指定镜像
docker rmi <image>
docker image rm <image>
# 强制删除镜像
docker rmi -f <image>
# 删除未使用的镜像
docker image prune
# 删除所有未使用的镜像
docker image prune -a
# 删除所有镜像
docker rmi $(docker images -q)
# 删除悬挂镜像(<none>)
docker image prune -f
容器管理
运行容器
# 基本运行
docker run nginx
# 后台运行
docker run -d nginx
# 指定容器名称
docker run --name my-nginx nginx
# 端口映射
docker run -p 80:80 nginx # 映射到所有接口
docker run -p 127.0.0.1:80:80 nginx # 映射到本地接口
docker run -p 8080:80 nginx # 映射到不同端口
# 随机端口映射
docker run -P nginx
# 环境变量
docker run -e NODE_ENV=production node
docker run -e MYSQL_ROOT_PASSWORD=password mysql
# 工作目录
docker run -w /app node
# 挂载目录
docker run -v /host/path:/container/path nginx
# 挂载数据卷
docker run -v my-volume:/data nginx
# 只读挂载
docker run -v /host/path:/container/path:ro nginx
# 交互模式
docker run -it ubuntu bash
# 自动删除容器
docker run --rm -it ubuntu bash
# 重启策略
docker run --restart unless-stopped nginx
# 资源限制
docker run -m 512m --cpus="1.0" nginx
# 组合示例
docker run -d \
--name my-app \
-p 8080:80 \
-e ENV=production \
-v /data:/app/data \
--restart unless-stopped \
--memory="1g" \
--cpus="0.5" \
nginx:alpine
查看容器
# 查看运行中的容器
docker ps
docker container ls
# 查看所有容器
docker ps -a
docker container ls -a
# 查看最近创建的容器
docker ps -l
# 只显示容器 ID
docker ps -q
# 显示容器大小
docker ps -s
# 查看容器详细信息
docker inspect <container>
# 查看容器进程
docker top <container>
# 查看容器端口映射
docker port <container>
# 查看容器资源使用
docker stats <container>
# 实时监控所有容器
docker stats
# 查看容器文件系统变化
docker diff <container>
容器操作
# 只创建容器不启动,之后用 docker start 启动
docker create --name my-app nginx:latest
# 启动容器
docker start <container>
# 停止容器
docker stop <container>
# 优雅停止(发送 SIGTERM)
docker stop -t 30 <container>
# 重启容器
docker restart <container>
# 强制终止容器(发送 SIGKILL)
docker kill <container>
# 发送自定义信号
docker kill -s SIGTERM <container>
# 暂停容器
docker pause <container>
# 恢复容器
docker unpause <container>
# 重命名容器
docker rename old-name new-name
# 更新容器配置
docker update --memory="1g" --cpus="2.0" <container>
进入容器
# 在运行的容器中执行命令
docker exec -it <container> bash
docker exec -it <container> sh
# 以 root 用户执行
docker exec -it --user root <container> bash
# 以特定用户执行
docker exec -it --user 1000:1000 <container> bash
# 设置环境变量
docker exec -it -e DEBUG=true <container> bash
# 附加到容器主进程(不推荐)
docker attach <container>
# 执行单个命令
docker exec <container> ls -la
docker exec <container> cat /etc/hosts
docker exec <container> ps aux
# 在后台执行命令
docker exec -d <container> touch /tmp/test.txt
文件操作
# 复制文件到容器
docker cp local-file.txt <container>:/path/in/container/
docker cp ./config.json <container>:/app/config.json
# 从容器复制文件
docker cp <container>:/path/in/container/file.txt ./local-file.txt
docker cp <container>:/app/logs ./logs
# 复制目录
docker cp ./local-dir <container>:/path/in/container/
docker cp <container>:/path/in/container/dir ./local-dir
# 复制时保持权限
docker cp --archive ./local-dir <container>:/path/
# 从停止的容器复制文件
docker cp stopped-container:/path/to/file ./file
查看日志
# 查看容器日志
docker logs <container>
# 实时跟踪日志
docker logs -f <container>
# 显示最新 N 行日志
docker logs --tail 100 <container>
# 显示时间戳
docker logs -t <container>
# 显示指定时间后的日志
docker logs --since "2023-01-01T00:00:00" <container>
docker logs --since "1h" <container>
# 显示指定时间范围的日志
docker logs --since "2023-01-01" --until "2023-01-02" <container>
# 组合使用
docker logs -f --tail 50 -t <container>
删除容器
# 删除已停止的容器
docker rm <container>
# 强制删除运行中的容器
docker rm -f <container>
# 删除多个容器
docker rm container1 container2 container3
# 删除所有已停止的容器
docker container prune
# 删除所有容器(包括运行中的)
docker rm -f $(docker ps -aq)
# 停止并删除容器
docker stop <container> && docker rm <container>
# 删除退出的容器
docker rm $(docker ps -a -f status=exited -q)
网络管理
查看网络
# 列出网络
docker network ls
# 查看网络详细信息
docker network inspect <network>
# 查看默认桥接网络
docker network inspect bridge
# 查看容器网络配置
docker inspect <container> --format='{{.NetworkSettings}}'
创建网络
# 创建默认桥接网络
docker network create my-network
# 创建指定驱动的网络
docker network create -d bridge my-bridge
docker network create -d overlay my-overlay
# 创建带子网的网络
docker network create --subnet 192.168.1.0/24 my-network
# 创建带网关的网络
docker network create \
--subnet 192.168.1.0/24 \
--gateway 192.168.1.1 \
my-network
# 创建带 IP 范围的网络
docker network create \
--subnet 192.168.1.0/24 \
--ip-range 192.168.1.128/25 \
--gateway 192.168.1.1 \
my-network
# 创建自定义网络选项
docker network create \
--driver bridge \
--opt com.docker.network.bridge.name=my-bridge \
--opt com.docker.network.driver.mtu=1450 \
my-network
网络连接
# 将容器连接到网络
docker network connect my-network <container>
# 运行时指定网络
docker run --network my-network nginx
# 指定容器在网络中的 IP
docker network connect --ip 192.168.1.100 my-network <container>
# 为容器设置别名
docker network connect --alias web-server my-network <container>
# 断开容器网络连接
docker network disconnect my-network <container>
# 强制断开连接
docker network disconnect -f my-network <container>
# 删除网络
docker network rm my-network
# 清理未使用的网络
docker network prune
端口映射
# 查看容器端口映射
docker port <container>
# 动态端口映射
docker run -P nginx
# 指定端口映射
docker run -p 8080:80 nginx
# 多端口映射
docker run -p 80:80 -p 443:443 nginx
# UDP 端口映射
docker run -p 53:53/udp dns-server
# 绑定到特定接口
docker run -p 127.0.0.1:8080:80 nginx
# 映射端口范围
docker run -p 8000-8005:8000-8005 my-app
网络模式
# 桥接模式(默认)
docker run --network bridge nginx
# 主机模式
docker run --network host nginx
# 无网络模式
docker run --network none nginx
# 容器模式
docker run --network container:other-container nginx
# 自定义网络
docker run --network my-custom-network nginx
数据卷管理
查看数据卷
# 列出数据卷
docker volume ls
# 查看数据卷详细信息
docker volume inspect <volume>
# 查看数据卷使用情况
docker system df -v
# 查看悬挂数据卷
docker volume ls -f dangling=true
创建数据卷
# 创建数据卷
docker volume create my-volume
# 创建指定驱动的数据卷
docker volume create -d local my-volume
# 创建带标签的数据卷
docker volume create --label env=production my-volume
# 创建 NFS 数据卷
docker volume create \
--driver local \
--opt type=nfs \
--opt o=addr=192.168.1.1,rw \
--opt device=:/path/to/dir \
my-nfs-volume
# 创建本地绑定数据卷
docker volume create \
--driver local \
--opt type=none \
--opt o=bind \
--opt device=/host/path \
my-bind-volume
使用数据卷
# 挂载数据卷
docker run -v my-volume:/data nginx
# 挂载主机目录
docker run -v /host/path:/container/path nginx
# 只读挂载
docker run -v my-volume:/data:ro nginx
# 挂载当前目录
docker run -v $(pwd):/app node
# 使用绝对路径挂载
docker run -v /home/user/data:/app/data nginx
# 临时文件系统
docker run --tmpfs /tmp nginx
# 挂载多个卷
docker run \
-v data-volume:/data \
-v logs-volume:/logs \
-v /host/config:/config:ro \
my-app
# 使用挂载语法(推荐)
docker run --mount source=my-volume,target=/data nginx
docker run --mount type=bind,source=/host/path,target=/container/path nginx
备份和恢复
# 备份数据卷
docker run --rm \
-v my-volume:/data \
-v $(pwd):/backup \
alpine tar czf /backup/backup.tar.gz -C /data .
# 恢复数据卷
docker run --rm \
-v my-volume:/data \
-v $(pwd):/backup \
alpine tar xzf /backup/backup.tar.gz -C /data
# 复制数据卷
docker run --rm \
-v source-volume:/source \
-v target-volume:/target \
alpine cp -a /source/. /target/
删除数据卷
# 删除数据卷
docker volume rm <volume>
# 删除多个数据卷
docker volume rm volume1 volume2 volume3
# 删除未使用的数据卷
docker volume prune
# 强制删除所有数据卷
docker volume rm $(docker volume ls -q)
# 删除带过滤条件的数据卷
docker volume ls -f dangling=true -q | xargs docker volume rm
Dockerfile 指令
基础指令
# 指定基础镜像
FROM node:16-alpine
# 设置维护者信息
LABEL maintainer="your-email@example.com"
LABEL version="1.0"
LABEL description="My application"
# 设置工作目录
WORKDIR /app
# 设置环境变量
ENV NODE_ENV=production
ENV PORT=3000
ENV PATH="/app/bin:${PATH}"
# 复制文件
COPY package*.json ./
COPY . .
# 添加文件(支持 URL 和自动解压)
ADD https://example.com/file.tar.gz /tmp/
ADD archive.tar.gz /opt/
# 执行命令
RUN npm install --production && \
npm cache clean --force && \
rm -rf /tmp/* && \
addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001
# 设置用户
USER nextjs
# 暴露端口
EXPOSE 3000
# 创建数据卷
VOLUME ["/data", "/logs"]
# 设置启动命令
CMD ["npm", "start"]
# 设置入口点
ENTRYPOINT ["docker-entrypoint.sh"]
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# 停止信号
STOPSIGNAL SIGTERM
# Shell 形式 vs Exec 形式
RUN echo "shell form"
RUN ["echo", "exec form"]
CMD echo "shell form"
CMD ["echo", "exec form"]
多阶段构建
# 构建阶段
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# 运行阶段
FROM nginx:alpine AS runtime
COPY --from=builder /app/dist /usr/share/nginx/html
COPY --from=builder /app/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# 测试阶段
FROM builder AS test
RUN npm install
RUN npm test
# 开发阶段
FROM builder AS development
RUN npm install
CMD ["npm", "run", "dev"]
优化技巧
# 使用特定版本标签
FROM node:16.14.2-alpine
# 合并 RUN 指令减少层数
RUN apk add --no-cache \
git \
curl \
python3 \
make \
g++ && \
rm -rf /var/cache/apk/*
# 利用构建缓存
COPY package*.json ./
RUN npm ci --only=production
# 再复制源代码
COPY . .
# 使用 .dockerignore
# 在 .dockerignore 中排除不需要的文件
# node_modules
# .git
# *.md
# tests/
# 最小权限原则
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001 && \
chown -R nextjs:nodejs /app
USER nextjs
# 设置合适的工作目录
WORKDIR /app
# 使用 COPY 而不是 ADD
COPY --chown=nextjs:nodejs . .
# 清理安装缓存
RUN npm ci --only=production && npm cache clean --force
Docker Compose
基本配置
version: '3.8'
services:
web:
build:
context: .
dockerfile: Dockerfile
args:
- NODE_ENV=production
ports:
- "80:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://user:pass@db:5432/myapp
volumes:
- ./src:/app/src
- node_modules:/app/node_modules
depends_on:
- db
- redis
restart: unless-stopped
networks:
- app-network
db:
image: postgres:13
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
ports:
- "5432:5432"
networks:
- app-network
redis:
image: redis:alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
networks:
- app-network
volumes:
postgres_data:
redis_data:
node_modules:
networks:
app-network:
driver: bridge
Compose 命令
# 启动所有服务
docker compose up
# 后台启动
docker compose up -d
# 重新构建并启动
docker compose up --build
# 启动指定服务
docker compose up web db
# 查看服务状态
docker compose ps
# 查看服务日志
docker compose logs
docker compose logs -f web
# 执行命令
docker compose exec web bash
docker compose exec db psql -U user myapp
# 停止服务
docker compose stop
# 停止并删除容器
docker compose down
# 停止并删除包括卷和镜像
docker compose down -v --rmi all
# 重启服务
docker compose restart
# 扩展服务
docker compose up -d --scale web=3
# 拉取镜像
docker compose pull
# 构建镜像
docker compose build
# 验证配置文件
docker compose config
系统管理
系统信息
# 查看 Docker 系统信息
docker info
# 查看 Docker 版本
docker version
# 查看客户端和服务端版本
docker version --format 'table'
# 查看系统资源使用
docker system df
# 查看详细资源使用
docker system df -v
# 查看事件
docker events
# 查看实时事件
docker events --since "1h"
# 过滤事件
docker events --filter container=mycontainer
docker events --filter event=start
docker events --filter type=image
系统清理
# 清理未使用的资源
docker system prune
# 清理所有未使用的资源(包括未使用的镜像)
docker system prune -a
# 强制清理(不询问确认)
docker system prune -f
# 清理指定时间前的资源
docker system prune --filter "until=24h"
docker system prune --filter "until=2023-01-01T00:00:00"
# 分别清理各类资源
docker container prune # 清理停止的容器
docker image prune # 清理悬挂镜像
docker image prune -a # 清理所有未使用镜像
docker network prune # 清理未使用网络
docker volume prune # 清理未使用数据卷
# 清理构建缓存
docker builder prune
docker builder prune -a
认证管理
# 登录 Docker Hub
docker login
# 使用用户名和密码登录
docker login -u username -p password
# 登录私有仓库
docker login registry.example.com
# 从文件读取密码
cat password.txt | docker login -u username --password-stdin
# 查看登录信息
cat ~/.docker/config.json
# 退出登录
docker logout
# 退出指定仓库
docker logout registry.example.com
守护进程管理
# 查看守护进程状态
systemctl status docker
# 启动守护进程
sudo systemctl start docker
# 停止守护进程
sudo systemctl stop docker
# 重启守护进程
sudo systemctl restart docker
# 设置开机自启
sudo systemctl enable docker
# 查看守护进程日志
journalctl -u docker.service
journalctl -u docker.service -f
# 重载守护进程配置
sudo systemctl daemon-reload
sudo systemctl restart docker
插件管理
# 列出已安装插件
docker plugin ls
# 安装插件(例如 Loki 日志驱动)
docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all-permissions
# 启用 / 禁用插件
docker plugin enable loki
docker plugin disable loki
# 卸载插件(需先禁用)
docker plugin rm loki
实践示例
Web 应用部署
# 部署 Nginx 静态网站
docker run -d \
--name my-website \
-p 80:80 \
-v $(pwd)/html:/usr/share/nginx/html:ro \
--restart unless-stopped \
nginx:alpine
# 部署 Node.js 应用
docker run -d \
--name my-node-app \
-p 3000:3000 \
-e NODE_ENV=production \
-v $(pwd):/app \
-w /app \
--restart unless-stopped \
node:16-alpine \
npm start
# 部署带负载均衡的应用
docker network create app-network
# 启动多个应用实例
for i in {1..3}; do
docker run -d \
--name app-$i \
--network app-network \
-e INSTANCE_ID=$i \
my-app:latest
done
# 启动负载均衡器
docker run -d \
--name loadbalancer \
--network app-network \
-p 80:80 \
-v $(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro \
nginx:alpine
数据库部署
# 部署 MySQL 数据库
docker run -d \
--name mysql-db \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=rootpassword \
-e MYSQL_DATABASE=myapp \
-e MYSQL_USER=appuser \
-e MYSQL_PASSWORD=apppass \
-v mysql-data:/var/lib/mysql \
-v $(pwd)/init.sql:/docker-entrypoint-initdb.d/init.sql \
--restart unless-stopped \
mysql:8.0
# 部署 PostgreSQL 数据库
docker run -d \
--name postgres-db \
-p 5432:5432 \
-e POSTGRES_DB=myapp \
-e POSTGRES_USER=user \
-e POSTGRES_PASSWORD=password \
-v postgres-data:/var/lib/postgresql/data \
--restart unless-stopped \
postgres:13
# 部署 Redis 缓存
docker run -d \
--name redis-cache \
-p 6379:6379 \
-v redis-data:/data \
--restart unless-stopped \
redis:alpine \
redis-server --appendonly yes
# 部署 MongoDB
docker run -d \
--name mongo-db \
-p 27017:27017 \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=password \
-v mongo-data:/data/db \
--restart unless-stopped \
mongo:latest
开发环境搭建
# 创建开发网络
docker network create dev-network
# 启动开发数据库
docker run -d \
--name dev-db \
--network dev-network \
-p 5432:5432 \
-e POSTGRES_DB=myapp \
-e POSTGRES_USER=dev \
-e POSTGRES_PASSWORD=devpass \
-v dev-db-data:/var/lib/postgresql/data \
postgres:13
# 启动 Redis 开发实例
docker run -d \
--name dev-redis \
--network dev-network \
-p 6379:6379 \
redis:alpine
# 启动开发应用
docker run -it --rm \
--name dev-app \
--network dev-network \
-p 3000:3000 \
-v $(pwd):/app \
-w /app \
-e NODE_ENV=development \
-e DATABASE_URL=postgresql://dev:devpass@dev-db:5432/myapp \
-e REDIS_URL=redis://dev-redis:6379 \
node:16 \
bash
# 启动开发工具容器
docker run -d \
--name dev-tools \
--network dev-network \
-p 8080:8080 \
-v $(pwd):/workspace \
--privileged \
codercom/code-server:latest
监控和日志
# 部署 Prometheus 监控
docker run -d \
--name prometheus \
-p 9090:9090 \
-v prometheus-data:/prometheus \
-v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml \
--restart unless-stopped \
prom/prometheus
# 部署 Grafana 可视化
docker run -d \
--name grafana \
-p 3000:3000 \
-e GF_SECURITY_ADMIN_PASSWORD=admin \
-v grafana-data:/var/lib/grafana \
--restart unless-stopped \
grafana/grafana
# 部署 ELK 日志栈
# Elasticsearch
docker run -d \
--name elasticsearch \
-p 9200:9200 \
-e "discovery.type=single-node" \
-v es-data:/usr/share/elasticsearch/data \
--restart unless-stopped \
docker.elastic.co/elasticsearch/elasticsearch:7.15.0
# Logstash
docker run -d \
--name logstash \
-p 5044:5044 \
-v $(pwd)/logstash.conf:/usr/share/logstash/pipeline/logstash.conf \
--restart unless-stopped \
docker.elastic.co/logstash/logstash:7.15.0
# Kibana
docker run -d \
--name kibana \
-p 5601:5601 \
-e ELASTICSEARCH_HOSTS=http://elasticsearch:9200 \
--link elasticsearch \
--restart unless-stopped \
docker.elastic.co/kibana/kibana:7.15.0
最佳实践
性能优化
1. 镜像优化
# 使用多阶段构建
FROM node:16 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
FROM node:16-alpine AS runtime
WORKDIR /app
COPY --from=build /app/dist ./
COPY --from=build /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "index.js"]
2. 构建缓存优化
# 先复制依赖文件,利用 Docker 缓存
COPY package*.json ./
RUN npm ci --only=production
# 再复制源代码
COPY . .
RUN npm run build
3. 镜像大小优化
# 使用 Alpine 基础镜像
FROM node:16-alpine
# 合并 RUN 指令
RUN apk add --no-cache git curl && \
npm install && \
npm cache clean --force && \
apk del git
# 清理不必要的文件
RUN rm -rf /tmp/* /var/cache/apk/*
安全最佳实践
1. 使用非 root 用户
# 创建非 root 用户
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001
# 设置文件权限
COPY --chown=nextjs:nodejs . .
# 切换到非 root 用户
USER nextjs
2. 镜像安全扫描
# 扫描镜像漏洞
docker scan my-image:latest
# 使用 Trivy 扫描
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image my-image:latest
# 使用 Clair 扫描
docker run -d --name clair-db postgres:9.6
docker run -d --name clair --link clair-db:postgres \
quay.io/coreos/clair:latest
3. 资源限制
# 限制内存使用
docker run -m 512m my-app
# 限制 CPU 使用
docker run --cpus="1.5" my-app
# 限制文件描述符
docker run --ulimit nofile=1024:1024 my-app
# 禁用交换
docker run --memory-swappiness=0 my-app
4. 网络安全
# 禁用网络
docker run --network none my-app
# 使用自定义网络
docker network create --driver bridge secure-network
docker run --network secure-network my-app
# 限制容器权限
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE my-app
# 只读文件系统
docker run --read-only my-app
运维最佳实践
1. 健康检查
# Dockerfile 中添加健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# 运行时添加健康检查
docker run -d \
--name my-app \
--health-cmd="curl -f http://localhost:3000/health" \
--health-interval=30s \
--health-timeout=3s \
--health-retries=3 \
my-app:latest
2. 日志管理
# 配置日志驱动
docker run -d \
--log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
my-app
# 使用 syslog 驱动
docker run -d \
--log-driver syslog \
--log-opt syslog-address=tcp://logserver:514 \
my-app
# 禁用日志
docker run -d --log-driver none my-app
3. 重启策略
# 总是重启
docker run -d --restart always my-app
# 除非手动停止否则重启
docker run -d --restart unless-stopped my-app
# 失败时重启(最多3次)
docker run -d --restart on-failure:3 my-app
# 不重启(默认)
docker run -d --restart no my-app
4. 监控和告警
# docker-compose.yml 监控配置
version: '3.8'
services:
app:
image: my-app:latest
deploy:
resources:
limits:
memory: 512M
cpus: '0.5'
reservations:
memory: 256M
cpus: '0.25'
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
常见问题
问题1:容器启动失败
现象: 容器创建后立即退出
排查步骤:
# 查看容器日志
docker logs <container>
# 查看容器退出码
docker ps -a
# 以交互模式运行调试
docker run -it <image> sh
# 检查镜像构建历史
docker history <image>
# 检查容器配置
docker inspect <container>
常见原因:
- 主进程执行完毕后退出
- 启动命令错误
- 缺少必要的环境变量
- 文件权限问题
解决方案:
# 使用正确的启动命令
docker run -d my-app command-that-runs-forever
# 检查 Dockerfile 中的 CMD 或 ENTRYPOINT
# 确保主进程不会立即退出
问题2:端口访问问题
现象: 无法访问容器暴露的端口
排查步骤:
# 检查端口映射
docker port <container>
# 检查容器网络配置
docker inspect <container> --format='{{.NetworkSettings}}'
# 检查防火墙设置
sudo ufw status
sudo iptables -L
# 测试容器内部服务
docker exec <container> curl localhost:port
# 检查宿主机端口占用
netstat -tlnp | grep :port
ss -tlnp | grep :port
解决方案:
# 正确映射端口
docker run -p host-port:container-port image
# 检查应用绑定地址
# 应用应该绑定到 0.0.0.0 而不是 127.0.0.1
# 使用 host 网络模式
docker run --network host image
问题3:存储空间不足
现象: Docker 占用大量磁盘空间
排查步骤:
# 查看空间使用情况
docker system df
# 查看详细使用情况
docker system df -v
# 查看磁盘使用
df -h /var/lib/docker
# 查看具体占用
du -sh /var/lib/docker/*
解决方案:
# 清理未使用资源
docker system prune -a
# 分别清理各类资源
docker container prune # 清理停止的容器
docker image prune -a # 清理未使用的镜像
docker volume prune # 清理未使用的数据卷
docker network prune # 清理未使用的网络
# 清理构建缓存
docker builder prune -a
# 配置日志轮转
docker run --log-opt max-size=10m --log-opt max-file=3 image
# 移动 Docker 根目录
sudo systemctl stop docker
sudo mv /var/lib/docker /new/location/docker
sudo ln -s /new/location/docker /var/lib/docker
sudo systemctl start docker
问题4:权限问题
现象: 文件权限错误,无法读写文件
排查步骤:
# 检查文件权限
ls -la mounted-directory
# 查看容器内用户信息
docker exec <container> id
# 检查挂载点权限
docker exec <container> ls -la /mounted/path
解决方案:
# 修改文件所有者
sudo chown -R $USER:$USER ./data
# 使用正确的用户 ID 运行容器
docker run --user $(id -u):$(id -g) image
# 在 Dockerfile 中设置用户
USER 1000:1000
# 修改挂载目录权限
chmod -R 755 ./data
# 使用 ACL 设置权限
setfacl -R -m u:1000:rwx ./data
问题5:网络连接问题
现象: 容器间无法通信或无法访问外网
排查步骤:
# 检查网络配置
docker network ls
docker network inspect bridge
# 测试容器间连通性
docker exec container1 ping container2
# 检查 DNS 解析
docker exec <container> nslookup google.com
# 检查路由表
docker exec <container> route -n
# 检查防火墙规则
sudo iptables -L DOCKER-USER
解决方案:
# 使用自定义网络
docker network create my-network
docker run --network my-network container1
docker run --network my-network container2
# 配置 DNS
docker run --dns=8.8.8.8 image
# 使用容器名通信
docker run --name web nginx
docker run --link web:web app
# 检查代理设置
docker run -e HTTP_PROXY=http://proxy:port image
问题6:镜像构建失败
现象: docker build 命令失败
排查步骤:
# 详细构建日志
docker build --no-cache --progress=plain .
# 检查 Dockerfile 语法
docker build --dry-run .
# 分步构建调试
docker build --target=stage-name .
解决方案:
# 检查文件路径
COPY ./source ./destination
# 处理换行符问题
# 在 Windows 上使用 LF 而不是 CRLF
# 检查基础镜像
FROM node:16-alpine
# 设置构建参数
docker build --build-arg HTTP_PROXY=http://proxy:port .
相关文章
Docker 系列导航
- 上一篇: Docker 安装配置指南 - Docker 环境搭建
- 下一篇: Docker 环境部署 - 各种服务容器化部署
Docker 基础系列
- Docker 安装配置指南 - Docker 环境搭建
- Docker 环境部署 - 各种服务容器化部署
- Docker 最佳实践 - 生产环境使用建议
容器编排
- Docker Compose 使用指南 - 多容器应用编排
- Kubernetes 单节点部署 - K8s 快速搭建
- Kubernetes 多节点部署 - 生产集群搭建
中间件容器化
- Nacos 服务发现 - 微服务注册中心
- Kafka 消息队列 - 分布式消息系统
- RabbitMQ 消息队列 - 可靠消息传递
数据库容器化
- MySQL 数据库 - 关系型数据库
- MongoDB 文档数据库 - NoSQL 数据库
- Redis 缓存数据库 - 内存数据库
- Cassandra 分布式数据库 - 大数据存储
监控运维
- SkyWalking 链路追踪 - 应用性能监控
- ELK Stack 日志分析 - 日志收集分析
- Prometheus 监控 - 指标监控
开发工具
- Git 版本控制 - 代码版本管理
- Jenkins CI/CD - 持续集成部署
- GitLab CI/CD - 代码托管和 CI/CD
云原生技术
- Helm 包管理 - Kubernetes 应用包管理
- Istio 服务网格 - 微服务治理
- 容器安全 - Docker 和 Kubernetes 安全
总结
Docker 是现代应用部署和开发的核心技术,本指南涵盖了从基础概念到高级实践的完整内容:
🎯 核心内容
- 镜像管理: 构建、拉取、推送、优化镜像
- 容器操作: 运行、监控、调试、管理容器
- 网络配置: 容器间通信、端口映射、自定义网络
- 存储管理: 数据持久化、卷挂载、备份恢复
🛠️ 实践技能
- Dockerfile 编写: 多阶段构建、最佳实践、安全配置
- Docker Compose: 多容器应用编排和服务定义
- 系统管理: 资源监控、日志管理、系统清理
- 故障排除: 常见问题诊断和解决方案
🔧 运维技巧
- 性能优化: 镜像大小优化、构建缓存、资源限制
- 安全加固: 用户权限、网络隔离、漏洞扫描
- 监控告警: 健康检查、日志收集、性能监控
- 自动化: CI/CD 集成、脚本化部署
💡 最佳实践:
- 始终使用特定版本标签而非 latest
- 采用多阶段构建优化镜像大小
- 使用非 root 用户提高安全性
- 合理配置资源限制和健康检查
- 定期清理未使用的资源