I've been running my swarm for a while, and now it's time to start cleaning up unused objects.

By unused I mean things like images, volumes, networks, etc. It's easy enough to do on a single node, ssh into it and run docker system prune --all --volumes --force. But that sucks when you have multiple nodes. Especially when you want to do this automatically. The --volumes is there to clean up the unused volumes. Without it, the prune will not remove them, even though you have the --all parameter.

Here's one way of running of a docker command across all your nodes in a swarm. It seems a bit hacky and is not a simple one-liner. But it works. Basically, you create a container, mount the docker socket, and run the docker command. Set the deploy:mode to global so it runs on all nodes. Be sure to set the restart_policy to something. If you don't, it'll run the command in an endless loop. I set condition to none because I didn't want this particular task to auto-restart.

Without further ado, here's my docker-compose.yml:

version: '3.7'
services:
  system-prune:
    image: docker
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    command: docker system prune --all --force --volumes
    deploy:
      mode: global
      restart_policy:
        condition: none

Run it by issuing docker stack deploy -c docker-compose.yml tasks. Unless absolutely necessary I recommend using a separate stack for your tasks and not run one a stack you already have created. The primary reason, you most likely don't want to accidentally clobber a service that is actually handling traffic if you name your task the same as a running service.

Now I'm putting this in a cron job on my master node so it will run every day. Happy dev-oping!