适用环境:Ubuntu 24.04 LTS / Docker 26.1.4 / Compose v2.28.1 / overlay2 / cgroup2fs / systemd
编写日期:2026-06-10
适用服务器:124.223.155.35 (VM-0-5-ubuntu) 及同架构 CVM
维护:本机权威源,修改后同步飞书文档

0. 环境速查

terminal bash
  1# 一行总览
  2docker version --format '{{.Server.Version}} | {{.Client.Version}}' 2>&1
  3docker info --format '{{.Driver}} | {{.CgroupDriver}} | {{.CgroupVersion}} | {{.KernelVersion}}'
  4cat /etc/docker/daemon.json

本机当前配置:

  • 存储驱动:overlay2
  • Cgroup:systemd (cgroup v2)
  • 根目录:/var/lib/docker (已用 2.2G)
  • 注册表镜像:mirror.ccs.tencentyun.comdocker.m.daocloud.io
  • 现有网络:baota_net (bridge)、默认 bridge/host/none
  • 现有卷:1 个 local 卷
  • 现有容器:1 个 mysql(mysql_bptx-mysql_BpTX-1,端口 13306→3306)

1. 安装与初始化

1.1 一键安装(Ubuntu/Debian)

terminal bash
  1# 官方脚本(国内可能慢)
  2curl -fsSL https://get.docker.com | bash
  3 
  4# 国内用户推荐用阿里云镜像
  5curl -fsSL https://get.docker.com -o get-docker.sh
  6sh get-docker.sh --mirror Aliyun
  7 
  8# 安装后把当前用户加进 docker 组(避免每次 sudo)
  9sudo usermod -aG docker $USER
 10newgrp docker   # 或重新登录
 11 
 12# 验证
 13docker run --rm hello-world

1.2 配置 daemon.json(最常改的)

terminal bash
  1# 标准位置
  2sudo nano /etc/docker/daemon.json

推荐配置(本机已用):

daemon.json json
  1{
  2  "registry-mirrors": [
  3    "https://mirror.ccs.tencentyun.com",
  4    "https://docker.m.daocloud.io"
  5  ],
  6  "log-driver": "json-file",
  7  "log-opts": {
  8    "max-size": "100m",
  9    "max-file": "5"
 10  },
 11  "storage-driver": "overlay2",
 12  "default-ulimits": {
 13    "nofile": { "Name": "nofile", "Hard": 65536, "Soft": 65536 }
 14  }
 15}

重启生效:

terminal bash
  1sudo systemctl restart docker

1.3 ⚠️ 改 daemon.json 的两个坑

现象 原因 修法
dockerd 起不来:invalid character '}' after array element 宝塔面板 / 其他工具会自动注入 mirror,破坏 JSON 闭合 python3 -c 'import json; json.dump(...)' 写文件,不要用 heredoc;写完 python3 -m json.tool 校验
多次 systemctl start docker 失败 systemd 限流("Start request repeated too quickly") systemctl reset-failed docker && systemctl start docker

1.4 镜像加速器选型(实测)

Mirror 实测结果 备注
mirror.ccs.tencentyun.com ✅ HTTP 200 腾讯云公网 mirror,首选
docker.m.daocloud.io ✅ 通 备选
ccr.ccs.tencentyun.com ❌ 401 Unauthorized 腾讯云内网,需账号授权
hub-mirror.c.163.com ❌ 000 域名失效 已下架
docker.mirrors.ustc.edu.cn ❌ 000 这台机不通
dockerproxy.com ❌ 000 这台机不通

2. 服务管理(systemd)

terminal bash
  1# 启停
  2sudo systemctl start docker
  3sudo systemctl stop docker
  4sudo systemctl restart docker
  5 
  6# 状态
  7sudo systemctl status docker
  8sudo systemctl is-active docker
  9sudo systemctl is-enabled docker
 10 
 11# 开机自启
 12sudo systemctl enable docker
 13sudo systemctl disable docker
 14 
 15# 限流重置(改坏配置反复启动会触发)
 16sudo systemctl reset-failed docker
 17sudo systemctl start docker
 18 
 19# 看日志(最后 50 条)
 20sudo journalctl -u docker -n 50 --no-pager
 21sudo journalctl -u docker -f   # 实时跟踪
 22 
 23# 看 dockerd 完整命令
 24systemctl cat docker | grep ExecStart

2.1 容器服务(开机自启)

terminal bash
  1# 临时容器重启策略
  2docker run --restart=no               myimage  # 默认:不重启
  3docker run --restart=on-failure:5     myimage  # 失败才重启,最多5次
  4docker run --restart=always           myimage  # 总是重启(包括 docker daemon 启动时)
  5docker run --restart=unless-stopped   myimage  # 推荐:除非手动 stop,否则总重启
terminal bash
  1# 已运行容器改重启策略
  2docker update --restart=unless-stopped <container>
  3 
  4# 批量改
  5docker ps -q | xargs -I {} docker update --restart=unless-stopped {}

3. 镜像管理

3.1 拉取 / 推送

terminal bash
  1docker pull mysql:8.0                       # 官方
  2docker pull registry.cn-hangzhou.aliyuncs.com/namespace/repo:tag   # 阿里云
  3docker pull mirror.ccs.tencentyun.com/library/mysql:8.0          # 走 mirror
  4 
  5# 推送(需先 docker login)
  6docker login
  7docker tag myapp:1.0 myregistry.com/myapp:1.0
  8docker push myregistry.com/myapp:1.0

3.2 列出 / 搜索 / 删除

terminal bash
  1docker images                              # 本地所有
  2docker images -a                           # 含中间层
  3docker images --format &#x27;{{.Repository}}:{{.Tag}} {{.Size}}'  # 精简
  4 
  5docker search nginx                        # Docker Hub 搜索
  6docker search --filter is-official=true nginx
  7 
  8# 删除
  9docker rmi <image>                         # 按 ID/name
 10docker rmi $(docker images -q -f "dangling=true")    # 清悬空镜像
 11docker image prune -a                      # 全部未用镜像(危险)

3.3 镜像标签 / 导出导入

terminal bash
  1# 打标签
  2docker tag mysql:8.0 myregistry.com/mysql:8.0
  3 
  4# 导出(生产环境离线迁移用)
  5docker save -o mysql-8.0.tar mysql:8.0
  6gzip mysql-8.0.tar                        # 压缩
  7 
  8# 导入
  9docker load -i mysql-8.0.tar
 10docker load -i mysql-8.0.tar.gz

3.4 构建镜像

terminal bash
  1# 标准构建
  2docker build -t myapp:1.0 .
  3docker build -t myapp:1.0 -f Dockerfile.dev .
  4 
  5# 多阶段构建指定阶段
  6docker build --target runtime -t myapp:runtime .
  7 
  8# 不用缓存
  9docker build --no-cache -t myapp:1.0 .
 10 
 11# BuildKit(更快,支持 secrets)
 12DOCKER_BUILDKIT=1 docker build -t myapp:1.0 .

Dockerfile 模板:

Dockerfile dockerfile
  1# syntax=docker/dockerfile:1.7
  2FROM python:3.12-slim AS builder
  3WORKDIR /app
  4COPY requirements.txt .
  5RUN pip wheel --no-cache-dir --wheel-dir /wheels -r requirements.txt
  6 
  7FROM python:3.12-slim
  8WORKDIR /app
  9COPY --from=builder /wheels /wheels
 10RUN pip install --no-cache-dir --no-index --find-links=/wheels /wheels/*
 11COPY . .
 12USER 1000:1000
 13EXPOSE 8000
 14CMD ["gunicorn", "app:app", "-b", "0.0.0.0:8000"]

3.5 查看镜像信息

terminal bash
  1docker history mysql:8.0                   # 层历史
  2docker inspect mysql:8.0                   # 完整 JSON
  3docker inspect --format=&#x27;{{.Config.Env}}' mysql:8.0   # 环境变量
  4docker inspect --format=&#x27;{{json .Config.ExposedPorts}}' mysql:8.0  # 端口

4. 容器生命周期

4.1 启动 / 停止 / 删除

terminal bash
  1# 运行
  2docker run -d --name web -p 8080:80 nginx:alpine
  3docker run -it --rm ubuntu:24.04 bash      # 交互式,用完即删
  4docker run -d --name db \
  5  -e MYSQL_ROOT_PASSWORD=*** \
  6  -v /data/mysql:/var/lib/mysql \
  7  -p 3306:3306 \
  8  --restart unless-stopped \
  9  mysql:8.0
 10 
 11# 查看
 12docker ps                 # 运行中
 13docker ps -a              # 全部
 14docker ps -q              # 只取 ID
 15docker ps --format &#x27;table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}'
 16 
 17# 启停
 18docker start <container>
 19docker stop <container>           # SIGTERM + 10s 超时
 20docker stop -t 30 <container>     # 给 30s 优雅退出
 21docker restart <container>
 22docker kill <container>           # SIGKILL 立即
 23 
 24# 删除
 25docker rm <container>
 26docker rm -f <container>          # 强制(运行中也能删)
 27docker rm $(docker ps -aq -f status=exited)   # 批量清已退出的
 28docker container prune            # 全部已停止

4.2 进入容器

terminal bash
  1docker exec -it <container> bash             # 首选 bash
  2docker exec -it <container> sh               # 镜像只有 sh 时(alpine)
  3docker exec -it -u root <container> bash     # 切到 root
  4docker exec -w /app <container> pwd          # 指定工作目录
  5docker exec <container> env                  # 不进 shell,直接看环境变量
  6 
  7# 单条命令
  8docker exec <container> cat /etc/nginx/nginx.conf > local.conf

4.3 查看日志

terminal bash
  1docker logs <container>                # 全部
  2docker logs --tail 100 <container>     # 最后 100 行
  3docker logs -f <container>             # 实时跟踪
  4docker logs --since 10m <container>    # 最近 10 分钟
  5docker logs --until 2026-06-10T08:00:00 <container>   # 截止某时间
  6docker logs -t <container>             # 带时间戳

4.4 资源使用

terminal bash
  1docker stats                  # 实时
  2docker stats --no-stream       # 快照
  3docker stats --format &#x27;table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}'
  4 
  5# 单个容器详细信息
  6docker inspect <container> | jq &#x27;.State, .HostConfig.Memory, .HostConfig.CpuShares'

4.5 进程 / 文件 / 网络(容器内)

terminal bash
  1# 进程
  2docker top <container>
  3 
  4# 文件改动(对比 image 的 overlay)
  5docker diff <container>
  6 
  7# 端口映射
  8docker port <container>
  9 
 10# 文件拷贝
 11docker cp <container>:/path/in/container ./local/path
 12docker cp ./local/file <container>:/path/in/container

4.6 提交 / 导入变更

terminal bash
  1# 把运行中容器的变更打包成新镜像(不推荐做生产镜像)
  2docker commit <container> myimage:custom
  3 
  4# 导出容器文件系统(不是镜像,没有 layer 元信息)
  5docker export <container> -o container.tar

5. 网络

5.1 端口映射

terminal bash
  1# -p 语法:-p <host_ip>:<host_port>:<container_port>/<protocol>
  2docker run -p 8080:80 nginx               # 主机 8080 → 容器 80
  3docker run -p 127.0.0.1:8080:80 nginx      # 只绑 loopback(更安全)
  4docker run -p 8080:80/tcp nginx            # 显式协议
  5docker run -p 8080-8090:8000-8010 nginx    # 端口段
  6docker run -P nginx                        # 全部 EXPOSE 端口随机映射到主机

5.2 自定义网络(推荐)

terminal bash
  1# 创建
  2docker network create mynet
  3docker network create --driver bridge --subnet 172.20.0.0/16 mynet
  4 
  5# 列出
  6docker network ls
  7docker network inspect mynet
  8 
  9# 容器加入(推荐用 compose,或 --network)
 10docker run -d --name web --network mynet nginx
 11docker network connect mynet <existing_container>
 12docker network disconnect mynet <container>
 13 
 14# 删除
 15docker network rm mynet
 16docker network prune   # 清未用
 17 
 18# 容器间通信:同网络下直接用容器名或别名
 19docker run -d --name db --network mynet mysql
 20docker run -d --name app --network mynet -e DB_HOST=db myapp
 21# app 容器里直接 mysql -h db ... 即可

5.3 网络模式

模式 用途 写法
bridge 默认,单机隔离 --network bridge
host 共享主机网络栈(最大性能,端口冲突风险) --network host
none 无网络 --network none
container:NAME 共享另一个容器的网络 --network container:web
自定义 bridge 多容器互通,推荐 --network mynet

5.4 DNS

terminal bash
  1# 容器内 DNS 由 dockerd 控制(默认从主机继承)
  2docker run --dns 8.8.8.8 --dns 114.114.114.114 myapp
  3 
  4# 容器 hostname
  5docker run --hostname myapp.local myapp
  6docker exec <container> cat /etc/hosts
  7docker exec <container> cat /etc/resolv.conf

6. 数据持久化(卷 / 挂载)

6.1 三种挂载方式

terminal bash
  1# 1) Volume(推荐,docker 管理)
  2docker volume create mydata
  3docker run -v mydata:/data myapp
  4docker run -v mydata:/data:ro myapp         # 只读
  5 
  6# 2) Bind mount(直接挂主机目录,调试/配置常用)
  7docker run -v /host/path:/container/path:ro myapp
  8docker run --mount type=bind,source=/host/path,target=/container/path,readonly myapp
  9 
 10# 3) tmpfs(内存盘,存临时数据)
 11docker run --tmpfs /tmp myapp
 12docker run --mount type=tmpfs,destination=/tmp,tmpfs-size=100m myapp

6.2 卷管理

terminal bash
  1docker volume ls
  2docker volume inspect mydata
  3docker volume rm mydata
  4docker volume prune            # 清未用

6.3 备份/恢复

terminal bash
  1# 备份(其它容器挂载到目标卷,打包)
  2docker run --rm \
  3  -v mydata:/source:ro \
  4  -v $(pwd):/backup \
  5  alpine tar czf /backup/mydata-$(date +%Y%m%d).tar.gz -C /source .
  6 
  7# 恢复
  8docker run --rm \
  9  -v mydata:/target \
 10  -v $(pwd):/backup \
 11  alpine tar xzf /backup/mydata-20260610.tar.gz -C /target
 12 
 13# 直接备份 mysql 卷
 14docker exec <mysql_container> sh -c &#x27;exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > backup.sql

6.4 权限

terminal bash
  1# 容器内进程以 root 跑(默认),文件会成 root:root
  2# 想跟主机用户对齐:
  3docker run -u $(id -u):$(id -g) -v /data:/data myapp
  4 
  5# 临时改文件 owner
  6docker run --user 0:0 myapp chown -R 1000:1000 /data
  7 
  8# 推荐镜像里建专用非 root 用户(USER 1000)

7. Compose(v2 语法)

7.1 基础 compose 文件

compose.yaml yaml
  1# compose.yaml(旧名 docker-compose.yml 也认)
  2services:
  3  web:
  4    image: nginx:alpine
  5    container_name: nginx
  6    restart: unless-stopped
  7    ports:
  8      - "8080:80"
  9    volumes:
 10      - ./conf:/etc/nginx/conf.d:ro
 11      - nginx_data:/var/log/nginx
 12    networks:
 13      - appnet
 14    environment:
 15      - TZ=Asia/Shanghai
 16    depends_on:
 17      - db
 18    healthcheck:
 19      test: ["CMD", "wget", "-qO-", "http://localhost/"]
 20      interval: 30s
 21      timeout: 5s
 22      retries: 3
 23 
 24  db:
 25    image: mysql:8.0
 26    restart: unless-stopped
 27    environment:
 28      MYSQL_ROOT_PASSWORD: *** # 生产别写这,用 .env 文件
 29    volumes:
 30      - db_data:/var/lib/mysql
 31    networks:
 32      - appnet
 33 
 34volumes:
 35  db_data:
 36  nginx_data:
 37 
 38networks:
 39  appnet:
 40    driver: bridge

.env 文件(放项目根目录,跟 compose.yaml 同级):

block text
  1MYSQL_ROOT_PASSWORD=actual-secret-here

7.2 compose 命令

terminal bash
  1# 启动
  2docker compose up -d                     # 后台
  3docker compose up -d --build            # 重新构建
  4docker compose up -d --force-recreate   # 强制重建容器
  5 
  6# 查看
  7docker compose ps
  8docker compose ps --format &#x27;table {{.Service}}\t{{.State}}\t{{.Ports}}'
  9docker compose logs -f web
 10docker compose logs --tail 100 web
 11docker compose top
 12 
 13# 启停
 14docker compose stop
 15docker compose start
 16docker compose restart web
 17docker compose pause
 18docker compose unpause
 19 
 20# 缩放(只对未指定 container_name 的服务有效)
 21docker compose up -d --scale worker=3
 22 
 23# 进容器
 24docker compose exec web bash
 25docker compose exec -u root db bash
 26 
 27# 在 compose 网络里跑一次性命令
 28docker compose run --rm web python manage.py migrate
 29 
 30# 删除
 31docker compose down              # 删容器、网络
 32docker compose down -v           # 顺便删卷(危险,删数据)
 33docker compose down --rmi all    # 顺便删镜像
 34 
 35# 配置校验
 36docker compose config            # 打印合并后的最终配置
 37docker compose config -q         # 静默校验(CI 友好)
 38 
 39# 拉镜像
 40docker compose pull

7.3 多环境 / 多 compose 文件

terminal bash
  1# 基础 compose.yaml + override
  2docker compose -f compose.yaml -f compose.prod.yaml up -d
  3 
  4# 环境变量
  5DATABASE_URL=postgres://... docker compose up -d
  6# 或用 .env.${ENV} 配合:
  7docker compose --env-file .env.prod up -d

7.4 compose 部署常用套路

terminal bash
  1# 部署脚本模板(幂等)
  2#!/bin/bash
  3set -e
  4APP=/opt/myapp
  5cd $APP
  6git pull
  7docker compose pull
  8docker compose up -d --remove-orphans
  9docker image prune -f    # 清悬空镜像
 10docker system prune -f   # 清所有未用(慎重)

8. 环境变量 / 配置文件注入

terminal bash
  1# 单个环境变量
  2docker run -e KEY=value myapp
  3docker run -e KEY1=v1 -e KEY2=v2 myapp
  4 
  5# 从文件读
  6docker run --env-file .env myapp
  7 
  8# 只读配置文件(bind mount)
  9docker run -v ./my.cnf:/etc/mysql/my.cnf:ro mysql:8.0
 10 
 11# secrets(swarm 模式,或 K8s)
 12docker secret create db_password ./pw.txt
 13docker service create --secret db_password myapp

9. 资源限制

terminal bash
  1# 内存
  2docker run -m 512m myapp                    # 硬限 512M
  3docker run --memory-reservation 256m myapp  # 软限(保证 256M,可短暂超)
  4docker run --memory-swap 1g myapp           # 内存+swap 总和
  5docker run --oom-kill-disable myapp         # OOM 时不杀(危险)
  6 
  7# CPU
  8docker run --cpus 1.5 myapp                 # 最多 1.5 核
  9docker run --cpuset-cpus 0,1 myapp          # 绑核
 10docker run --cpu-shares 512 myapp           # 权重(默认 1024)
 11 
 12# 磁盘 IO
 13docker run --device-read-bps /dev/sda:10mb myapp
 14docker run --device-write-iops /dev/sda:1000 myapp
 15 
 16# ulimit
 17docker run --ulimit nofile=65536:65536 myapp

容器运行时改:

terminal bash
  1docker update -m 1g <container>
  2docker update --cpus 2 <container>

10. 健康检查

terminal bash
  1# Dockerfile 里
  2HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
  3  CMD curl -f http://localhost/ || exit 1
terminal bash
  1# 运行时
  2docker inspect --format=&#x27;{{json .State.Health}}' <container> | jq .
  3 
  4# compose 里
  5healthcheck:
  6  test: ["CMD-SHELL", "pg_isready -U postgres || exit 1"]
  7  interval: 10s
  8  timeout: 5s
  9  retries: 5
 10  start_period: 30s

11. 日志管理

11.1 默认 json-file 驱动

terminal bash
  1# 配置(写在 daemon.json)
  2{
  3  "log-driver": "json-file",
  4  "log-opts": {
  5    "max-size": "100m",   # 单文件最大
  6    "max-file": "5"        # 保留几个
  7  }
  8}
  9 
 10# 单容器覆盖
 11docker run --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 myapp

11.2 其它驱动

terminal bash
  1# 推到 syslog
  2docker run --log-driver=syslog --log-opt syslog-address=tcp://logserver:514 myapp
  3 
  4# 推到 journald
  5docker run --log-driver=journald myapp
  6sudo journalctl -u docker CONTAINER_NAME=web
  7 
  8# 无日志(不推荐)
  9docker run --log-driver=none myapp

11.3 排错现场

terminal bash
  1# 实时跟踪
  2docker logs -f <container> 2>&1 | grep -i error
  3 
  4# 找时间段的日志(json-file 驱动)
  5docker inspect <container> | jq -r &#x27;.[0].LogPath'
  6sudo tail -f /var/lib/docker/containers/<id>/<id>-json.log

12. 排障大全

12.1 容器起不来

terminal bash
  1# 1) 看日志
  2docker logs <container>
  3docker logs --tail 200 <container>
  4 
  5# 2) 看退出码
  6docker inspect <container> | jq &#x27;.[0].State'
  7 
  8# 3) 已退出容器进 shell(加 --rm 的进不去)
  9docker run -it --rm <image> bash   # 用同镜像开个新的查问题
 10 
 11# 4) 覆盖入口
 12docker run -it --entrypoint bash <image>
 13 
 14# 5) 资源耗尽
 15docker stats <container>
 16dmesg | grep -i oom   # OOM 杀进程记录

12.2 dockerd 起不来

terminal bash
  1# 看完整错误
  2sudo journalctl -u docker -n 100 --no-pager
  3 
  4# 常见 3 个:
  5# 1) iptables/nftables 冲突 → sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
  6# 2) 存储驱动坏了 → /var/lib/docker/ 内容不一致,需 docker system prune -a(数据丢)
  7# 3) daemon.json JSON 错 → python3 -m json.tool /etc/docker/daemon.json

12.3 镜像拉不下来

terminal bash
  1# 1) 先确认不是网络问题
  2curl -I https://mirror.ccs.tencentyun.com/v2/
  3 
  4# 2) 配 mirror(见 §1.2)
  5 
  6# 3) 手动走 mirror
  7docker pull mirror.ccs.tencentyun.com/library/mysql:8.0
  8 
  9# 4) 看 dockerd 拉镜像的日志
 10sudo journalctl -u docker -f | grep -i pull

12.4 网络问题

terminal bash
  1# 容器之间不通
  2docker network inspect mynet      # 是不是在同一 net
  3docker exec web ping -c 2 db      # 容器内互测
  4docker exec web nslookup db       # DNS 解析
  5docker exec web cat /etc/resolv.conf
  6 
  7# 主机访问不了容器端口
  8docker port <container>                              # 看实际映射
  9ss -tlnp | grep <port>                               # 主机监听了吗
 10sudo iptables -L -n | grep <port>                    # 防火墙
 11sudo ufw status                                      # UFW
 12 
 13# 容器访问不了外网
 14docker run --rm alpine ping -c 2 8.8.8.8             # ICMP
 15docker run --rm alpine wget -qO- ifconfig.me         # HTTPS

12.5 磁盘满

terminal bash
  1# 看 docker 占用
  2docker system df
  3docker system df -v
  4 
  5# 清
  6docker container prune       # 停的容器
  7docker image prune -a        # 未用镜像
  8docker volume prune          # 未用卷(小心)
  9docker network prune         # 未用网络
 10docker system prune          # 上面全清(会问 y)
 11docker system prune -a --volumes  # 含卷(非常危险)
 12 
 13# /var/lib/docker/overlay2 单独占满:dific 找最大层
 14du -sh /var/lib/docker/*
 15du -sh /var/lib/docker/overlay2/* | sort -h | tail -20

12.6 容器时区不对

terminal bash
  1# 方法 1:挂主机时区
  2docker run -v /etc/localtime:/etc/localtime:ro myapp
  3docker run -e TZ=Asia/Shanghai myapp
  4 
  5# 方法 2:compose
  6environment:
  7  - TZ=Asia/Shanghai
  8volumes:
  9  - /etc/localtime:/etc/localtime:ro

12.7 容器中文乱码

terminal bash
  1environment:
  2  - LANG=C.UTF-8
  3  - LC_ALL=C.UTF-8

13. 安全

13.1 镜像安全

terminal bash
  1# 扫漏洞
  2docker scan <image>            # 内置(要登录 Docker Hub)
  3trivy image <image>            # 推荐:trivy
  4 
  5# 只用官方/可信镜像,禁 latest 标签(生产)
  6# 镜像签名(cosign 之类)— 高级用法

13.2 容器权限最小化

terminal bash
  1# 禁特权
  2docker run --security-opt no-new-privileges myapp
  3 
  4# 禁所有 capabilities
  5docker run --cap-drop=ALL myapp
  6 
  7# 只给需要的
  8docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE myapp
  9 
 10# 禁 root(镜像内 USER 1000 也要有)
 11docker run --user 1000:1000 myapp
 12 
 13# 只读 rootfs
 14docker run --read-only myapp
 15 
 16# 禁 network namespace 操作
 17docker run --security-opt seccomp=default.json myapp  # 默认就开了
 18docker run --security-opt apparmor=docker-default myapp  # 默认就开了

13.3 密钥管理

terminal bash
  1# 绝不要把 .env 写进镜像
  2# 绝不要 docker run -e KEY=xxx 还录屏/截图
  3# 优先用 secrets 机制或挂载的密钥文件
  4docker run -v /run/secrets:/run/secrets:ro myapp

14. Swarm(多机编排)

本机当前是单机模式,Swarm 关。简单命令备忘:

terminal bash
  1# 初始化集群
  2docker swarm init
  3docker swarm init --advertise-addr 1.2.3.4
  4 
  5# 看节点
  6docker node ls
  7 
  8# 起服务
  9docker service create --replicas 3 --name web -p 80:80 nginx
 10docker service ls
 11docker service ps web
 12docker service scale web=5
 13docker service update --image nginx:1.27 web
 14docker service rm web
 15 
 16# 离开集群
 17docker swarm leave --force
单机直接用 compose 就行,Swarm 是为多机/多副本设计的。

15. 监控 / 清理

terminal bash
  1# 总体磁盘
  2docker system df
  3 
  4# 实时
  5docker stats
  6 
  7# 事件流
  8docker events --since 10m
  9 
 10# 清理
 11docker system prune              # 停的容器+未用网络+悬空镜像+build cache
 12docker system prune -a           # 加上未用镜像
 13docker system prune -a --volumes # 加上未用卷(数据丢)
 14docker builder prune             # 只清 build cache

生产 cron 清理:

terminal bash
  1# /etc/cron.d/docker-cleanup
  20 3 * * 0 root docker image prune -a -f --filter "until=168h"  # 7 天前未用镜像
  30 3 * * 0 root docker container prune -f                       # 已停止容器
  40 3 * * 0 root docker volume prune -f                          # 未用卷
  50 3 * * 0 root docker builder prune -f --keep-storage 10GB     # build cache 限 10G

16. 进阶 / 杂项

16.1 buildx(多架构构建)

terminal bash
  1docker buildx create --use --name mybuilder
  2docker buildx build --platform linux/amd64,linux/arm64 -t myapp:1.0 --push .

16.2 私有 registry

terminal bash
  1# 登录
  2docker login registry.cn-hangzhou.aliyuncs.com -u xxx -p yyy
  3cat ~/.docker/config.json    # 凭据存在这
  4 
  5# 登出
  6docker logout registry.cn-hangzhou.aliyuncs.com
  7 
  8# 拉私有镜像
  9docker pull registry.cn-hangzhou.aliyuncs.com/namespace/repo:tag

16.3 容器内 docker(dind,CI 用)

terminal bash
  1docker run --privileged -d --name dind docker:dind
  2# 主机端口 2375/2376 暴露出来,CI 客户端连进去
warning

慎用 --privileged,只给 CI/构建用。

16.4 容器与主机文件互拷

terminal bash
  1docker cp ./local.conf <container>:/etc/nginx/conf.d/
  2docker cp <container>:/var/log/nginx/access.log ./

16.5 限制用户 / 命名空间

terminal bash
  1docker run --userns=host myapp                  # 共享主机用户 ns(少见)
  2docker run --pid=host myapp                     # 共享主机 PID(看主机进程)
  3docker run --ipc=host myapp                     # 共享 IPC

16.6 BuildKit 缓存挂载

Dockerfile dockerfile
  1# syntax=docker/dockerfile:1.7
  2RUN --mount=type=cache,target=/root/.cache/pip \
  3    pip install -r requirements.txt

17. 常用诊断一键脚本

terminal bash
  1# 收集完整诊断信息(出问题时跑一下)
  2cat << &#x27;EOF' > /tmp/docker-diag.sh
  3#!/bin/bash
  4echo "=== OS ==="
  5cat /etc/os-release | head -5
  6echo "=== Kernel ==="
  7uname -a
  8echo "=== Docker ==="
  9docker version --format &#x27;{{.Server.Version}} | {{.Client.Version}}'
 10docker info 2>&1 | grep -E "Driver|Cgroup|Storage|Docker Root Dir|Registry Mirrors" -A 1 | head -20
 11echo "=== Disk ==="
 12df -h /var/lib/docker
 13du -sh /var/lib/docker 2>/dev/null
 14echo "=== Containers ==="
 15docker ps -a --format &#x27;table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}'
 16echo "=== Recent dockerd logs ==="
 17journalctl -u docker -n 30 --no-pager | tail -30
 18echo "=== Network ==="
 19docker network ls
 20echo "=== Volumes ==="
 21docker volume ls
 22EOF
 23chmod +x /tmp/docker-diag.sh

18. 参考

  • 官方文档:https://docs.docker.com/
  • Compose 规范:https://docs.docker.com/compose/compose-file/
  • 排错 wiki:https://docs.docker.com/engine/Troubleshooting/
  • 本机现有应用参考:/root/hermes_from_43/hermes-agent/docker-compose.yml
  • 上次踩坑:daemon.json JSON 闭合 + systemd 限流重置

修订记录

日期 修订内容
2026-06-10 初版,基于本机(Ubuntu24.04/Docker26.1.4)环境编写