Class: Cutlass::ContainerBoot
- Inherits:
-
Object
- Object
- Cutlass::ContainerBoot
- Defined in:
- lib/cutlass/container_boot.rb
Overview
Boots containers and tears ‘em down
Has a single method ContainerBoot#call which returns an instance of
boot = ContainerBoot.new(image_id: @image.id)
boot.call do |container_control|
container_control.class # => ContainerControl
container_control.bash_exec("pwd")
end
The number one reason to boot a container is to be able to exercise a booted server from within the container. To do this you need to tell docker want port to expose inside of the container. Docker will expose that port and bind it to a free port on the “host” i.e. your local machine. From there you can make queries to various docker ports:
boot = ContainerBoot.new(image_id: @image.id, expose_ports: [8080])
boot.call do |container_control|
local_port = container_control.get_host_port(8080)
`curl localhost:#{local_port}`
end
Note: Booting a container only works if the image has an ENTRYPOINT that does not exit.
Note: Running ‘bash_exec` commands from this context gives you a raw access to the container. It does not execute the container’s entrypoint. That means if you’re running inside of a CNB image, that env vars won’t be set and the directory might be different.
Instance Method Summary collapse
- #call ⇒ Object
-
#initialize(image_id:, env: {}, expose_ports: [], memory: nil) ⇒ ContainerBoot
constructor
A new instance of ContainerBoot.
Constructor Details
#initialize(image_id:, env: {}, expose_ports: [], memory: nil) ⇒ ContainerBoot
Returns a new instance of ContainerBoot.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/cutlass/container_boot.rb', line 36 def initialize(image_id:, env: {}, expose_ports: [], memory: nil) @expose_ports = Array(expose_ports) config = { "Image" => image_id, "ExposedPorts" => {}, "HostConfig" => { "PortBindings" => {} } } port_bindings = config["HostConfig"]["PortBindings"] @expose_ports.each do |port| config["ExposedPorts"]["#{port}/tcp"] = {} # If we do not specify a port, Docker will grab a random unused one: port_bindings["#{port}/tcp"] = [{"HostPort" => ""}] end config["Memory"] = memory.to_i if memory config["Env"] = env.map { |k, v| "#{k}=#{v}" } @container = Docker::Container.create(config) end |
Instance Method Details
#call ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/cutlass/container_boot.rb', line 60 def call raise "Must call with a block" unless block_given? @container.start! puts @container.logs(stdout: 1) if Cutlass.debug? puts @container.logs(stderr: 1) if Cutlass.debug? yield ContainerControl.new(@container, ports: @expose_ports) rescue => error raise error, <<~EOM message #{error.} boot stdout: #{@container.logs(stdout: 1)} boot stderr: #{@container.logs(stderr: 1)} EOM ensure @container&.delete(force: true) end |