(in-package #:nekod.docker) (defun list-volumes (sock) "List all Docker volumes on this host. Returns JSON body (Volumes array + Warnings) as a string." (multiple-value-bind (status body) (docker-get sock "/volumes") (if (= status 200) body (error 'nekod:docker-api-error :message body :status-code status :endpoint "/volumes")))) (defun inspect-volume (sock name) "Inspect a Docker volume by name. Returns full JSON metadata as a string." (multiple-value-bind (status body) (docker-get sock (format nil "/volumes/~a" name)) (if (= status 200) body (error 'nekod:docker-api-error :message body :status-code status :endpoint (format nil "/volumes/~a" name))))) (defun create-volume (sock name &key (driver "local") driver-opts labels) "Create a Docker volume. name — volume name driver — storage driver, defaults to \"local\" driver-opts — alist of driver-specific options labels — alist of string key-value metadata pairs Returns JSON body (contains volume metadata) as a string." (let ((body (format nil "{\"Name\":~s,\"Driver\":~s,\"DriverOpts\":{~{~s:~s~^,~}},\"Labels\":{~{~s:~s~^,~}}}" name driver (loop for (k . v) in (or driver-opts '()) nconc (list k v)) (loop for (k . v) in (or labels '()) nconc (list k v))))) (multiple-value-bind (status resp) (docker-post sock "/volumes/create" body) (if (= status 201) resp (error 'nekod:docker-api-error :message resp :status-code status :endpoint "/volumes/create"))))) (defun remove-volume (sock name &optional (force nil)) "Remove a Docker volume by name. force — forcefully remove even if in use (Docker 1.9+). Returns t on success." (multiple-value-bind (status body) (docker-delete sock (format nil "/volumes/~a?force=~a" name (if force "true" "false"))) (if (= status 204) t (error 'nekod:docker-api-error :message body :status-code status :endpoint (format nil "/volumes/~a" name))))) (defun prune-volumes (sock) "Remove all unused Docker volumes (not referenced by any container). WARNING: data loss is permanent. Returns JSON summary (SpaceReclaimed) as a string." (multiple-value-bind (status body) (docker-post sock "/volumes/prune") (if (= status 200) body (error 'nekod:docker-api-error :message body :status-code status :endpoint "/volumes/prune"))))