How do I execute one `docker build` command for several defined vagrant machines?

Preamble

I have a Vagrantfile which is using Docker to deploy 5 machines, all based on the same base Dockerfile.

This builds all OK, but when I do a vagrant up I build the same image 5 times (because it’s executing docker build for all 5 machines in parallel).

For context, the Vagrantfile looks a bit like this (to save clicking through to the Git repo, and for posterity):

ENV['VAGRANT_DEFAULT_PROVIDER'] = 'docker'
Vagrant.configure("2") do |config|
  config.vm.provider "docker" do |d|
    d.build_dir       = "."
    d.has_ssh         = true
    d.remains_running = false
    d.create_args     = ['--tmpfs', '/tmp', '--tmpfs', '/run', '--tmpfs', '/run/lock', '-v', '/sys/fs/cgroup:/sys/fs/cgroup:ro', '-t']
  end

  config.vm.define "host1" do |host|
    host.vm.hostname = "host1.example.org"
    host.vm.network "private_network", ip: "192.0.2.11"
    host.vm.provider "docker" do |d|
      d.name = "host1_example_org"
    end
  end

  # Repeat until

  config.vm.define "host5" do |host|
    host.vm.hostname = "host5.example.org"
    host.vm.network "private_network", ip: "192.0.2.15"
    host.vm.provider "docker" do |d|
      d.name = "host5_example_org"
    end

    host.vm.provision "ansible_local", run: "always" do |ansible|
      ansible.playbook         = "build_setup.yml"
      ansible.playbook_command = "sudo ansible-playbook"
      ansible.install_mode     = "pip"
      ansible.pip_install_cmd  = "sudo apt install -y python3-pip && sudo rm -f /usr/bin/pip && sudo ln -s /usr/bin/pip3 /usr/bin/pip"
    end
  end
end

The ansible playbook at the end copies the SSH keys into /root/.ssh/host[1-5] and creates an SSH config file for each host with the respective IP address and SSH key.

I thought I could add this block into the host5 block:

    host.trigger.before :up do |trigger|
      trigger.run = {
        inline: "docker build . -t 'example/build:latest'"
      }
    end

And then in the other host blocks, I could add this line (which is very OS specific):

    host.trigger.before :up do |trigger|
      trigger.run = {
        inline: "bash -c 'until docker image list example/build:latest | grep latest ; do sleep 5 ; done'"
      }
    end

However, I get a race condition where the image is tagged by Docker, but it actually isn’t usable by Vagrant, causing a failure, and the Ansible playbook will fire before the rest of the machines are started.

What I want

Ideally, Vagrant+Docker will do a docker build . -t 'example/build:latest' before it then tries to use those images

I also want to set the ansible_local provision to execute once the other machines are up.

Can anyone help me get to the bottom of how I might achieve this?