This uses the HTTP REST API from the container engines to run. See the API docs for more details:
- The Swagger 2.0 specs are downloaded and parsed into relevant edn files.
- They are categorized by engine type and stored into the resources with version numbers.
- The code doing this can be found here.
- The library is then published with only the parsed and optimized edn to be as lean as possible at runtime have optimal performance.
- The main code then loads the corresponding edn file by version and performs the necessary calls to the engine.
This library aims to be a as thin layer as possible between you and the container engine. This consists of following public functions:
Lists the categories of operations supported.
(c/categories :docker "v1.41") ; for docker
(c/categories :podman "v3.2.3") ; for podman
#_=> (:system
:exec
:images
:secrets
:events
:_ping
:containers
:auth
:tasks
:volumes
:networks
:build
:nodes
:commit
:plugins
:info
:swarm
:distribution
:version
:services
:configs
:session)
Some engines like podman support multiple APIs, for example it supports both podman and docker APIs.
Hence the categories would be namespaced to show which belong to what engine.
eg. :containers
for docker and :libpod/containers
for podman APIs.
Connect to the UNIX socket and create a client scoped to the operations of a given category.
(def images (c/client {:engine :podman
:category :libpod/images
:conn {:uri "unix:///var/run/podman.sock"}
:version "v3.2.3"}))
Using a timeout for the connections. Some actions can take quite a long time so set the timeout accordingly. When you don't provide timeouts then there will be no timeout on the client side.
(def ping (c/client {:engine :docker
:category :_ping
:version "v1.41"
:conn {:uri "unix:///var/run/docker.sock"
:connect-timeout 10
:read-timeout 30000
:write-timeout 30000
:call-timeout 30000}}}))
Alternatively if connecting to a remote engine over TCP supply the :uri
as http://your.engine.host:2376
.
NOTE: unix://
, http://
, tcp://
and https://
are the currently supported protocols.
Lists the supported ops by a client.
(c/ops images)
#_=> (:ImageDeleteLibpod
:ImagePushLibpod
:ImageExportLibpod
:ImageHistoryLibpod
:ImageDeleteAllLibpod
:ImageInspectLibpod
:ImageGetLibpod
:ImageUntagLibpod
:ImageTagLibpod
:ImageChangesLibpod
:ImageListLibpod
:ImageLoadLibpod
:ImageTreeLibpod
:ImagePruneLibpod
:ImageSearchLibpod
:ImageImportLibpod
:ImageExistsLibpod
:ImagePullLibpod)
Returns the summary and the doc URL of an operation in a client.
(c/doc images :ImageList)
#_=> {:summary
"List Images\nReturns a list of images on the server. Note that it uses a different, smaller representation of an image than inspecting a single image.",
:doc-url "https://docs.docker.com/engine/api/v1.41/#operation/ImageList"}
Invokes an operation via the client and a given operation map and returns the result data.
; Pulls the busybox:musl image from Docker hub
(c/invoke images {:op :ImageCreate
:params {:fromImage "busybox:musl"}})
; Creates a container named conny from it
(c/invoke containers {:op :ContainerCreate
:params {:name "conny"}
:data {:Image "busybox:musl"
:Cmd "ls"}})
The operation map is of the following structure:
{:op :NameOfOp
:params {:param-1 "value1"
:param-2 true}
:data {map or stream or raw data to be passed. Corresponds to the Request Body in the docs}}
Takes an optional key as
. Defaults to :data
. Returns an InputStream if passed as :stream
, the raw underlying network socket if passed as :socket
. :stream
is useful for streaming responses like logs, events etc, which run till the container is up. :socket
is useful for events when bidirectional streams are returned by docker in operations like :ContainerAttach
.
{:op :NameOfOp
:params {:param-1 "value1"
:param-2 true}
:as :stream}
Note: :socket
is unsupported on the babashka runtime for now.
Takes another optional key :throw-exceptions
. Defaults to false
. If set to true will throw an exception for exceptional status codes from the Docker API i.e. status >= 400
. Throws an java.lang.RuntimeException
with the message.
{:op :NameOfOp
:throw-exceptions true}
In general if any param is documented to take a file or a binary string, pass an input-stream to it. This would not only make it more efficient but should keep the encoding correct. For example: https://docs.docker.com/engine/api/v1.41/#operation/ImageLoad