# Prevent Storage Issues: Automated EC2 Cleanup Using AWS Systems Manager

Deploying services on AWS EC2 instances using Docker over time can lead to high storage, memory, and CPU usage. Manually increasing volume size and running prune commands to clear overlay storage and reduce memory usage is not a sustainable solution. To address this, we can automate the cleanup of EC2 instances using AWS Systems Manager.

By setting up a maintenance window with a *cron expression*, you can automate the regular cleanup of instances without manual intervention. This setup can be customized to run daily, during off-hours, or at specific intervals such as every few days or weeks. While there are other scheduling options available, configuring a *cron expression* is typically the easiest. This automation helps maintain optimal storage utilization and performance. Below is a step-by-step guide with screenshots to assist you through each stage of the process.

Step1: In the AWS Management Console, navigate to EC2, locate the IAM role for your instance, and attach the `AmazonSSMManagedInstanceCore` policy. This grants Systems Manager the permissions needed to manage and clean up your EC2 instances.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721635784159/50d78b40-0375-45de-8eae-fdc30eb5c48a.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721635590207/9987676e-6aa1-4ea8-9939-6c385ad3954f.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721635622001/f2e9708b-85c8-429b-9ca7-196836cb429c.png align="center")

Step2: After completing Step 1, connect to the EC2 instance using Session Manager. Verify the Docker and system agent paths by running the following commands: `which docker` and `which systemctl`.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721636115785/713ee5f9-d738-4cf0-a57c-0b35a50cb984.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721636135047/d8981a7e-4d97-43e4-8bc6-e1649cc00502.png align="center")

Step3: Go to AWS Systems Manager, click on "Documents" in the left sidebar, and create a cleanup document as shown in the screenshots.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721636775372/01f78a9a-16f4-440f-b8ff-720729abc110.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721636798621/6310a7ea-da41-4d43-b462-89c36e7ea39e.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721636830116/29846165-54cd-40e6-bb34-edf71095218a.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721638887079/503a300b-7d25-44fb-9d3c-96b43d16fb2c.png align="center")

* For AWS Linux-Based EC2 Instances(Confirm the Docker and system agent paths after Step 2):
    
    ```yaml
    schemaVersion: '2.2'
    description: "Run Docker cleanup commands on EC2 instances"
    mainSteps:
      - action: aws:runShellScript
        name: runDockerCleanup
        inputs:
          runCommand:
            - /bin/docker stop $(/bin/docker ps -q)
            - sleep 2
            - /bin/docker system prune -a -f
            - sleep 3
            - /bin/docker volume ls -qf dangling=true | xargs -r /bin/docker volume rm
            - sleep 3
            - /bin/systemctl restart ecs
            - sleep 3
            - /bin/docker system prune -a -f
            - sudo sync; sudo echo 3 > /proc/sys/vm/drop_caches
            - /bin/systemctl status ecs
            - /bin/docker ps -a
    ```
    
* For Ubuntu-Based EC2 Instances(Confirm the Docker and system agent paths after Step 2):
    

```yaml
schemaVersion: '2.2'
description: "Run Docker cleanup commands on EC2 instances"
mainSteps:
  - action: aws:runShellScript
    name: runDockerCleanup
    inputs:
      runCommand:
        - /usr/bin/docker stop $(/bin/docker ps -q)
        - sleep 2
        - /usr/bin/docker system prune -a -f
        - sleep 3
        - /usr/bin/docker volume ls -qf dangling=true | xargs -r /bin/docker volume rm
        - sleep 3
        - /usr/bin/systemctl restart ecs
        - sleep 3
        - /usr/bin/docker system prune -a -f
        - sudo sync; sudo echo 3 > /proc/sys/vm/drop_caches
        - /usr/bin/systemctl status ecs
        - /usr/bin/docker ps -a
```

***NOTE***: *If your services include* cron jobs\*, avoid stopping running containers and restarting the ECS service as part of cleanup scripts. This can disrupt scheduled tasks. To modify the provided script for such scenarios, comment out the script lines\* `docker stop` *and* `systemctl restart ecs` *Use only the prune and dangling volume cleanup commands for such services.*

* After the document is created, you can view and verify it as shown in the screenshots below.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721639290013/2faf5cc2-e6b1-4f5e-899a-18dc71141d2e.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721639312482/12e58525-6c2a-4758-9230-1ea4e69d37f9.png align="center")

Step4: Verify that your EC2 instance appears in Fleet Manager(found in the Systems Manager left sidebar), as shown in the screenshot below.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721639647540/cbb52a9d-b3da-453e-bb17-02f9200b3c13.png align="center")

Step5: Set up a maintenance window to automate the cleanup using the created document, as shown in the screenshots below.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721640224713/3a463c16-a642-4eb2-8963-34170982ba35.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721640259294/d2b848bd-99fe-4270-9ef8-c0c5dd4970c9.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721640302123/32746b15-c8ff-40e1-a2f9-e079a9221d3d.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721641265573/acefaeea-7c8b-4e0f-9d23-7acc9a0162c0.png align="center")

Step6: Navigate to the Systems Manager console, select "Maintenance Windows" from the left sidebar, choose your maintenance window, and click "Register Targets" to schedule the cleanup command on the selected EC2 instances, as shown in the screenshots below.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721643698202/6bb26557-8a24-4a95-9b82-be6118c1b8c2.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721645479170/dcbc64ac-34a1-413e-bf69-82fb21217fd7.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721643725956/78b9842a-d26a-43d2-bcc1-bedbb01d4900.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721643754064/f15e1d01-c882-4d6b-bac9-250e16b6f740.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721644126916/a3a3d8e8-0472-4451-b1a7-70ed67df9d07.png align="center")

Step7: Register a "Tasks" to link the cleanup document with the maintenance window and the registered target instances, as shown in the screenshots below.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721645590493/cdc178f2-b7f2-4995-89dd-a0e92d4ae65a.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721645630521/9317e0d6-9ab8-4d31-92bc-a6b63411326b.png align="center")

* Search for the created command document name in the command document search bar and select it.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721645734878/649d731e-283e-4613-a87c-ac81d8e264e7.png align="center")

* Select the target you registered earlier in the maintenance window. Set the concurrency value to 1 (tasks run on one instance at a time) and the error threshold value to 1 (task stops if one instance fails). This ensures sequential execution and halts on errors for accurate control.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721646080483/70c9b985-337f-4b95-af9e-34e67481e4a1.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721646676681/c2d85a7a-45cf-42e7-b1d3-10e3da04449f.png align="center")

* After registering the task, you can view and check the details, including description, tasks, and targets, as shown in the screenshots below.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721647555556/19187873-6206-4b9b-a69e-a5a86dd638f2.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721647575040/4b9af059-34fc-495c-ad15-6f5400771b51.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721647597738/5a404670-90ab-428a-8679-3603a0654863.png align="center")

* Check the history to verify the success or failure status of the cleanup commands executed on EC2 instances during the configured time period, as shown in the screenshot below.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721648262394/1c9c972d-1248-45de-9e32-51ff9d11ccc2.png align="center")

---

> <div data-node-type="callout">
> <div data-node-type="callout-emoji">💡</div>
> <div data-node-type="callout-text"><strong><em>Note:</em></strong><em> Check Docker overlays and system storage using </em><code>df -h</code><em> and monitor memory usage with </em><code>free -h</code><em> on your EC2 instances </em>both before and after executing the cleanup commands.<em> Automating cleanup commands helps prevent hitting storage and memory limits, which could cause loss of EC2 server access and poor performance due to full storage, memory, and CPU usage.</em></div>
> </div>
