全部笔记All notes

Docker 容器管理命令完整指南

阅读 20m 12s20m 12s read

概述

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 Compose 使用指南 - 多容器应用编排
  • Kubernetes 单节点部署 - K8s 快速搭建
  • Kubernetes 多节点部署 - 生产集群搭建

中间件容器化

数据库容器化

监控运维

开发工具

  • Git 版本控制 - 代码版本管理
  • Jenkins CI/CD - 持续集成部署
  • GitLab CI/CD - 代码托管和 CI/CD

云原生技术

  • Helm 包管理 - Kubernetes 应用包管理
  • Istio 服务网格 - 微服务治理
  • 容器安全 - Docker 和 Kubernetes 安全

总结

Docker 是现代应用部署和开发的核心技术,本指南涵盖了从基础概念到高级实践的完整内容:

🎯 核心内容

  • 镜像管理: 构建、拉取、推送、优化镜像
  • 容器操作: 运行、监控、调试、管理容器
  • 网络配置: 容器间通信、端口映射、自定义网络
  • 存储管理: 数据持久化、卷挂载、备份恢复

🛠️ 实践技能

  • Dockerfile 编写: 多阶段构建、最佳实践、安全配置
  • Docker Compose: 多容器应用编排和服务定义
  • 系统管理: 资源监控、日志管理、系统清理
  • 故障排除: 常见问题诊断和解决方案

🔧 运维技巧

  • 性能优化: 镜像大小优化、构建缓存、资源限制
  • 安全加固: 用户权限、网络隔离、漏洞扫描
  • 监控告警: 健康检查、日志收集、性能监控
  • 自动化: CI/CD 集成、脚本化部署

💡 最佳实践:

  • 始终使用特定版本标签而非 latest
  • 采用多阶段构建优化镜像大小
  • 使用非 root 用户提高安全性
  • 合理配置资源限制和健康检查
  • 定期清理未使用的资源