This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-05-29
Channels
- # announcements (1)
- # babashka (83)
- # beginners (67)
- # chlorine-clover (22)
- # cider (11)
- # circleci (6)
- # clj-kondo (12)
- # cljs-dev (137)
- # cljsrn (15)
- # clojure (124)
- # clojure-europe (40)
- # clojure-italy (1)
- # clojure-nl (3)
- # clojure-norway (1)
- # clojure-serbia (3)
- # clojure-spec (19)
- # clojure-uk (14)
- # clojuredesign-podcast (5)
- # clojurescript (80)
- # conjure (49)
- # core-async (62)
- # cursive (18)
- # datascript (1)
- # datomic (64)
- # docker (28)
- # emacs (20)
- # figwheel-main (249)
- # fulcro (95)
- # graalvm (2)
- # jobs-discuss (11)
- # joker (2)
- # juxt (4)
- # lambdaisland (9)
- # leiningen (1)
- # meander (14)
- # mount (6)
- # off-topic (16)
- # pathom (46)
- # re-frame (35)
- # reagent (6)
- # reitit (5)
- # shadow-cljs (28)
- # spacemacs (6)
- # sql (18)
- # tools-deps (26)
- # vim (8)
- # xtdb (23)
- # yada (1)
I'm in the process of migrating to version 1.0.1 of clj-docker-client and am having issues understanding how exec works now. I'm running this:
(docker/invoke
client
{:op :ContainerExec
:params {:id "couchbase"
:execConfig {:Cmd [,,,]}}})
Which returns an Id, but I don't think this has run anything in the container. This is the function that I used to have before upgrading:
(defn exec
"Run a command inside a Docker container"
[^DockerClient conn id cmdvec]
(let [^ExecStartResultCallback callback (ExecStartResultCallback. System/out System/err)
^ExecCreateCmd exec-cmd (-> conn
(.execCreateCmd id)
(.withAttachStdout true)
(.withAttachStderr true)
(.withCmd (into-array String cmdvec)))]
(-> conn
(.execStartCmd (.getId ^ExecCreateCmdResponse (.exec exec-cmd)))
^ExecStartResultCallback (.exec callback)
.awaitCompletion)))
Ok, I think I've got it. The invoke
above creates an Exec instance that must be executed, and the result is a stream that can be watched if desired. Here's the working function:
(defn exec
"Run command inside docker container"
[client image-id cmd]
(let [instance (docker/invoke client
{:op :ContainerExec
:params {:id image-id
:execConfig {:AttachStdout true
:Cmd cmd}}})
exec-client (docker/client {:category :exec
:conn {:uri "unix:///var/run/docker.sock"}})]
(docker/invoke exec-client
{:as :stream
:op :ExecStart
:params {:id (:Id instance)
:execStartConfig {}}})))
I did have to create an :exec
client, I don't know if there's a way around that.
It is a bit odd that I can create the Exec instance with the :containers
client, but not start it. ¯\(ツ)/¯
@U0JAE119P yes the way youre doing it is correct. The reasoning is that clj-docker-client is now a very thin layer on top of docker's REST API, documented here
https://docs.docker.com/engine/api/v1.40
To create the exec instance the api is /containers/{id}/exec
hence uses the containers client: https://docs.docker.com/engine/api/v1.40/#operation/ContainerExec
To start it the API is /exec/{id}/start
: https://docs.docker.com/engine/api/v1.40/#operation/ExecStart
the categories are the prefixes in the API paths: /images, /containers, /_ping etc
Right, that's how I was able to piece it together. Thanks for following up!
you can have a look at the (maybe more more searchable) vendored swagger YAML: https://github.com/into-docker/clj-docker-client/blob/master/resources/clj_docker_client/api/latest.yaml
hopefully this simplification and reducing layers between you and docker helps! thats what allowed it to reach 1.0 too 😄
Yes, that does make it much much simpler. It's straightforward to make the connection. Although, I did have a question regarding (docker/doc ,,,)
For example:
(docker/doc client :ContainerExec)
=>
{:doc "Create an exec instance\nRun a command inside a running container.",
:params ({:name "execConfig"} {:name "id", :type "string"})}
Id tells me it's a type string, but execConfig doesn't.
Going to the YAML file, I was able to see that it was an object type and was able to see which keys were needed, is there a different way to drill down?
yeah thats something ive been planning to work on, do a proper spec based info and data generation: https://github.com/into-docker/clj-docker-client/issues/15
this is the best it can for now unfortunately 😞
So if it's missing a type, it is implicitly object?
finding it hard to find time for this, some PRs would be really swiftly merged though! 😄
Ah gotcha
you can try to use REBL if you want
you can create a client and use REBL to drill down in the UI
better doc and help IMO
I'll have to give that a shot, I've yet to try out REBL 😛
you can very very minutely inspect the client thats created here 😄
Sorry it took me this long to get up to speed with the latest version, it's much much nicer now 🙂 No more dealing with Java interop, just data!
awesome! hope its useful
this is how REBL drilling down looks like 😄
oooo nice!