From 516d475f16dde60e114c1528926df2d3f70e3593 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Fri, 10 Jul 2015 11:32:02 -0600 Subject: [PATCH] Checksum args to each docker container in local data This allows Vagrant to calculate if a container's arguments (such as the run arguments) have changed in the Vagrantfile since the original run. Fixes GH-3055 --- plugins/provisioners/docker/client.rb | 76 ++++++++++++++++++++++----- templates/locales/en.yml | 4 +- 2 files changed, 65 insertions(+), 15 deletions(-) diff --git a/plugins/provisioners/docker/client.rb b/plugins/provisioners/docker/client.rb index 6f0e39ad3..391c76395 100644 --- a/plugins/provisioners/docker/client.rb +++ b/plugins/provisioners/docker/client.rb @@ -59,7 +59,15 @@ module VagrantPlugins id = "$(cat #{config[:cidfile]})" if container_exists?(id) - start_container(id) + if container_args_changed?(config) + @machine.ui.info(I18n.t("vagrant.docker_restarting_container", + name: config[:name], + )) + stop_container(id) + create_container(config) + else + start_container(id) + end else create_container(config) end @@ -75,27 +83,41 @@ module VagrantPlugins end end + def stop_container(id) + @machine.communicate.sudo %[ + docker stop #{id} + docker rm #{id} + ] + end + def container_running?(id) lookup_container(id) end + def container_args_changed?(config) + path = container_data_path(config) + return true if !path.exist? + + args = container_run_args(config) + sha = Digest::SHA1.hexdigest(args) + return true if path.read.chomp != sha + + return false + end + def create_container(config) - name = config[:name] + args = container_run_args(config) - # If the name is the automatically assigned name, then - # replace the "/" with "-" because "/" is not a valid - # character for a docker container name. - name = name.gsub("/", "-") if name == config[:original_name] - - args = "--cidfile=#{config[:cidfile]} " - args << "-d " if config[:daemonize] - args << "--name #{name} " if name && config[:auto_assign_name] - args << "--restart=#{config[:restart]}" if config[:restart] - args << " #{config[:args]}" if config[:args] @machine.communicate.sudo %[ rm -f #{config[:cidfile]} - docker run #{args} #{config[:image]} #{config[:cmd]} + docker run #{args} ] + + name = container_name(config) + sha = Digest::SHA1.hexdigest(args) + container_data_path(config).open("w+") do |f| + f.write(sha) + end end def lookup_container(id, list_all = false) @@ -110,6 +132,33 @@ module VagrantPlugins end end + def container_name(config) + name = config[:name] + + # If the name is the automatically assigned name, then + # replace the "/" with "-" because "/" is not a valid + # character for a docker container name. + name = name.gsub("/", "-") if name == config[:original_name] + name + end + + def container_run_args(config) + name = container_name(config) + + args = "--cidfile=#{config[:cidfile]} " + args << "-d " if config[:daemonize] + args << "--name #{name} " if name && config[:auto_assign_name] + args << "--restart=#{config[:restart]}" if config[:restart] + args << " #{config[:args]}" if config[:args] + + "#{args} #{config[:image]} #{config[:cmd]}".strip + end + + def container_data_path(config) + name = container_name(config) + @machine.data_dir.join("docker-#{name}") + end + protected # This handles outputting the communication data back to the UI @@ -125,7 +174,6 @@ module VagrantPlugins @machine.ui.info(data.chomp, options) end end - end end end diff --git a/templates/locales/en.yml b/templates/locales/en.yml index b906e8f0b..87373d758 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -141,7 +141,9 @@ en: Building Docker images... docker_running: |- -- Container: %{name} - docker_starting_containers: + docker_restarting_container: |- + -- Detected changes to container '%{name}', restarting... + docker_starting_containers: |- Starting Docker containers... inserted_key: |- Key inserted! Disconnecting and reconnecting using new SSH key...