Class: GDKBox::Docker

Inherits:
Object
  • Object
show all
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.

Instance Method Summary collapse

Constructor Details

#initialize(shell: Shell.new) ⇒ Docker

Returns a new instance of Docker.



10
11
12
# File 'lib/gdkbox/docker.rb', line 10

def initialize(shell: Shell.new)
  @shell = shell
end

Instance Method Details

#available?Boolean

Returns:

  • (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).



50
51
52
# File 'lib/gdkbox/docker.rb', line 50

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.



40
41
42
43
44
45
46
47
# File 'lib/gdkbox/docker.rb', line 40

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

#list_namesObject

Names of all gdkbox-managed containers, derived from labels.



78
79
80
81
82
83
84
85
86
87
# File 'lib/gdkbox/docker.rb', line 78

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) ⇒ Object



18
19
20
# File 'lib/gdkbox/docker.rb', line 18

def pull(image)
  @shell.run!("docker", "pull", image)
end

#rm(name, force: true) ⇒ Object



62
63
64
65
66
67
# File 'lib/gdkbox/docker.rb', line 62

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.



23
24
25
26
27
28
29
30
31
# File 'lib/gdkbox/docker.rb', line 23

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



54
55
56
# File 'lib/gdkbox/docker.rb', line 54

def start(name)
  @shell.run!("docker", "start", name)
end

#state(name) ⇒ Object

The container's lifecycle state, or :absent if it does not exist.



70
71
72
73
74
75
# File 'lib/gdkbox/docker.rb', line 70

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



58
59
60
# File 'lib/gdkbox/docker.rb', line 58

def stop(name)
  @shell.run!("docker", "stop", name)
end