diff --git a/core/lib/testcontainers/docker_container.rb b/core/lib/testcontainers/docker_container.rb index 6d639f9..c357169 100644 --- a/core/lib/testcontainers/docker_container.rb +++ b/core/lib/testcontainers/docker_container.rb @@ -487,7 +487,18 @@ def start connection = Docker::Connection.new(Docker.url, Docker.options) - Docker::Image.create({"fromImage" => @image}.merge(@image_create_options), connection) + image_options = {"fromImage" => @image}.merge(@image_create_options) + image_reference = (image_options["fromImage"] || image_options[:fromImage] || @image).to_s + tag_option = image_options["tag"] || image_options[:tag] + if tag_option && !image_reference.end_with?(":#{tag_option}") + image_reference = "#{image_reference}:#{tag_option}" + end + + begin + Docker::Image.get(image_reference, {}, connection) + rescue Docker::Error::NotFoundError + Docker::Image.create(image_options, connection) + end @_container ||= Docker::Container.create(_container_create_options) @_container.start diff --git a/core/test/docker_container_test.rb b/core/test/docker_container_test.rb index 00e13f3..fa0614d 100644 --- a/core/test/docker_container_test.rb +++ b/core/test/docker_container_test.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true require "test_helper" +require "tmpdir" +require "securerandom" class DockerContainerTest < TestcontainersTest def before_all @@ -44,6 +46,38 @@ def test_it_creates_an_image_with_options bad_container.remove if bad_container.exists? end + def test_it_uses_locally_built_image_before_pulling + image_repo = "testcontainers-local-#{SecureRandom.hex(6)}" + image_tag = "latest" + image_reference = "#{image_repo}:#{image_tag}" + container = nil + + Dir.mktmpdir do |dir| + dockerfile_path = File.join(dir, "Dockerfile") + File.write(dockerfile_path, <<~DOCKERFILE) + FROM alpine:latest + CMD ["sleep", "60"] + DOCKERFILE + + Docker::Image.build_from_dir(dir, {"t" => image_reference, "dockerfile" => "Dockerfile"}) + end + + container = Testcontainers::DockerContainer.new(image_reference) + container.start + + assert container.running? + ensure + if container + container.stop if container.running? + container.remove if container.exists? + end + begin + Docker::Image.get(image_reference).remove(force: true) + rescue Docker::Error::NotFoundError + # image already removed + end + end + def test_it_returns_the_container_image assert_equal "hello-world", @container.image end