You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求在AWS EC2启动ECS任务前执行docker system prune解决磁盘满问题

嘿,这个问题我之前帮好几个开发者处理过,确实是ECS+EC2自动关机场景里很容易踩的坑——任务刚结束就触发关机,Docker的自动清理(比如定时垃圾回收或者默认的资源清理逻辑)根本没机会跑,日积月累磁盘自然就被占满了。给你几个靠谱的解决方案,按优先级排序:

方案1:在关机流程里主动触发Docker清理(最可靠)

核心思路是不要直接关机,先让EC2执行完彻底的Docker清理操作,确认完成后再关机。你可以修改CloudWatch规则触发的Lambda函数来实现这个流程:

  • 原来的Lambda可能是直接调用ec2.stop_instances(),现在改成三步:
    1. 用EC2 Run Command给目标实例发送清理命令
    2. 等待清理命令执行完成
    3. 再调用关机接口

示例Lambda代码片段(Python):

import boto3
import time

ec2 = boto3.client('ec2')
ssm = boto3.client('ssm')

def lambda_handler(event, context):
    # 从CloudWatch事件中获取目标EC2实例ID
    instance_id = event['detail']['instance-id']
    
    # 发送Docker全量清理命令:清理未使用的容器、镜像、卷
    response = ssm.send_command(
        InstanceIds=[instance_id],
        DocumentName='AWS-RunShellScript',
        Parameters={'commands': ['docker system prune -af --volumes']}
    )
    command_id = response['Command']['CommandId']
    
    # 轮询等待命令执行完成(最多等待5分钟)
    wait_time = 0
    while wait_time < 300:
        invocation_status = ssm.get_command_invocation(
            CommandId=command_id,
            InstanceId=instance_id
        )['Status']
        if invocation_status in ['Success', 'Failed']:
            break
        time.sleep(10)
        wait_time += 10
    
    # 无论清理成功与否,最终执行关机(也可根据状态调整逻辑)
    ec2.stop_instances(InstanceIds=[instance_id])
    return {'status': 'shutdown initiated after cleanup attempt'}

注意事项:

  • 给Lambda角色添加ssm:SendCommand、ssm:GetCommandInvocation、ec2:StopInstances的权限(最小权限原则,别直接给全量权限)
  • EC2实例需要安装SSM Agent(Amazon Linux 2默认自带,其他系统需手动安装)
方案2:给EC2添加本地关机钩子

如果不想改动Lambda,也可以在EC2实例的操作系统层面设置关机前的自动清理脚本:

以Amazon Linux 2为例,创建一个systemd服务:

# 新建服务文件
sudo tee /etc/systemd/system/shutdown-docker-cleanup.service <<EOF
[Unit]
Description=Cleanup Docker resources on shutdown
DefaultDependencies=no
Before=shutdown.target reboot.target halt.target

[Service]
Type=oneshot
ExecStart=/usr/bin/docker system prune -af --volumes
TimeoutStartSec=300  # 最多等待5分钟完成清理

[Install]
WantedBy=shutdown.target reboot.target halt.target
EOF

然后启用这个服务:

sudo systemctl daemon-reload
sudo systemctl enable shutdown-docker-cleanup.service

这样实例收到关机信号时,会先执行Docker清理,完成后再继续关机流程。

方案3:延迟关机,给自动清理留时间

这是最简单的临时方案,可靠性稍差:修改CloudWatch规则的触发逻辑,不是任务一停止就关机,而是延迟15-30分钟再触发。

比如在CloudWatch事件规则里,把触发动作设置为“延迟15分钟”,或者用Lambda的异步调用+SQS延迟队列实现。这个方法的缺点是清理时间不确定,但大多数场景下15分钟足够Docker默认的垃圾回收跑完。

额外优化:从源头减少磁盘占用

除了事后清理,还可以从任务层面降低磁盘消耗:

  • 在ECS任务定义中配置awslogs日志驱动,把容器日志传到CloudWatch,避免日志占用本地磁盘
  • 尽量使用轻量级基础镜像(比如Alpine代替Ubuntu),减少镜像体积
  • 在容器启动脚本的末尾,主动清理临时文件(比如rm -rf /tmp/*)

内容的提问来源于stack exchange,提问作者user2043723

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:53:54