Merge pull request #11205 from briancain/DOCKER-BUILDKIT-FIXUP

Enhance docker build method for the Docker provider to include buildkit output
This commit is contained in:
Brian Cain 2019-11-22 14:21:59 -08:00 committed by GitHub
commit e100d9cd48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 11 deletions

View File

@ -15,19 +15,31 @@ module VagrantPlugins
@executor = Executor::Local.new @executor = Executor::Local.new
end end
# Returns the id for a new container built from `docker build`. Raises
# an exception if the id was unable to be captured from the output
#
# @return [String] id - ID matched from the docker build output.
def build(dir, **opts, &block) def build(dir, **opts, &block)
args = Array(opts[:extra_args]) args = Array(opts[:extra_args])
args << dir args << dir
result = execute('docker', 'build', *args, &block) opts = {with_stderr: true}
matches = result.scan(/Successfully built (.+)$/i) result = execute('docker', 'build', *args, opts, &block)
if matches.empty? matches = result.match(/Successfully built (?<id>.+)$/i)
# This will cause a stack trace in Vagrant, but it is a bug if !matches
# if this happens anyways. # Check for the new output format 'writing image sha256...'
raise "UNKNOWN OUTPUT: #{result}" # In this case, docker builtkit is enabled. Its format is different
# from standard docker
@logger.warn("Could not determine docker container ID. Scanning for buildkit output instead")
matches = result.match(/writing image .+:(?<id>[0-9a-z]+) done/i)
if !matches
# This will cause a stack trace in Vagrant, but it is a bug
# if this happens anyways.
raise Errors::BuildError, result: result
end
end end
# Return the last match, and the capture of it # Return the matched group `id`
matches[-1][0] matches[:id]
end end
def create(params, **opts, &block) def create(params, **opts, &block)

View File

@ -5,6 +5,10 @@ module VagrantPlugins
error_namespace("docker_provider.errors") error_namespace("docker_provider.errors")
end end
class BuildError < DockerError
error_key(:build_error)
end
class CommunicatorNonDocker < DockerError class CommunicatorNonDocker < DockerError
error_key(:communicator_non_docker) error_key(:communicator_non_docker)
end end

View File

@ -27,7 +27,13 @@ module VagrantPlugins
stdout: result.stdout stdout: result.stdout
end end
result.stdout if opts
if opts[:with_stderr]
return result.stdout + " " + result.stderr
else
return result.stdout
end
end
end end
def windows? def windows?

View File

@ -159,6 +159,8 @@ en:
run exits and doesn't keep running. run exits and doesn't keep running.
errors: errors:
build_error: |-
Vagrant received unknown output from `docker build` while building a container: %{result}
compose_lock_timeout: |- compose_lock_timeout: |-
Vagrant encountered a timeout waiting for the docker compose driver Vagrant encountered a timeout waiting for the docker compose driver
to become available. Please try to run your command again. If you to become available. Please try to run your command again. If you

View File

@ -152,6 +152,27 @@ describe VagrantPlugins::DockerProvider::Driver do
].to_json } ].to_json }
describe '#build' do
let(:result) { "Successfully built 1a2b3c4d" }
let(:buildkit_result) { "writing image sha256:1a2b3c4d done" }
let(:cid) { "1a2b3c4d" }
it "builds a container with standard docker" do
allow(subject).to receive(:execute).and_return(result)
container_id = subject.build("/tmp/fakedir")
expect(container_id).to eq(cid)
end
it "builds a container with buildkit docker" do
allow(subject).to receive(:execute).and_return(buildkit_result)
container_id = subject.build("/tmp/fakedir")
expect(container_id).to eq(cid)
end
end
describe '#create' do describe '#create' do
let(:params) { { let(:params) { {