1. Docker基础命令实战

第一次接触Docker时,我被那些晦涩的命令搞得晕头转向。直到后来才发现,掌握几个核心命令就能应付80%的日常场景。先来看最基础的"hello world"级操作:

# 检查Docker是否安装成功
docker --version
docker info

这两个命令就像汽车的仪表盘,--version告诉你安装的Docker引擎版本,而info会显示更详细的系统信息,包括容器数量、存储驱动等。我经常用info检查Docker的运行状态,特别是在服务异常时。

镜像操作是Docker的起点。还记得我第一次拉取镜像时,盯着下载进度条看了半天:

# 搜索并拉取官方MySQL镜像
docker search mysql
docker pull mysql:5.7

这里有个实用技巧:search命令的--filter=STARS=3000可以筛选星标超过3000的优质镜像。拉取特定版本时一定要指定tag(如5.7),否则默认拉取latest可能带来兼容性问题。

镜像管理常用命令:

# 查看本地镜像列表
docker images

# 删除指定镜像
docker rmi -f mysql:5.7

# 清理所有悬空镜像
docker image prune

注意-f参数是强制删除运行中的镜像,但生产环境慎用。我曾在测试环境误删基础镜像,导致所有依赖它的容器崩溃。

2. 容器生命周期管理

容器操作是Docker的核心。最常用的run命令就像魔术师的帽子,能变出各种服务实例:

# 启动一个Nginx容器
docker run -d --name my_nginx -p 8080:80 nginx

这个命令包含了几个关键参数:

  • -d:后台运行(detach模式)
  • --name:给容器起个易记的名字
  • -p:端口映射(主机端口:容器端口)

有一次我忘记映射端口,在主机上死活访问不到Nginx,排查了半天才发现问题。现在养成了习惯,启动容器后立即执行docker ps检查端口映射。

容器状态管理三板斧:

# 查看运行中的容器
docker ps

# 停止/启动容器
docker stop my_nginx
docker start my_nginx

# 删除容器
docker rm my_nginx

进阶技巧:docker run -it ubuntu /bin/bash会进入交互模式,就像SSH到一台临时虚拟机。我常用这种方式测试新环境,退出后容器自动销毁,不留痕迹。

3. 数据持久化与卷管理

初学Docker时,我最困惑的就是容器重启后数据丢失的问题。直到学会使用数据卷(Volume),才真正理解"牲畜 vs 宠物"的比喻。

挂载主机目录最简单实用:

docker run -v /宿主机路径:/容器路径 mysql

但更规范的做法是使用命名卷:

# 创建管理卷
docker volume create db_vol

# 挂载到容器
docker run -v db_vol:/var/lib/mysql mysql

我曾遇到过容器权限问题,解决方案是添加--privileged=true参数。但要注意这会降低安全性,生产环境应该通过chown提前设置好目录权限。

数据备份也很重要:

# 备份卷数据到tar包
docker run --rm -v db_vol:/volume -v /backup:/backup alpine \
   tar cvf /backup/db_backup.tar /volume

4. 网络配置实战

Docker网络刚开始像黑盒子,直到我动手实践才理清几种模式:

# 查看现有网络
docker network ls

# 创建自定义桥接网络
docker network create --driver bridge my_net

把容器接入自定义网络:

docker run --network=my_net --name web nginx
docker run --network=my_net --name db mysql

这样web容器可以直接用db主机名访问数据库,不需要知道IP。我在微服务项目中常用这种方式实现服务发现。

端口映射的进阶用法:

# 随机映射主机端口
docker run -P nginx

# 查看实际映射端口
docker port 容器ID

遇到网络问题时,docker network inspect是救命稻草,它能显示所有连接的容器和IP分配情况。

5. 镜像构建与Dockerfile

从消费者变成生产者,Dockerfile是必经之路。这是我常用的模板:

FROM python:3.8-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["gunicorn", "app:app", "-b", "0.0.0.0:5000"]

构建命令:

docker build -t my_app:v1 .

几个优化技巧:

  1. 合理使用.dockerignore文件加速构建
  2. 多阶段构建减小镜像体积
  3. 固定基础镜像版本避免意外更新

我曾因为没固定基础镜像版本,导致生产环境构建突然失败。现在所有FROM都带具体版本号,比如python:3.8.12-slim

6. 日志与故障排查

掌握排查技巧能节省大量时间。查看日志最直接:

docker logs -f --tail 100 容器ID

-f是实时跟踪,--tail只看最后N行。对于卡死的容器,docker stats能看资源占用:

CONTAINER ID   NAME      CPU %   MEM USAGE / LIMIT
c3f279d17e0a   redis     0.5%    156MiB / 3GiB

进入容器排查也很方便:

docker exec -it 容器ID /bin/bash

但要注意,修改运行中容器的文件只是临时生效,重建容器会丢失。持久化变更应该更新Dockerfile重新构建。

7. 安全最佳实践

安全常被忽视,直到出问题才后悔。几个关键点:

  1. 不要使用root用户运行进程:
RUN groupadd -r appuser && useradd -r -g appuser appuser
USER appuser
  1. 定期扫描镜像漏洞:
docker scan 镜像名
  1. 限制容器资源:
docker run -m 512m --cpus=1 nginx
  1. 使用只读文件系统:
docker run --read-only -v /tmp:/tmp alpine

8. 常用工具链

除了命令行,这些工具能提升效率:

  1. Docker Compose:一键启动多容器应用
version: '3'
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"
  1. Portainer:图形化管理界面
docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer
  1. Watchtower:自动更新容器
docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower

9. 生产环境经验

在真实项目中踩过的坑:

  1. 存储驱动选择:对于写入密集的应用,overlay2aufs性能更好

  2. 时区问题:基础镜像通常是UTC时间,需要显式设置:

ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime
  1. 信号处理:确保应用能正确处理SIGTERM,否则docker stop会超时强制kill

  2. 健康检查:关键服务应该配置HEALTHCHECK

HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost/ || exit 1

10. 性能调优技巧

当容器规模变大后,这些优化很关键:

  1. 镜像分层:将变化频率低的层放在Dockerfile前面

  2. 构建缓存:合理排序COPY和RUN指令,最大化利用缓存

  3. 资源限制:为每个容器设置合理的CPU和内存限制

  4. 日志轮转:防止日志撑爆磁盘

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

11. 跨主机网络方案

当单机Docker不够用时,需要考虑:

  1. Overlay网络:适合Swarm集群
docker network create -d overlay my_overlay
  1. Macvlan:让容器直接使用物理网络
docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 my_macvlan
  1. Ingress负载均衡:Swarm模式下自动配置

12. 备份与迁移

可靠的备份策略包括:

  1. 镜像导出
docker save -o my_app.tar my_app:v1
docker load -i my_app.tar
  1. 容器快照
docker export 容器ID > container.tar
docker import container.tar my_image
  1. 卷备份
docker run --rm -v 数据卷:/volume -v /backup:/backup alpine \
  tar cvf /backup/backup.tar /volume

13. CI/CD集成

在自动化流程中使用Docker的典型场景:

  1. 构建阶段
# .gitlab-ci.yml示例
build_image:
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE .
    - docker push $CI_REGISTRY_IMAGE
  1. 测试阶段
docker-compose -f docker-compose.test.yml up --abort-on-container-exit
  1. 部署阶段
docker stack deploy -c docker-compose.prod.yml my_stack

14. 监控与告警

完善的监控体系应该包括:

  1. 基础指标
docker stats
  1. Prometheus监控
# docker-compose.yml片段
monitor:
  image: prom/prometheus
  volumes:
    - ./prometheus.yml:/etc/prometheus/prometheus.yml
  ports:
    - "9090:9090"
  1. 日志聚合
docker run --name logspout \
  -v /var/run/docker.sock:/var/run/docker.sock \
  gliderlabs/logspout \
  syslog+tls://logs.example.com:514

15. 资源清理

随着时间推移,系统会积累各种资源:

# 删除所有停止的容器
docker container prune

# 删除所有未被使用的网络
docker network prune

# 删除所有悬空镜像
docker image prune

# 一键清理所有资源
docker system prune

建议在crontab中设置定期清理:

0 3 * * * /usr/bin/docker system prune -f

16. 多阶段构建实战

这是减小镜像大小的神器:

# 构建阶段
FROM golang:1.16 AS builder
WORKDIR /src
COPY . .
RUN go build -o app .

# 运行阶段
FROM alpine:latest
WORKDIR /app
COPY --from=builder /src/app .
CMD ["./app"]

最终镜像只有十几MB,而包含完整Go环境的构建镜像超过1GB。我在Java项目中也常用这种方式,先用Maven镜像构建,然后只拷贝jar包到JRE镜像。

17. 容器编排基础

虽然Kubernetes是主流,但Docker Swarm更简单易用:

# 初始化Swarm集群
docker swarm init

# 部署服务
docker service create --replicas 3 -p 80:80 --name web nginx

# 滚动更新
docker service update --image nginx:1.19 web

适合中小型项目的快速部署,我曾在客户现场用Swarm 30分钟搭建起高可用集群。

18. 自定义网络插件

当默认网络不满足需求时:

# 创建Macvlan网络
docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 my_macvlan

这样容器会获得和物理机同网段的IP,可以直接被外部访问。我在IoT项目中用这种方式让设备直接与容器通信。

更多推荐