Class: Testcontainers::DockerContainer
- Inherits:
-
Object
- Object
- Testcontainers::DockerContainer
- Defined in:
- lib/testcontainers/docker_container.rb
Overview
The DockerContainer class is used to manage Docker containers. It provides an interface to create, start, stop, and manipulate containers using the Docker API.
Instance Attribute Summary collapse
-
#_container ⇒ Docker::Container?
readonly
the underlying Docker::Container object.
-
#_id ⇒ String?
readonly
the container’s ID.
-
#command ⇒ Array<String>?
the command to run in the container.
-
#entrypoint ⇒ Array<String>?
the entrypoint to run in the container.
-
#env ⇒ Array<String>?
an array of environment variables for the container in the format KEY=VALUE.
-
#exposed_ports ⇒ Hash?
a hash mapping exposed container ports to an empty hash (used for Docker API compatibility).
-
#filesystem_binds ⇒ Array<String>?
an array of strings representing bind mounts from the host to the container.
-
#healthcheck ⇒ Hash?
a hash of healthcheck options for the container.
-
#image ⇒ String
the container’s image name.
-
#labels ⇒ Hash?
a hash of labels to be applied to the container.
-
#logger ⇒ Logger
a logger instance for the container.
-
#name ⇒ String
the container’s name.
-
#port_bindings ⇒ Hash?
a hash mapping container ports to host port bindings (used for Docker API compatibility).
-
#volumes ⇒ Hash?
a hash mapping volume paths in the container to an empty hash (used for Docker API compatibility).
-
#wait_for ⇒ Object
Returns the value of attribute wait_for.
-
#working_dir ⇒ String?
the working directory for the container.
Instance Method Summary collapse
-
#add_env(env_or_key, value = nil) ⇒ Array<String>
Add environment variables to the container configuration.
-
#add_exposed_port(port) ⇒ Hash
Add an exposed port to the container configuration.
-
#add_exposed_ports(*ports) ⇒ Hash
Add multiple exposed ports to the container configuration.
-
#add_filesystem_bind(host_or_hash, container_path = nil, mode = "rw") ⇒ Array<String>
Add a filesystem bind to the container configuration.
-
#add_filesystem_binds(filesystem_binds) ⇒ Array<String>
Add multiple filesystem binds to the container configuration.
-
#add_fixed_exposed_port(container_port, host_port = nil) ⇒ Hash
Add a fixed exposed port to the container configuration.
-
#add_fixed_exposed_ports(port_mappings = {}) ⇒ Hash
Add multiple fixed exposed ports to the container configuration.
-
#add_healthcheck(options = {}) ⇒ Hash
Adds a healthcheck to the container.
-
#add_label(label, value) ⇒ Hash
Add a label to the container configuration.
-
#add_labels(labels) ⇒ Hash
Add multiple labels to the container configuration.
-
#add_volume(volume) ⇒ Hash
Add a volume to the container configuration.
-
#add_volumes(volumes = []) ⇒ Hash
Add multiple volumes to the container configuration.
-
#add_wait_for(method = nil, *args, **kwargs, &block) ⇒ Proc
Add a wait_for strategy to the container configuration.
-
#copy_file_from_container(container_path, host_path_or_io) ⇒ String
Copies a file from the container to the host.
-
#copy_file_to_container(container_path, host_path_or_io) ⇒ self
Copies a IO object or a file from the host to the container.
-
#created_at ⇒ String?
Returns the container’s created at timestamp.
-
#dead? ⇒ Boolean
Returns whether the container is running.
-
#exec(cmd, options = {}, &block) ⇒ Array, Integer
Executes a command in the container.
-
#exists? ⇒ Boolean
Returns whether the container exists.
-
#exited? ⇒ Boolean
Returns whether the container is stopped.
-
#first_mapped_port ⇒ Integer
Returns the container’s first mapped port.
-
#get_env(key) ⇒ String?
Returns the value for the given environment variable.
-
#healthy? ⇒ Boolean, false
Returns whether the container is healthy.
-
#host ⇒ String
Returns the container’s host.
-
#info ⇒ Hash?
Returns the container’s info (inspect).
-
#initialize(image, name: nil, command: nil, entrypoint: nil, exposed_ports: nil, image_create_options: {}, port_bindings: nil, volumes: nil, filesystem_binds: nil, env: nil, labels: nil, working_dir: nil, healthcheck: nil, wait_for: nil, logger: Testcontainers.logger) ⇒ DockerContainer
constructor
Initializes a new DockerContainer instance.
-
#inside_container? ⇒ Boolean
Returns whether this is running inside a container.
-
#kill(signal: "SIGKILL") ⇒ DockerContainer?
Kills the container with the specified signal.
-
#logs(stdout: true, stderr: true) ⇒ Array<String>
Returns the container’s logs.
-
#mapped_port(port) ⇒ Integer
Returns the mapped host port for the given container port.
-
#mount_names ⇒ Array<String>
Returns the container’s mount names.
-
#mounts ⇒ Array<Hash>
Returns the container’s mounts.
-
#paused? ⇒ Boolean
Returns whether the container is paused.
-
#read_file(path) ⇒ String
Reads the contents of a file inside the container.
-
#remove(options = {}) ⇒ DockerContainer?
(also: #delete)
Removes the container.
-
#restart ⇒ DockerContainer
Restarts the container.
-
#restarting? ⇒ Boolean
Returns whether the container is restarting.
-
#running? ⇒ Boolean, false
Returns whether the container is running.
-
#start ⇒ DockerContainer
(also: #enter)
Starts the container.
-
#status ⇒ String
Returns the container’s status.
-
#stop(force: false) ⇒ DockerContainer
(also: #exit)
Stops the container.
-
#stop! ⇒ DockerContainer
Stops the container forcefully.
-
#store_file(path, contents) ⇒ Object
Writes the contents of a file inside the container.
-
#supports_healthcheck? ⇒ Boolean
Returns whether the container supports healthchecks.
-
#use {|DockerContainer| ... } ⇒ DockerContainer
Starts the container, yields the container instance to the block, and stops the container.
-
#wait_for_healthcheck(timeout: 60, interval: 0.1) ⇒ Boolean
Waits for the container to be healthy.
-
#wait_for_http(timeout: 60, interval: 0.1, path: "/", container_port: 80, https: false, status: 200) ⇒ Boolean
Waits for the container to respond to HTTP requests.
-
#wait_for_logs(matcher, timeout: 60, interval: 0.1) ⇒ Boolean
Waits for the container logs to match the given regex.
-
#wait_for_tcp_port(port, timeout: 60, interval: 0.1) ⇒ Boolean
Waits for the container to open the given port.
-
#with(options) ⇒ DockerContainer
Set options for the container configuration using “with_” methods.
-
#with_command(*parts) ⇒ DockerContainer
Set the command for the container.
-
#with_entrypoint(*parts) ⇒ DockerContainer
Set the entrypoint for the container.
-
#with_env(env_or_key, value = nil) ⇒ DockerContainer
Sets the container’s environment variables.
-
#with_exposed_port(port) ⇒ DockerContainer
Adds a single exposed port to the container.
-
#with_exposed_ports(*ports) ⇒ DockerContainer
Adds exposed ports to the container.
-
#with_filesystem_binds(filesystem_binds) ⇒ DockerContainer
Adds filesystem binds to the container.
-
#with_fixed_exposed_port(container_port, host_port = nil) ⇒ DockerContainer
(also: #with_port_binding)
Adds a fixed exposed port to the container.
-
#with_healthcheck(options = {}) ⇒ DockerContainer
Adds a healthcheck to the container.
-
#with_label(label, value) ⇒ DockerContainer
Adds a label to the container.
-
#with_labels(labels) ⇒ DockerContainer
Adds labels to the container.
-
#with_name(name) ⇒ DockerContainer
Set the name of the container.
-
#with_volumes(volumes = {}) ⇒ DockerContainer
Adds volumes to the container.
-
#with_wait_for(method = nil, *args, **kwargs, &block) ⇒ DockerContainer
Add a wait_for strategy to the container configuration.
-
#with_working_dir(working_dir) ⇒ DockerContainer
Sets the container’s working directory.
Constructor Details
#initialize(image, name: nil, command: nil, entrypoint: nil, exposed_ports: nil, image_create_options: {}, port_bindings: nil, volumes: nil, filesystem_binds: nil, env: nil, labels: nil, working_dir: nil, healthcheck: nil, wait_for: nil, logger: Testcontainers.logger) ⇒ DockerContainer
Initializes a new DockerContainer instance.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/testcontainers/docker_container.rb', line 41 def initialize(image, name: nil, command: nil, entrypoint: nil, exposed_ports: nil, image_create_options: {}, port_bindings: nil, volumes: nil, filesystem_binds: nil, env: nil, labels: nil, working_dir: nil, healthcheck: nil, wait_for: nil, logger: Testcontainers.logger) @image = image @name = name @command = command @entrypoint = entrypoint @exposed_ports = add_exposed_ports(exposed_ports) if exposed_ports @image_create_options = @port_bindings = add_fixed_exposed_ports(port_bindings) if port_bindings @volumes = add_volumes(volumes) if volumes @env = add_env(env) if env @filesystem_binds = add_filesystem_binds(filesystem_binds) if filesystem_binds @labels = add_labels(labels) if labels @working_dir = working_dir @healthcheck = add_healthcheck(healthcheck) if healthcheck @wait_for = add_wait_for(wait_for) @logger = logger @_container = nil @_id = nil @_created_at = nil end |
Instance Attribute Details
#_container ⇒ Docker::Container? (readonly)
the underlying Docker::Container object
21 22 23 |
# File 'lib/testcontainers/docker_container.rb', line 21 def _container @_container end |
#_id ⇒ String? (readonly)
the container’s ID
21 22 23 |
# File 'lib/testcontainers/docker_container.rb', line 21 def _id @_id end |
#command ⇒ Array<String>?
the command to run in the container
21 22 23 |
# File 'lib/testcontainers/docker_container.rb', line 21 def command @command end |
#entrypoint ⇒ Array<String>?
the entrypoint to run in the container
21 22 23 |
# File 'lib/testcontainers/docker_container.rb', line 21 def entrypoint @entrypoint end |
#env ⇒ Array<String>?
an array of environment variables for the container in the format KEY=VALUE
21 22 23 |
# File 'lib/testcontainers/docker_container.rb', line 21 def env @env end |
#exposed_ports ⇒ Hash?
a hash mapping exposed container ports to an empty hash (used for Docker API compatibility)
21 22 23 |
# File 'lib/testcontainers/docker_container.rb', line 21 def exposed_ports @exposed_ports end |
#filesystem_binds ⇒ Array<String>?
an array of strings representing bind mounts from the host to the container
21 22 23 |
# File 'lib/testcontainers/docker_container.rb', line 21 def filesystem_binds @filesystem_binds end |
#healthcheck ⇒ Hash?
a hash of healthcheck options for the container
21 22 23 |
# File 'lib/testcontainers/docker_container.rb', line 21 def healthcheck @healthcheck end |
#image ⇒ String
the container’s image name
21 22 23 |
# File 'lib/testcontainers/docker_container.rb', line 21 def image @image end |
#labels ⇒ Hash?
a hash of labels to be applied to the container
21 22 23 |
# File 'lib/testcontainers/docker_container.rb', line 21 def labels @labels end |
#logger ⇒ Logger
a logger instance for the container
21 22 23 |
# File 'lib/testcontainers/docker_container.rb', line 21 def logger @logger end |
#name ⇒ String
the container’s name
21 22 23 |
# File 'lib/testcontainers/docker_container.rb', line 21 def name @name end |
#port_bindings ⇒ Hash?
a hash mapping container ports to host port bindings (used for Docker API compatibility)
21 22 23 |
# File 'lib/testcontainers/docker_container.rb', line 21 def port_bindings @port_bindings end |
#volumes ⇒ Hash?
a hash mapping volume paths in the container to an empty hash (used for Docker API compatibility)
21 22 23 |
# File 'lib/testcontainers/docker_container.rb', line 21 def volumes @volumes end |
#wait_for ⇒ Object
Returns the value of attribute wait_for.
22 23 24 |
# File 'lib/testcontainers/docker_container.rb', line 22 def wait_for @wait_for end |
#working_dir ⇒ String?
the working directory for the container
21 22 23 |
# File 'lib/testcontainers/docker_container.rb', line 21 def working_dir @working_dir end |
Instance Method Details
#add_env(env_or_key, value = nil) ⇒ Array<String>
Add environment variables to the container configuration.
72 73 74 75 76 77 |
# File 'lib/testcontainers/docker_container.rb', line 72 def add_env(env_or_key, value = nil) @env ||= [] new_env = process_env_input(env_or_key, value) @env.concat(new_env) @env end |
#add_exposed_port(port) ⇒ Hash
Add an exposed port to the container configuration.
83 84 85 86 87 88 89 90 |
# File 'lib/testcontainers/docker_container.rb', line 83 def add_exposed_port(port) port = normalize_port(port) @exposed_ports ||= {} @port_bindings ||= {} @exposed_ports[port] ||= {} @port_bindings[port] ||= [{"HostPort" => ""}] @exposed_ports end |
#add_exposed_ports(*ports) ⇒ Hash
Add multiple exposed ports to the container configuration.
96 97 98 99 100 101 102 103 |
# File 'lib/testcontainers/docker_container.rb', line 96 def add_exposed_ports(*ports) ports = ports.first if ports.first.is_a?(Array) ports.each do |port| add_exposed_port(port) end @exposed_ports end |
#add_filesystem_bind(host_or_hash, container_path = nil, mode = "rw") ⇒ Array<String>
Add a filesystem bind to the container configuration.
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/testcontainers/docker_container.rb', line 162 def add_filesystem_bind(host_or_hash, container_path = nil, mode = "rw") @filesystem_binds ||= [] if host_or_hash.is_a?(Hash) host_path, container_path = host_or_hash.first elsif host_or_hash.is_a?(String) if container_path host_path = host_or_hash else host_path, container_path, mode = host_or_hash.split(":") mode ||= "rw" end else raise ArgumentError, "Invalid input format for add_filesystem_bind" end @filesystem_binds << "#{host_path}:#{container_path}:#{mode}" add_volume(container_path) @filesystem_binds end |
#add_filesystem_binds(filesystem_binds) ⇒ Array<String>
Add multiple filesystem binds to the container configuration.
187 188 189 190 191 192 193 194 |
# File 'lib/testcontainers/docker_container.rb', line 187 def add_filesystem_binds(filesystem_binds) @filesystem_binds ||= [] binds = normalize_filesystem_binds(filesystem_binds) binds.each do |bind| add_filesystem_bind(*bind) end @filesystem_binds end |
#add_fixed_exposed_port(container_port, host_port = nil) ⇒ Hash
Add a fixed exposed port to the container configuration.
111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/testcontainers/docker_container.rb', line 111 def add_fixed_exposed_port(container_port, host_port = nil) if container_port.is_a?(Hash) container_port, host_port = container_port.first end container_port = normalize_port(container_port) @exposed_ports ||= {} @port_bindings ||= {} @exposed_ports[container_port] = {} @port_bindings[container_port] = [{"HostPort" => host_port.to_s}] @port_bindings end |
#add_fixed_exposed_ports(port_mappings = {}) ⇒ Hash
Add multiple fixed exposed ports to the container configuration.
128 129 130 131 132 133 |
# File 'lib/testcontainers/docker_container.rb', line 128 def add_fixed_exposed_ports(port_mappings = {}) port_mappings.each do |container_port, host_port| add_fixed_exposed_port(container_port, host_port) end @port_bindings end |
#add_healthcheck(options = {}) ⇒ Hash
Adds a healthcheck to the container.
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/testcontainers/docker_container.rb', line 226 def add_healthcheck( = {}) test = [:test] if test.nil? @healthcheck = {"Test" => ["NONE"]} return @healthcheck end interval = [:interval]&.to_f || 30.0 timeout = [:timeout]&.to_f || 30.0 retries = [:retries]&.to_i || 3 shell = [:shell] || false test = test.split(" ") if test.is_a?(String) test = shell ? test.unshift("CMD-SHELL") : test.unshift("CMD") @healthcheck = { "Test" => test, "Interval" => (interval * 1_000_000_000).to_i, "Timeout" => (timeout * 1_000_000_000).to_i, "Retries" => retries, "StartPeriod" => 0 } end |
#add_label(label, value) ⇒ Hash
Add a label to the container configuration.
201 202 203 204 205 |
# File 'lib/testcontainers/docker_container.rb', line 201 def add_label(label, value) @labels ||= {} @labels[label] = value @labels end |
#add_labels(labels) ⇒ Hash
Add multiple labels to the container configuration.
211 212 213 214 215 |
# File 'lib/testcontainers/docker_container.rb', line 211 def add_labels(labels) @labels ||= {} @labels.merge!(labels) @labels end |
#add_volume(volume) ⇒ Hash
Add a volume to the container configuration.
139 140 141 142 143 |
# File 'lib/testcontainers/docker_container.rb', line 139 def add_volume(volume) @volumes ||= {} @volumes[volume] = {} @volumes end |
#add_volumes(volumes = []) ⇒ Hash
Add multiple volumes to the container configuration.
149 150 151 152 153 154 |
# File 'lib/testcontainers/docker_container.rb', line 149 def add_volumes(volumes = []) volumes = normalize_volumes(volumes) @volumes ||= {} @volumes.merge!(volumes) @volumes end |
#add_wait_for(method = nil, *args, **kwargs, &block) ⇒ Proc
Add a wait_for strategy to the container configuration.
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
# File 'lib/testcontainers/docker_container.rb', line 258 def add_wait_for(method = nil, *args, **kwargs, &block) if method.nil? if block if block.arity == 1 @wait_for = block else raise ArgumentError, "Invalid wait_for block: #{block}" end elsif @exposed_ports && !@exposed_ports.empty? port = @exposed_ports.keys.first.split("/").first @wait_for = ->(container) { container.wait_for_tcp_port(port) } end elsif method.is_a?(Proc) if method.arity == 1 @wait_for = method else raise ArgumentError, "Invalid wait_for method: #{method}" end elsif method.is_a?(Array) method_name = "wait_for_#{method[0]}".to_sym args = method[1] || [] kwargs = method[2] || {} if respond_to?(method_name) @wait_for = ->(container) { container.send(method_name, *args, **kwargs) } else raise ArgumentError, "Invalid wait_for method: #{method_name}" end else method_name = "wait_for_#{method}".to_sym if respond_to?(method_name) @wait_for = ->(container) { container.send(method_name, *args, **kwargs) } else raise ArgumentError, "Invalid wait_for method: #{method_name}" end end @wait_for end |
#copy_file_from_container(container_path, host_path_or_io) ⇒ String
Copies a file from the container to the host.
951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 |
# File 'lib/testcontainers/docker_container.rb', line 951 def copy_file_from_container(container_path, host_path_or_io) raise ContainerNotStartedError, "Container has not been started" unless running? raise ArgumentError, "Container path must be a non-empty string" if container_path.to_s.empty? begin io = host_path_or_io.is_a?(String) ? File.open(host_path_or_io, "w") : host_path_or_io io.rewind if io.pos != 0 content = read_file(container_path) io.write(content) io.rewind rescue => e puts "Error while copying file from container: #{e.}" raise e # Optionally re-raise the exception or handle it according to your needs ensure io.close if io.respond_to?(:close) end content end |
#copy_file_to_container(container_path, host_path_or_io) ⇒ self
Copies a IO object or a file from the host to the container.
925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 |
# File 'lib/testcontainers/docker_container.rb', line 925 def copy_file_to_container(container_path, host_path_or_io) raise ContainerNotStartedError, "Container has not been started" unless running? raise ArgumentError, "Container path must be a non-empty string" if container_path.to_s.empty? begin io = host_path_or_io.is_a?(String) ? File.open(host_path_or_io) : host_path_or_io io.rewind if io.pos != 0 store_file(container_path, io.read) io.rewind rescue => e puts "Error while copying file to container: #{e.}" return false ensure io.close if io.respond_to?(:close) end true end |
#created_at ⇒ String?
Returns the container’s created at timestamp. The timestamp is in UTC and formatted as ISO 8601. Example: “2014-10-31T23:22:05.430Z”.
673 674 675 |
# File 'lib/testcontainers/docker_container.rb', line 673 def created_at @_created_at end |
#dead? ⇒ Boolean
Returns whether the container is running.
583 584 585 |
# File 'lib/testcontainers/docker_container.rb', line 583 def dead? status == "dead" end |
#exec(cmd, options = {}, &block) ⇒ Array, Integer
Executes a command in the container. See docs.docker.com/engine/api/v1.42/#operation/ContainerExec for all available options.
796 797 798 799 800 801 |
# File 'lib/testcontainers/docker_container.rb', line 796 def exec(cmd, = {}, &block) raise ContainerNotStartedError unless @_container @_container.exec(cmd, , &block) rescue Excon::Error::Socket => e raise ConnectionError, e. end |
#exists? ⇒ Boolean
Returns whether the container exists.
657 658 659 660 661 662 663 664 665 666 |
# File 'lib/testcontainers/docker_container.rb', line 657 def exists? return false unless @_id Docker::Container.get(@_id) true rescue Docker::Error::NotFoundError false rescue Excon::Error::Socket => e raise ConnectionError, e. end |
#exited? ⇒ Boolean
Returns whether the container is stopped.
621 622 623 |
# File 'lib/testcontainers/docker_container.rb', line 621 def exited? status == "exited" end |
#first_mapped_port ⇒ Integer
Returns the container’s first mapped port.
736 737 738 739 |
# File 'lib/testcontainers/docker_container.rb', line 736 def first_mapped_port raise ContainerNotStartedError unless @_container container_ports.map { |port| mapped_port(port) }.first end |
#get_env(key) ⇒ String?
Returns the value for the given environment variable.
764 765 766 767 |
# File 'lib/testcontainers/docker_container.rb', line 764 def get_env(key) env_entry = env.find { |entry| entry.start_with?("#{key}=") } env_entry&.split("=")&.last end |
#healthy? ⇒ Boolean, false
Returns whether the container is healthy.
631 632 633 634 635 636 637 638 639 640 641 |
# File 'lib/testcontainers/docker_container.rb', line 631 def healthy? if supports_healthcheck? @_container&.json&.dig("State", "Health", "Status") == "healthy" else raise HealthcheckNotSupportedError end rescue ContainerNotStartedError false rescue Excon::Error::Socket => e raise ConnectionError, e. end |
#host ⇒ String
Returns the container’s host.
696 697 698 699 700 701 702 703 704 705 706 707 708 709 |
# File 'lib/testcontainers/docker_container.rb', line 696 def host host = docker_host return "localhost" if host.nil? raise ContainerNotStartedError unless @_container if inside_container? && ENV["DOCKER_HOST"].nil? gateway_ip = container_gateway_ip return bridge_ip if gateway_ip == host return gateway_ip end host rescue Excon::Error::Socket => e raise ConnectionError, e. end |
#info ⇒ Hash?
Returns the container’s info (inspect). See docs.docker.com/engine/api/v1.42/#tag/Container/operation/ContainerInspect
684 685 686 687 688 689 |
# File 'lib/testcontainers/docker_container.rb', line 684 def info raise ContainerNotStartedError unless @_container @_container.json rescue Excon::Error::Socket => e raise ConnectionError, e. end |
#inside_container? ⇒ Boolean
Returns whether this is running inside a container.
914 915 916 |
# File 'lib/testcontainers/docker_container.rb', line 914 def inside_container? File.exist?("/.dockerenv") end |
#kill(signal: "SIGKILL") ⇒ DockerContainer?
Kills the container with the specified signal
528 529 530 531 532 533 534 |
# File 'lib/testcontainers/docker_container.rb', line 528 def kill(signal: "SIGKILL") raise ContainerNotStartedError unless @_container @_container.kill(signal: signal) self rescue Excon::Error::Socket => e raise ConnectionError, e. end |
#logs(stdout: true, stderr: true) ⇒ Array<String>
Returns the container’s logs.
776 777 778 779 780 781 782 783 |
# File 'lib/testcontainers/docker_container.rb', line 776 def logs(stdout: true, stderr: true) raise ContainerNotStartedError unless @_container stdout = @_container.logs(stdout: stdout) stderr = @_container.logs(stderr: stderr) [stdout, stderr] rescue Excon::Error::Socket => e raise ConnectionError, e. end |
#mapped_port(port) ⇒ Integer
Returns the mapped host port for the given container port.
717 718 719 720 721 722 723 724 725 726 727 728 729 730 |
# File 'lib/testcontainers/docker_container.rb', line 717 def mapped_port(port) raise ContainerNotStartedError unless @_container mapped_port = container_port(port) if inside_container? gateway_ip = container_gateway_ip host = docker_host return port.to_i if gateway_ip == host end mapped_port.to_i rescue Excon::Error::Socket => e raise ConnectionError, e. end |
#mount_names ⇒ Array<String>
Returns the container’s mount names.
755 756 757 |
# File 'lib/testcontainers/docker_container.rb', line 755 def mount_names mounts.map { |mount| mount["Name"] } end |
#mounts ⇒ Array<Hash>
Returns the container’s mounts.
746 747 748 |
# File 'lib/testcontainers/docker_container.rb', line 746 def mounts info["Mounts"] end |
#paused? ⇒ Boolean
Returns whether the container is paused.
592 593 594 |
# File 'lib/testcontainers/docker_container.rb', line 592 def paused? status == "paused" end |
#read_file(path) ⇒ String
Reads the contents of a file inside the container.
975 976 977 978 979 |
# File 'lib/testcontainers/docker_container.rb', line 975 def read_file(path) raise ContainerNotStartedError unless @_container @_container.read_file(path) end |
#remove(options = {}) ⇒ DockerContainer? Also known as: delete
Removes the container.
542 543 544 545 546 547 548 |
# File 'lib/testcontainers/docker_container.rb', line 542 def remove( = {}) @_container&.remove() @_container = nil self rescue Excon::Error::Socket => e raise ConnectionError, e. end |
#restart ⇒ DockerContainer
Restarts the container.
558 559 560 561 562 563 564 |
# File 'lib/testcontainers/docker_container.rb', line 558 def restart raise ContainerNotStartedError unless @_container @_container.restart self rescue Excon::Error::Socket => e raise ConnectionError, e. end |
#restarting? ⇒ Boolean
Returns whether the container is restarting.
601 602 603 |
# File 'lib/testcontainers/docker_container.rb', line 601 def restarting? status == "restarting" end |
#running? ⇒ Boolean, false
Returns whether the container is running.
610 611 612 613 614 |
# File 'lib/testcontainers/docker_container.rb', line 610 def running? status == "running" rescue ContainerNotStartedError false end |
#start ⇒ DockerContainer Also known as: enter
Starts the container.
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 |
# File 'lib/testcontainers/docker_container.rb', line 474 def start Docker::Image.create({"fromImage" => @image}.merge(@image_create_options)) @_container ||= Docker::Container.create() @_container.start @_id = @_container.id json = @_container.json @name = json["Name"] @_created_at = json["Created"] @wait_for&.call(self) self rescue Docker::Error::NotFoundError => e raise NotFoundError, e. rescue Excon::Error::Socket => e raise ConnectionError, e. end |
#status ⇒ String
Returns the container’s status. Possible values are: “created”, “restarting”, “running”, “removing”, “paused”, “exited”, “dead”.
571 572 573 574 575 576 |
# File 'lib/testcontainers/docker_container.rb', line 571 def status raise ContainerNotStartedError unless @_container @_container.json["State"]["Status"] rescue Excon::Error::Socket => e raise ConnectionError, e. end |
#stop(force: false) ⇒ DockerContainer Also known as: exit
Stops the container.
502 503 504 505 506 507 508 |
# File 'lib/testcontainers/docker_container.rb', line 502 def stop(force: false) raise ContainerNotStartedError unless @_container @_container.stop(force: force) self rescue Excon::Error::Socket => e raise ConnectionError, e. end |
#stop! ⇒ DockerContainer
Stops the container forcefully.
517 518 519 |
# File 'lib/testcontainers/docker_container.rb', line 517 def stop! stop(force: true) end |
#store_file(path, contents) ⇒ Object
Writes the contents of a file inside the container.
987 988 989 990 991 |
# File 'lib/testcontainers/docker_container.rb', line 987 def store_file(path, contents) raise ContainerNotStartedError unless @_container @_container.store_file(path, contents) end |
#supports_healthcheck? ⇒ Boolean
Returns whether the container supports healthchecks. This is determined by the presence of a healthcheck in the container’s configuration.
648 649 650 651 |
# File 'lib/testcontainers/docker_container.rb', line 648 def supports_healthcheck? raise ContainerNotStartedError unless @_container @_container.json["Config"]["Healthcheck"] != nil end |
#use {|DockerContainer| ... } ⇒ DockerContainer
Starts the container, yields the container instance to the block, and stops the container.
462 463 464 465 466 467 |
# File 'lib/testcontainers/docker_container.rb', line 462 def use start yield self ensure stop end |
#wait_for_healthcheck(timeout: 60, interval: 0.1) ⇒ Boolean
Waits for the container to be healthy.
836 837 838 839 840 841 842 843 844 845 846 847 848 849 |
# File 'lib/testcontainers/docker_container.rb', line 836 def wait_for_healthcheck(timeout: 60, interval: 0.1) raise ContainerNotStartedError unless @_container raise HealthcheckNotSupportedError unless supports_healthcheck? Timeout.timeout(timeout) do loop do return true if healthy? sleep interval end end rescue Timeout::Error raise TimeoutError, "Timed out waiting for health check to be healthy" end |
#wait_for_http(timeout: 60, interval: 0.1, path: "/", container_port: 80, https: false, status: 200) ⇒ Boolean
Waits for the container to respond to HTTP requests.
891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 |
# File 'lib/testcontainers/docker_container.rb', line 891 def wait_for_http(timeout: 60, interval: 0.1, path: "/", container_port: 80, https: false, status: 200) raise ContainerNotStartedError unless @_container raise PortNotMappedError unless mapped_port(container_port) Timeout.timeout(timeout) do loop do begin response = Excon.get("#{https ? "https" : "http"}://#{host}:#{mapped_port(container_port)}#{path}") return true if response.status == status rescue Excon::Error::Socket # The container may not be ready to accept connections yet end sleep interval end end rescue Timeout::Error raise TimeoutError, "Timed out waiting for HTTP status #{status} on #{path}" end |
#wait_for_logs(matcher, timeout: 60, interval: 0.1) ⇒ Boolean
Waits for the container logs to match the given regex.
812 813 814 815 816 817 818 819 820 821 822 823 824 825 |
# File 'lib/testcontainers/docker_container.rb', line 812 def wait_for_logs(matcher, timeout: 60, interval: 0.1) raise ContainerNotStartedError unless @_container Timeout.timeout(timeout) do loop do stdout, stderr = @_container.logs(stdout: true, stderr: true) return true if stdout&.match?(matcher) || stderr&.match?(matcher) sleep interval end end rescue Timeout::Error raise TimeoutError, "Timed out waiting for logs to match #{matcher}" end |
#wait_for_tcp_port(port, timeout: 60, interval: 0.1) ⇒ Boolean
Waits for the container to open the given port.
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 |
# File 'lib/testcontainers/docker_container.rb', line 861 def wait_for_tcp_port(port, timeout: 60, interval: 0.1) raise ContainerNotStartedError unless @_container raise PortNotMappedError unless mapped_port(port) Timeout.timeout(timeout) do loop do Timeout.timeout(interval) do TCPSocket.new(host, mapped_port(port)).close return true end rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Timeout::Error sleep interval end end rescue Timeout::Error raise TimeoutError, "Timed out waiting for port #{port} to open" end |
#with(options) ⇒ DockerContainer
Set options for the container configuration using “with_” methods.
300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/testcontainers/docker_container.rb', line 300 def with() .each do |key, value| method_name = "with_#{key}" if respond_to?(method_name) send(method_name, value) else raise ArgumentError, "Invalid with_ method: #{method_name}" end end self end |
#with_command(*parts) ⇒ DockerContainer
Set the command for the container.
317 318 319 320 321 |
# File 'lib/testcontainers/docker_container.rb', line 317 def with_command(*parts) @command = parts.first.is_a?(Array) ? parts.first : parts self end |
#with_entrypoint(*parts) ⇒ DockerContainer
Set the entrypoint for the container.
327 328 329 330 331 |
# File 'lib/testcontainers/docker_container.rb', line 327 def with_entrypoint(*parts) @entrypoint = parts.first.is_a?(Array) ? parts.first : parts self end |
#with_env(env_or_key, value = nil) ⇒ DockerContainer
Sets the container’s environment variables.
350 351 352 353 |
# File 'lib/testcontainers/docker_container.rb', line 350 def with_env(env_or_key, value = nil) add_env(env_or_key, value) self end |
#with_exposed_port(port) ⇒ DockerContainer
Adds a single exposed port to the container.
377 378 379 380 |
# File 'lib/testcontainers/docker_container.rb', line 377 def with_exposed_port(port) add_exposed_ports(port) self end |
#with_exposed_ports(*ports) ⇒ DockerContainer
Adds exposed ports to the container.
368 369 370 371 |
# File 'lib/testcontainers/docker_container.rb', line 368 def with_exposed_ports(*ports) add_exposed_ports(*ports) self end |
#with_filesystem_binds(filesystem_binds) ⇒ DockerContainer
Adds filesystem binds to the container.
408 409 410 411 |
# File 'lib/testcontainers/docker_container.rb', line 408 def with_filesystem_binds(filesystem_binds) add_filesystem_binds(filesystem_binds) self end |
#with_fixed_exposed_port(container_port, host_port = nil) ⇒ DockerContainer Also known as: with_port_binding
Adds a fixed exposed port to the container.
388 389 390 391 |
# File 'lib/testcontainers/docker_container.rb', line 388 def with_fixed_exposed_port(container_port, host_port = nil) add_fixed_exposed_port(container_port, host_port) self end |
#with_healthcheck(options = {}) ⇒ DockerContainer
Adds a healthcheck to the container.
441 442 443 444 |
# File 'lib/testcontainers/docker_container.rb', line 441 def with_healthcheck( = {}) add_healthcheck() self end |
#with_label(label, value) ⇒ DockerContainer
Adds a label to the container.
427 428 429 430 |
# File 'lib/testcontainers/docker_container.rb', line 427 def with_label(label, value) add_label(label, value) self end |
#with_labels(labels) ⇒ DockerContainer
Adds labels to the container.
417 418 419 420 |
# File 'lib/testcontainers/docker_container.rb', line 417 def with_labels(labels) add_labels(labels) self end |
#with_name(name) ⇒ DockerContainer
Set the name of the container.
337 338 339 340 |
# File 'lib/testcontainers/docker_container.rb', line 337 def with_name(name) @name = name self end |
#with_volumes(volumes = {}) ⇒ DockerContainer
Adds volumes to the container.
400 401 402 403 |
# File 'lib/testcontainers/docker_container.rb', line 400 def with_volumes(volumes = {}) add_volumes(volumes) self end |
#with_wait_for(method = nil, *args, **kwargs, &block) ⇒ DockerContainer
Add a wait_for strategy to the container configuration.
453 454 455 456 |
# File 'lib/testcontainers/docker_container.rb', line 453 def with_wait_for(method = nil, *args, **kwargs, &block) add_wait_for(method, *args, **kwargs, &block) self end |
#with_working_dir(working_dir) ⇒ DockerContainer
Sets the container’s working directory.
359 360 361 362 |
# File 'lib/testcontainers/docker_container.rb', line 359 def with_working_dir(working_dir) @working_dir = working_dir self end |