Class: GDKBox::Docker
- Inherits:
-
Object
- Object
- GDKBox::Docker
- Defined in:
- lib/gdkbox/docker.rb
Overview
A small, focused wrapper around the docker CLI.
Only the verbs gdkbox needs are exposed. Every container created by gdkbox
is tagged with the gdkbox=true label plus a gdkbox.name label so they
can be discovered later without relying on local metadata alone.
Defined Under Namespace
Classes: PullProgress
Instance Method Summary collapse
- #available? ⇒ Boolean
-
#cp_into(name, src, dest) ⇒ Object
Copy a host path into a container at dest (a full destination path).
-
#exec(name, script, user: nil, workdir: nil, env: {}, input: nil, check: true) ⇒ Object
Run a bash script inside a running container.
-
#image_exists?(image) ⇒ Boolean
Whether the image is already present locally.
-
#initialize(shell: Shell.new) ⇒ Docker
constructor
A new instance of Docker.
-
#list_names ⇒ Object
Names of all gdkbox-managed containers, derived from labels.
-
#pull(image, &block) ⇒ Object
Pull an image.
- #rm(name, force: true) ⇒ Object
-
#run_container(name:, image:, publish: [], labels: {}, env: {}, args: []) ⇒ Object
Start a detached container, returning its id.
- #start(name) ⇒ Object
-
#state(name) ⇒ Object
The container's lifecycle state, or :absent if it does not exist.
- #stop(name) ⇒ Object
Constructor Details
Instance Method Details
#available? ⇒ Boolean
14 15 16 |
# File 'lib/gdkbox/docker.rb', line 14 def available? !@shell.which("docker").nil? end |
#cp_into(name, src, dest) ⇒ Object
Copy a host path into a container at dest (a full destination path).
223 224 225 |
# File 'lib/gdkbox/docker.rb', line 223 def cp_into(name, src, dest) @shell.run!("docker", "cp", src, "#{name}:#{dest}") end |
#exec(name, script, user: nil, workdir: nil, env: {}, input: nil, check: true) ⇒ Object
Run a bash script inside a running container. The script is passed to
bash -lc as a single argument; values that vary (keys, usernames) are
passed through the environment to avoid quoting pitfalls.
When check is true (the default) a non-zero exit raises; pass check: false to capture output and exit status without raising, which is what agent runs want so the caller can surface the agent's output either way.
213 214 215 216 217 218 219 220 |
# File 'lib/gdkbox/docker.rb', line 213 def exec(name, script, user: nil, workdir: nil, env: {}, input: nil, check: true) cmd = ["docker", "exec", "-i"] cmd.push("-u", user) if user cmd.push("-w", workdir) if workdir env.each { |key, value| cmd.push("-e", "#{key}=#{value}") } cmd.push(name, "bash", "-lc", script) check ? @shell.run!(*cmd, input: input) : @shell.run(*cmd, input: input) end |
#image_exists?(image) ⇒ Boolean
Whether the image is already present locally.
19 20 21 |
# File 'lib/gdkbox/docker.rb', line 19 def image_exists?(image) @shell.run("docker", "image", "inspect", image).success? end |
#list_names ⇒ Object
Names of all gdkbox-managed containers, derived from labels.
251 252 253 254 255 256 257 258 259 260 |
# File 'lib/gdkbox/docker.rb', line 251 def list_names result = @shell.run( "docker", "ps", "-a", "--filter", "label=gdkbox=true", "--format", '{{index .Labels "gdkbox.name"}}' ) return [] unless result.success? result.stdout.split("\n").map(&:strip).reject(&:empty?) end |
#pull(image, &block) ⇒ Object
Pull an image. With no block the pull runs quietly and the (captured)
Result is returned. With a block the pull is streamed and the block is
called with a PullProgress after every line of docker pull output, so a
caller can drive a progress bar. Raises CommandError on a non-zero exit.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/gdkbox/docker.rb', line 27 def pull(image, &block) return @shell.run!("docker", "pull", image) unless block tracker = PullProgress.new result = @shell.stream_tty("docker", "pull", image) do |line| tracker.ingest(line) block.call(tracker) end unless result.success? raise CommandError.new(["docker", "pull", image], result.status, result.stderr) end result end |
#rm(name, force: true) ⇒ Object
235 236 237 238 239 240 |
# File 'lib/gdkbox/docker.rb', line 235 def rm(name, force: true) cmd = ["docker", "rm"] cmd << "-f" if force cmd << name @shell.run(*cmd) end |
#run_container(name:, image:, publish: [], labels: {}, env: {}, args: []) ⇒ Object
Start a detached container, returning its id.
196 197 198 199 200 201 202 203 204 |
# File 'lib/gdkbox/docker.rb', line 196 def run_container(name:, image:, publish: [], labels: {}, env: {}, args: []) cmd = ["docker", "run", "-d", "--name", name] labels.each { |key, value| cmd.push("--label", "#{key}=#{value}") } env.each { |key, value| cmd.push("-e", "#{key}=#{value}") } publish.each { |mapping| cmd.push("-p", mapping) } cmd << image cmd.concat(args) @shell.run!(*cmd).stdout.strip end |
#start(name) ⇒ Object
227 228 229 |
# File 'lib/gdkbox/docker.rb', line 227 def start(name) @shell.run!("docker", "start", name) end |
#state(name) ⇒ Object
The container's lifecycle state, or :absent if it does not exist.
243 244 245 246 247 248 |
# File 'lib/gdkbox/docker.rb', line 243 def state(name) result = @shell.run("docker", "inspect", "-f", "{{.State.Status}}", name) return :absent unless result.success? result.stdout.strip.to_sym end |
#stop(name) ⇒ Object
231 232 233 |
# File 'lib/gdkbox/docker.rb', line 231 def stop(name) @shell.run!("docker", "stop", name) end |