你真的了解 Docker 日志吗?

Docker集群磁盘告警:定位与日志驱动程序清理
文章讲述了作者在接到服务器磁盘告警后,通过排查DockerSwarm集群中的游戏后台程序,发现是Docker引擎日志占用大量磁盘空间。作者详细描述了查找容器日志、驱动程序日志的过程,以及如何清理和管理Docker日志驱动程序,以释放磁盘空间。

dockerlogs



前言

今天服务器发送了磁盘告警通知,于是打开了尘封已久的电脑连上了公司服务器,服务器跑的是一个 Docker Swarm 集群(正是集群中的某一台服务器发生告警),告警的服务器上运行了多个游戏后台程序。一看到捕鱼游戏的程序,想都不用想(连打一条鱼都能产生日志的游戏),肯定就是它在搞鬼。于是进入该模块的数据持久化目录下查看其磁盘占用情况,结果发现就占用了 4 个多 G 不到 5 个 G,且其他容器(模块)的日志也是比较小的(几百兆)。

于是就去查看 Docker 的引擎日志,结果就是 Docker 引擎日志占用的服务器磁盘空间,接下来看看具体的排查步骤。

排查

1、先查看各游戏模块的数据持久化目录数据大小

其他模块日志的大小均小于当前查询模块的值,所以排除容器日志占用的服务器磁盘空间。

du -h --max-depth=1 ./

image-20230909204323801

2、接着查看 Docker 引擎日志(或叫驱动程序日志)

整体来说,Docker 日志无非就两类 => 容器日志驱动程序日志,第一步排查的就属于容器日志

驱动程序位于 Docker 服务的数据目录下的 container 目录下(我当前 Docker 服务的数据目录位于 /data/docker/ 下)。

进入对应目录后,查看该目录下对应的目录大小,下图可见 container 就是 Docker 的驱动程序日志目录,占了 140G。

du -h --max-depth=1 ./

image-20230909203829748

3、进入 container 目录并查看具体是哪个容器服务产生的大数据量的驱动程序日志

首先你要清楚的是,缺省情况下的 Docker 日志驱动程序为 json-file,常见的驱动程序还有 syslog、fluentd、gelf 等。

下图可见,容器 ID 为 d99611... 产生了 128 G 的驱动程序日志(这里要清楚的是每个容器都会产生驱动程序日志)。

du -sh * | sort -nr | head

image-20230909210007786

4、进入该容器 ID 目录并再次确认日志大小

很显然,我的日志驱动程序是 json-file 类型的,我们只需清空该日志即可释放其占用的磁盘空间

du -sh * | sort -nr | head

image-20230909210310815

5、清空该程序驱动日志

这里要注意:尽量不要使用 rm -rf 来删除日志文件(可能空间没有真正的释放,需重启 Docker 服务)。

因此我们使用一个空值进行覆盖即可(无需重启)释放磁盘空间占用。

清理后我们可见日志文件大小瞬间变为 16K。

image-20230909210520944

总结

1、Docker 日志分类

  • 容器的 stdout 和 stderr

    这些日志由在 Docker 容器中运行的应用程序生成。stdout 通常包含应用程序的正常输出,而 stderr 包含错误和异常信息。这些日志是最常见的 Docker 日志,它们可以通过 Docker 命令或 Docker API 进行访问。

  • Docker 守护进程日志

    Docker 守护进程本身也会生成日志,用于记录容器的创建、启动、停止等活动。这些日志通常包含 Docker 守护进程的运行状态和错误信息。它们通常被记录在守护进程的日志文件中,文件位置因操作系统而异(如 /var/log/docker.log)。

  • 容器日志文件

    Docker 容器内部的日志通常存储在容器的文件系统中。这些日志文件由容器内运行的应用程序生成,其位置和格式取决于应用程序的配置。你可以通过进入容器并查看这些文件来访问容器内部的日志。

  • Docker 日志驱动程序

    Docker 支持不同的日志驱动程序,用于将容器的日志输出发送到不同的目标。常见的日志驱动程序包括 json-file、journald、syslog、fluentd、gelf、splunk 等。每个驱动程序都有自己的配置选项和目标,允许你将日志发送到特定的日志聚合工具或目标。

2、如何查看你 Docker 当前的日志驱动程序

全局查看 Docker 的日志驱动程序

docker info
# 或
docker info |grep "Logging Driver"
# 或
docker info --format '{{.LoggingDriver}}'

image-20230909205808530

如何查看某个容器的日志驱动程序呢?

docker inspect -f '{{.HostConfig.LogConfig.Type}}' <你的容器ID>

3、如何指定设置 Docker 容器的日志驱动程序?

  • 运行容器时指定日志驱动

    场景:在运行少量容器服务时可这样操作

    注意:该操作的优先级高于全局配置的优先级

    docker run -it --log-driver none alpine ash
    
    # --log-driver:指定驱动程序
    # none:驱动程序名
    
  • 在 Docker 服务进行全局配置

    场景:在运行大量容器服务时可这样操作

    注意1:修改后需重新启动 Docker 以使更改对新创建的容器生效。现有容器不使用新的日志记录配置。

    注意2:daemon.json 配置文件中的 log-opts 配置必须以字符串类型的方式配置(因此数字也必须引号引起来)。

    {
      "log-driver": "json-file",
      "log-opts": {
        "max-size": "10m",
        "max-file": "3",
        "labels": "production_status",
        "env": "os,customer"
      }
    }
    
    # 说明
    # log-driver:指定日志驱动程序
    # log-opts:配置日志文件大小、文件个数及相关自定义标签等
    # max-size:限制日志文件最大大小
    # max-file:限制日志文件最多个数
    

4、Docker 支持的日志记录驱动程序

看官方文档:https://docs.docker.com/config/containers/logging/configure/

image-20230909211948220

在生产环境中,通常会将容器的日志输出发送到集中式日志系统,以便集中存储、分析和监控。常见的集中式日志系统包括Elasticsearch、Logstash、Kibana(ELK堆栈)、Fluentd、Graylog、Splunk 等。

比如将 Docker 驱动程序日志发送到 ELK,可这样配置:

{
  "log-driver": "syslog",
  "log-opts": {
    "syslog-address": "udp://<logstash-host>:<logstash-port>"
  }
}

—END

<think> 嗯,用户询问在生产环境中是否需要停掉Docker容器。这个问题需要从多个角度来思考。 首先考虑生产环境的核心需求。生产环境的核心目标是保证服务持续可用,任何操作都要优先考虑业务连续性。因此停容器通常不是常规操作。 想到几种可能需要停容器的情况。滚动更新时,旧容器需要停止并替换为新版本容器。这时候停止是必要的,但属于自动化流程的一部分。另外就是资源维护场景,比如主机维护或资源回收,这时候可能需要有计划地停止容器。还有问题排查或安全事件时,有时需要停止异常容器进行隔离。 不过更值得强调的是不应该停容器的情况。如果容器运行的是关键业务,比如数据库或核心API服务,随意停止会导致服务中断。另外高可用架构中单个容器停止可能影响不大,但也要看具体设计。负载均衡器通常会自动处理节点变化。 关于如何安全停止容器,想到几个要点。一定要通过编排工具如Docker Compose或K8s操作,而不是手动docker stop。必须在维护窗口操作并提前通知。停止前确保有健康实例接手流量。重要容器停止前要备份状态。监控系统要设置好报警,以便快速发现问题。 用户可能是运维或DevOps人员,关注生产环境稳定性。深层需求可能是想了解最佳实践,避免服务中断。回答时应该强调"通常不需要"这个核心观点,同时给出具体场景和操作建议。 准备在回答中先明确"通常不需要"的立场,然后分情况讨论。要突出编排工具的重要性,并提供具体操作示例。最后总结强调业务连续性优先的原则。 </think>在生产环境中,**通常不需要也不建议随意停掉正在运行的服务容器**,尤其是在没有替代方案的情况下。但根据具体场景,有计划地停止容器是必要的运维操作。以下是主要考量点: ### ⚠️ 不应该随意停止的场景 1. **核心业务服务**:运行数据库(如 MySQL、Redis)、API 网关、消息队列、核心业务微服务的容器,停止会导致服务中断、数据不一致或业务瘫痪。 2. **无冗余的单点服务**:未配置高可用或负载均衡的容器,停止即导致该服务完全不可用。 3. **用户访问高峰时段**:停止容器会直接影响用户体验和业务收益。 ### ✅ 需要有计划停止的场景 1. **滚动更新/发布**: * 部署新版本镜像时,需要按顺序停止旧容器并启动新容器(由编排工具如 Docker Swarm/Kubernetes 自动管理)。 * **操作示例** (针对单个 Docker Compose 项目): ```bash # 使用 compose 安全更新服务(会停止旧容器、拉取新镜像、启动新容器docker compose up -d --pull always --build --force-recreate your_service_name ``` 2. **资源维护与回收**: * 主机维护(硬件升级、系统补丁)。 * 资源超配,需释放资源时停掉非关键或低优先级容器。 * **操作要点**: * 优先使用 `docker compose stop` 或 `docker stop`(发送 SIGTERM 允许进程优雅退出)。 * **避免**直接使用 `docker compose down` 或 `docker rm -f`(强制删除,可能导致数据丢失或状态不一致)[^1]。 3. **问题排查与安全隔离**: * 容器行为异常(如资源耗尽、崩溃循环、被入侵),需停止进行故障分析或阻断攻击。 * **操作示例**: ```bash # 停止问题容器 docker stop suspicious_container # 检查日志(即使容器已停止) docker logs suspicious_container ``` ### 🔧 安全停止的最佳实践 1. **使用编排工具**:优先通过 Kubernetes、Docker Swarm、Nomad 或 `docker compose` 管理启停,确保遵循声明式配置和健康检查[^1][^3]。 2. **维护窗口期**:在业务低峰期操作,提前公告。 3. **确保冗余**:停止前确认负载均衡器已摘除该节点,或有健康实例接管流量。 4. **备份状态**:对有状态容器(如数据库),确保停止前数据持久化到卷并完成备份。 5. **优雅终止**:容器内应用需正确处理 `SIGTERM` 信号以完成清理工作。 6. **监控告警**:实时监控容器状态,停止后验证服务整体健康度[^3]。 ### 📌 总结 > **是否需要停掉生产环境的 Docker 容器?** > **不是常规操作,但必要时应遵循严格流程:** > ✅ **需要停**:滚动更新、主机维护、故障隔离时。 > ❌ **不能随意停**:核心服务、无冗余单点、业务高峰时段。 > 🔒 **安全操作原则**:用编排工具、选低峰期、保冗余、先备份、监控验证[^1][^3]。 --- ### 🔍 相关问题 1. 如何确保 Docker 容器在停止时数据不会丢失? 2. Kubernetes 中的滚动更新是如何管理容器停止和启动的? 3. 如何配置 Docker Compose 以实现服务的高可用性? 4. 生产环境中应如何监控 Docker 容器的健康状态? 5. 容器优雅关闭(Graceful Shutdown)的具体实现方式是什么? [^1]: 正确停止容器的方法,避免资源误删。 [^2]: 容器运行依赖前台进程,停止命令需考虑进程信号处理。 [^3]: 使用编排工具和监控是生产环境运维的关键保障
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云计算-Security

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值