From 0536817e90813258ae83c27c16d55d78775666f6 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Tue, 26 Nov 2013 19:48:51 -0200 Subject: [PATCH 01/14] provisioners: Import Docker provisioner code from Vocker --- .../cap/debian/docker_configure_auto_start.rb | 15 +++ .../debian/docker_configure_vagrant_user.rb | 13 +++ .../docker/cap/debian/docker_install.rb | 26 +++++ .../docker/cap/debian/docker_start_service.rb | 13 +++ .../docker/cap/linux/docker_installed.rb | 13 +++ plugins/provisioners/docker/config.rb | 44 ++++++++ plugins/provisioners/docker/docker_client.rb | 102 ++++++++++++++++++ .../provisioners/docker/docker_installer.rb | 41 +++++++ plugins/provisioners/docker/errors.rb | 11 ++ plugins/provisioners/docker/plugin.rb | 48 +++++++++ plugins/provisioners/docker/provisioner.rb | 41 +++++++ 11 files changed, 367 insertions(+) create mode 100644 plugins/provisioners/docker/cap/debian/docker_configure_auto_start.rb create mode 100644 plugins/provisioners/docker/cap/debian/docker_configure_vagrant_user.rb create mode 100644 plugins/provisioners/docker/cap/debian/docker_install.rb create mode 100644 plugins/provisioners/docker/cap/debian/docker_start_service.rb create mode 100644 plugins/provisioners/docker/cap/linux/docker_installed.rb create mode 100644 plugins/provisioners/docker/config.rb create mode 100644 plugins/provisioners/docker/docker_client.rb create mode 100644 plugins/provisioners/docker/docker_installer.rb create mode 100644 plugins/provisioners/docker/errors.rb create mode 100644 plugins/provisioners/docker/plugin.rb create mode 100644 plugins/provisioners/docker/provisioner.rb diff --git a/plugins/provisioners/docker/cap/debian/docker_configure_auto_start.rb b/plugins/provisioners/docker/cap/debian/docker_configure_auto_start.rb new file mode 100644 index 000000000..52c438f20 --- /dev/null +++ b/plugins/provisioners/docker/cap/debian/docker_configure_auto_start.rb @@ -0,0 +1,15 @@ +module VagrantPlugins + module Docker + module Cap + module Debian + module DockerConfigureAutoStart + def self.docker_configure_auto_start(machine) + if ! machine.communicate.test('grep -q \'\-r=true\' /etc/init/docker.conf') + machine.communicate.sudo("sed -i.bak 's/docker -d/docker -d -r=true/' /etc/init/docker.conf ") + end + end + end + end + end + end +end diff --git a/plugins/provisioners/docker/cap/debian/docker_configure_vagrant_user.rb b/plugins/provisioners/docker/cap/debian/docker_configure_vagrant_user.rb new file mode 100644 index 000000000..1136ddd79 --- /dev/null +++ b/plugins/provisioners/docker/cap/debian/docker_configure_vagrant_user.rb @@ -0,0 +1,13 @@ +module VagrantPlugins + module Docker + module Cap + module Debian + module DockerConfigureVagrantUser + def self.docker_configure_vagrant_user(machine) + machine.communicate.sudo("usermod -a -G docker #{machine.config.ssh.username || "vagrant"}") + end + end + end + end + end +end diff --git a/plugins/provisioners/docker/cap/debian/docker_install.rb b/plugins/provisioners/docker/cap/debian/docker_install.rb new file mode 100644 index 000000000..8d5773465 --- /dev/null +++ b/plugins/provisioners/docker/cap/debian/docker_install.rb @@ -0,0 +1,26 @@ +module VagrantPlugins + module Docker + module Cap + module Debian + module DockerInstall + def self.docker_install(machine, version) + package = 'lxc-docker' + package << "-#{version}" if version != :latest + + machine.communicate.tap do |comm| + # TODO: Perform check on the host machine if aufs is installed and using LXC + if machine.provider_name != :lxc + comm.sudo("lsmod | grep aufs || modprobe aufs || apt-get install -y linux-image-extra-`uname -r`") + end + comm.sudo("apt-get install -y --force-yes -q curl") + comm.sudo("curl http://get.docker.io/gpg | apt-key add -") + comm.sudo("echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list") + comm.sudo("apt-get update") + comm.sudo("apt-get install -y --force-yes -q xz-utils #{package} -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold'") + end + end + end + end + end + end +end diff --git a/plugins/provisioners/docker/cap/debian/docker_start_service.rb b/plugins/provisioners/docker/cap/debian/docker_start_service.rb new file mode 100644 index 000000000..a97bade8b --- /dev/null +++ b/plugins/provisioners/docker/cap/debian/docker_start_service.rb @@ -0,0 +1,13 @@ +module VagrantPlugins + module Docker + module Cap + module Debian + module DockerStartService + def self.docker_start_service(machine) + machine.communicate.sudo("service docker start") + end + end + end + end + end +end diff --git a/plugins/provisioners/docker/cap/linux/docker_installed.rb b/plugins/provisioners/docker/cap/linux/docker_installed.rb new file mode 100644 index 000000000..f5d693501 --- /dev/null +++ b/plugins/provisioners/docker/cap/linux/docker_installed.rb @@ -0,0 +1,13 @@ +module VagrantPlugins + module Docker + module Cap + module Linux + module DockerInstalled + def self.docker_installed(machine) + machine.communicate.test("test -f /usr/bin/docker", sudo: true) + end + end + end + end + end +end diff --git a/plugins/provisioners/docker/config.rb b/plugins/provisioners/docker/config.rb new file mode 100644 index 000000000..3845cab2f --- /dev/null +++ b/plugins/provisioners/docker/config.rb @@ -0,0 +1,44 @@ +require 'set' + +module VagrantPlugins + module Docker + class Config < Vagrant.plugin("2", :config) + attr_reader :images, :containers + attr_accessor :version + + def initialize + @images = Set.new + @containers = Hash.new + @version = :latest + end + + def pull_images(*images) + @images += images.map(&:to_s) + end + + def run(*args) + container_name = args.shift + params = {} + + if args.empty? + params[:image] = container_name + elsif args.first.is_a?(String) + params[:image] = args.shift + params[:cmd] = container_name + else + params = args.shift + params[:cmd] ||= container_name + end + + # TODO: Validate provided parameters before assignment + @containers[container_name.to_s] = params + end + + def merge(other) + super.tap do |result| + result.pull_images *(other.images + self.images) + end + end + end + end +end diff --git a/plugins/provisioners/docker/docker_client.rb b/plugins/provisioners/docker/docker_client.rb new file mode 100644 index 000000000..923a7dc9a --- /dev/null +++ b/plugins/provisioners/docker/docker_client.rb @@ -0,0 +1,102 @@ +require 'digest/sha1' + +module VagrantPlugins + module Docker + class DockerClient + def initialize(machine) + @machine = machine + end + + def pull_images(*images) + @machine.communicate.tap do |comm| + images.each do |image| + comm.sudo("docker images | grep -q #{image} || docker pull #{image}") + end + end + end + + def start_service + if !daemon_running? && @machine.guest.capability?(:docker_start_service) + @machine.guest.capability(:docker_start_service) + end + end + + def daemon_running? + @machine.communicate.test('test -f /var/run/docker.pid') + end + + def run(containers) + containers.each do |name, config| + cids_dir = "/var/lib/vocker/cids" + config[:cidfile] ||= "#{cids_dir}/#{Digest::SHA1.hexdigest name}" + + @machine.communicate.sudo("mkdir -p #{cids_dir}") + run_container({name: name}.merge config) + end + end + + def run_container(config) + raise "Container's cidfile was not provided!" unless config[:cidfile] + + id = "$(cat #{config[:cidfile]})" + + if container_exist?(id) + start_container(id) + else + create_container(config) + end + end + + def container_exist?(id) + @machine.communicate.test("sudo docker ps -a -q | grep -q #{id}") + end + + def start_container(id) + unless container_running?(id) + @machine.communicate.sudo("docker start #{id}") + end + end + + def container_running?(id) + @machine.communicate.test("sudo docker ps -q | grep #{id}") + end + + def create_container(config) + # DISCUSS: Does this really belong here? + ensure_bind_mounts_exist(config) + + args = "-cidfile=#{config[:cidfile]} -d " + args << prepare_run_arguments(config) + @machine.communicate.sudo %[ + rm -f #{config[:cidfile]} + docker run #{args} #{config[:image]} #{config[:cmd]} + ] + end + + private + + def ensure_bind_mounts_exist(config) + Array(config[:volumes]).each do |volume| + if volume =~ /(.+):.+/ + guest_vm_path = $1 + @machine.communicate.sudo "mkdir -p #{guest_vm_path}" + end + end + end + + def prepare_run_arguments(config) + args = [] + + args << "-dns=#{config[:dns]}" if config[:dns] + args << "-name=#{config[:name]}" if config[:name] + args << "#{config[:additional_run_args]}" if config[:additional_run_args] + + args += Array(config[:volumes]).map { |volume| "-v #{volume}" } + args += Array(config[:ports]).map { |port| "-p #{port}" } + args += Array(config[:links]).map { |link| "-link #{link}" } + + args.compact.flatten.join ' ' + end + end + end +end diff --git a/plugins/provisioners/docker/docker_installer.rb b/plugins/provisioners/docker/docker_installer.rb new file mode 100644 index 000000000..068bf6799 --- /dev/null +++ b/plugins/provisioners/docker/docker_installer.rb @@ -0,0 +1,41 @@ +require_relative "errors" + +module VagrantPlugins + module Docker + class DockerInstaller + def initialize(machine, version) + @machine = machine + @version = version + end + + # This handles verifying the Docker installation, installing it if it was + # requested, and so on. This method will raise exceptions if things are + # wrong. + def ensure_installed + if !@machine.guest.capability?(:docker_installed) + @machine.ui.warn(I18n.t("vagrant.docker_cant_detect")) + return + end + + if !@machine.guest.capability(:docker_installed) + @machine.ui.info(I18n.t("vagrant.docker_installing")) + @machine.guest.capability(:docker_install, @version) + + if !@machine.guest.capability(:docker_installed) + raise Errors::DockerInstallFailed + end + end + + if @machine.guest.capability?(:docker_configure_auto_start) + @machine.guest.capability(:docker_configure_auto_start) + else + @machine.env.ui.warn I18n.t('vagrant.docker_auto_start_not_available') + end + + if @machine.guest.capability?(:docker_configure_vagrant_user) + @machine.guest.capability(:docker_configure_vagrant_user) + end + end + end + end +end diff --git a/plugins/provisioners/docker/errors.rb b/plugins/provisioners/docker/errors.rb new file mode 100644 index 000000000..4866d3a40 --- /dev/null +++ b/plugins/provisioners/docker/errors.rb @@ -0,0 +1,11 @@ +module VagrantPlugins + module Docker + module Errors + class DockerInstallFailed < ::Vagrant::Errors::VagrantError + end + + class DockerNotRunning < ::Vagrant::Errors::VagrantError + end + end + end +end diff --git a/plugins/provisioners/docker/plugin.rb b/plugins/provisioners/docker/plugin.rb new file mode 100644 index 000000000..72bc8463d --- /dev/null +++ b/plugins/provisioners/docker/plugin.rb @@ -0,0 +1,48 @@ +require "vagrant" + +module VagrantPlugins + module Docker + class Plugin < Vagrant.plugin("2") + name "docker" + description <<-DESC + Provides support for provisioning your virtual machines with + Docker images and containers. + DESC + + config(:docker, :provisioner) do + require_relative "config" + Config + end + + guest_capability("debian", "docker_install") do + require_relative "cap/debian/docker_install" + Cap::Debian::DockerInstall + end + + guest_capability("debian", "docker_configure_auto_start") do + require_relative "cap/debian/docker_configure_auto_start" + Cap::Debian::DockerConfigureAutoStart + end + + guest_capability("debian", "docker_configure_vagrant_user") do + require_relative "cap/debian/docker_configure_vagrant_user" + Cap::Debian::DockerConfigureVagrantUser + end + + guest_capability("debian", "docker_start_service") do + require_relative "cap/debian/docker_start_service" + Cap::Debian::DockerStartService + end + + guest_capability("linux", "docker_installed") do + require_relative "cap/linux/docker_installed" + Cap::Linux::DockerInstalled + end + + provisioner(:docker) do + require_relative "provisioner" + Provisioner + end + end + end +end diff --git a/plugins/provisioners/docker/provisioner.rb b/plugins/provisioners/docker/provisioner.rb new file mode 100644 index 000000000..d1da07714 --- /dev/null +++ b/plugins/provisioners/docker/provisioner.rb @@ -0,0 +1,41 @@ +require_relative "errors" +require_relative "docker_client" +require_relative "docker_installer" + +module VagrantPlugins + module Docker + # TODO: Improve handling of vagrant-lxc specifics (like checking for apparmor + # profile stuff + autocorrection) + class Provisioner < Vagrant.plugin("2", :provisioner) + def initialize(machine, config, installer = nil, client = nil) + super(machine, config) + # TODO: Rename to installer / client (drop docker suffix) + @installer = installer || DockerInstaller.new(@machine, config.version) + @client = client || DockerClient.new(@machine) + end + + def provision + @logger = Log4r::Logger.new("vagrant::provisioners::vocker") + + @logger.info("Checking for Docker installation...") + @installer.ensure_installed + + # Attempt to start service if not running + @client.start_service + unless @client.daemon_running? + raise Errors::DockerNotRunning + end + + if config.images.any? + @machine.ui.info(I18n.t("vagrant.docker_pulling_images")) + @client.pull_images(*config.images) + end + + if config.containers.any? + @machine.ui.info(I18n.t("vagrant.docker_starting_containers")) + @client.run(config.containers) + end + end + end + end +end From 82fc9330af8c7af608daa3b6c011541c71ba2ea9 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Tue, 26 Nov 2013 20:09:20 -0200 Subject: [PATCH 02/14] provisioners/docker: Simplify raising of Docker related errors --- plugins/provisioners/docker/docker_installer.rb | 2 +- plugins/provisioners/docker/errors.rb | 11 ----------- plugins/provisioners/docker/provisioner.rb | 9 ++++++--- templates/locales/en.yml | 4 ++++ 4 files changed, 11 insertions(+), 15 deletions(-) delete mode 100644 plugins/provisioners/docker/errors.rb diff --git a/plugins/provisioners/docker/docker_installer.rb b/plugins/provisioners/docker/docker_installer.rb index 068bf6799..974f2b6d6 100644 --- a/plugins/provisioners/docker/docker_installer.rb +++ b/plugins/provisioners/docker/docker_installer.rb @@ -22,7 +22,7 @@ module VagrantPlugins @machine.guest.capability(:docker_install, @version) if !@machine.guest.capability(:docker_installed) - raise Errors::DockerInstallFailed + raise DockerError, :install_failed end end diff --git a/plugins/provisioners/docker/errors.rb b/plugins/provisioners/docker/errors.rb deleted file mode 100644 index 4866d3a40..000000000 --- a/plugins/provisioners/docker/errors.rb +++ /dev/null @@ -1,11 +0,0 @@ -module VagrantPlugins - module Docker - module Errors - class DockerInstallFailed < ::Vagrant::Errors::VagrantError - end - - class DockerNotRunning < ::Vagrant::Errors::VagrantError - end - end - end -end diff --git a/plugins/provisioners/docker/provisioner.rb b/plugins/provisioners/docker/provisioner.rb index d1da07714..63155e76c 100644 --- a/plugins/provisioners/docker/provisioner.rb +++ b/plugins/provisioners/docker/provisioner.rb @@ -1,9 +1,12 @@ -require_relative "errors" require_relative "docker_client" require_relative "docker_installer" module VagrantPlugins module Docker + class DockerError < Vagrant::Errors::VagrantError + error_namespace("vagrant.provisioners.docker") + end + # TODO: Improve handling of vagrant-lxc specifics (like checking for apparmor # profile stuff + autocorrection) class Provisioner < Vagrant.plugin("2", :provisioner) @@ -15,7 +18,7 @@ module VagrantPlugins end def provision - @logger = Log4r::Logger.new("vagrant::provisioners::vocker") + @logger = Log4r::Logger.new("vagrant::provisioners::docker") @logger.info("Checking for Docker installation...") @installer.ensure_installed @@ -23,7 +26,7 @@ module VagrantPlugins # Attempt to start service if not running @client.start_service unless @client.daemon_running? - raise Errors::DockerNotRunning + raise DockerError, :not_running end if config.images.any? diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 1c5562094..75dfd72b7 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -1295,3 +1295,7 @@ en: playbook_path_invalid: "`playbook` for the Ansible provisioner does not exist on the host system: %{path}" inventory_path_invalid: "`inventory_path` for the Ansible provisioner does not exist on the host system: %{path}" extra_vars_invalid: "`extra_vars` for the Ansible provisioner must be a hash or a path to an existing file. Received: %{value} (as %{type})" + + docker: + not_running: "Docker is not running on the guest VM." + install_failed: "Docker installation failed." From 2d50b2f0856fe119dbc762af538bcb9708912614 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Tue, 26 Nov 2013 20:30:06 -0200 Subject: [PATCH 03/14] provisioner/docker: Add missing I18n --- templates/locales/en.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 75dfd72b7..0f0dfedbd 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -42,6 +42,17 @@ en: to automatically delete Chef nodes and clients. chef_run_list_empty: |- Warning: Chef run list is empty. This may not be what you want. + + docker_installing: |- + Installing Docker onto machine... + docker_pulling_images: + Pulling Docker images... + docker_starting_containers: + Starting Docker containers... + docker_auto_start_not_available: |- + Unable to configure automatic restart of Docker containers on + the guest machine + provisioner_cleanup: |- Running cleanup tasks for '%{name}' provisioner... From 3289141fc3f2a8439b999e382b33c788d716a35f Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Fri, 29 Nov 2013 01:26:35 -0200 Subject: [PATCH 04/14] provisioners/docker: Clean up some leftovers from vocker --- plugins/provisioners/docker/docker_client.rb | 2 +- plugins/provisioners/docker/docker_installer.rb | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/provisioners/docker/docker_client.rb b/plugins/provisioners/docker/docker_client.rb index 923a7dc9a..895d21ce1 100644 --- a/plugins/provisioners/docker/docker_client.rb +++ b/plugins/provisioners/docker/docker_client.rb @@ -27,7 +27,7 @@ module VagrantPlugins def run(containers) containers.each do |name, config| - cids_dir = "/var/lib/vocker/cids" + cids_dir = "/var/lib/vagrant/cids" config[:cidfile] ||= "#{cids_dir}/#{Digest::SHA1.hexdigest name}" @machine.communicate.sudo("mkdir -p #{cids_dir}") diff --git a/plugins/provisioners/docker/docker_installer.rb b/plugins/provisioners/docker/docker_installer.rb index 974f2b6d6..3cf444f41 100644 --- a/plugins/provisioners/docker/docker_installer.rb +++ b/plugins/provisioners/docker/docker_installer.rb @@ -1,5 +1,3 @@ -require_relative "errors" - module VagrantPlugins module Docker class DockerInstaller From dda7cbb412b2228aaad019b053c1fbc46f42dff4 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 3 Dec 2013 14:18:30 -0800 Subject: [PATCH 05/14] provisioners/docker: make sure version is correct type, fix Ruby warning --- plugins/provisioners/docker/config.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/provisioners/docker/config.rb b/plugins/provisioners/docker/config.rb index 3845cab2f..f90335835 100644 --- a/plugins/provisioners/docker/config.rb +++ b/plugins/provisioners/docker/config.rb @@ -34,9 +34,13 @@ module VagrantPlugins @containers[container_name.to_s] = params end + def finalize! + @version = @version.to_sym + end + def merge(other) super.tap do |result| - result.pull_images *(other.images + self.images) + result.pull_images(*(other.images + self.images)) end end end From d3b7bffc6597fb3526a1651d02cef301d913f6a8 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 3 Dec 2013 14:19:31 -0800 Subject: [PATCH 06/14] provisioners/docker: style nitpick on unless --- plugins/provisioners/docker/provisioner.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/provisioners/docker/provisioner.rb b/plugins/provisioners/docker/provisioner.rb index 63155e76c..546c4b20f 100644 --- a/plugins/provisioners/docker/provisioner.rb +++ b/plugins/provisioners/docker/provisioner.rb @@ -25,9 +25,7 @@ module VagrantPlugins # Attempt to start service if not running @client.start_service - unless @client.daemon_running? - raise DockerError, :not_running - end + raise DockerError, :not_running if !@client.daemon_running? if config.images.any? @machine.ui.info(I18n.t("vagrant.docker_pulling_images")) From c55f7dfd642ce6580006084cbc9c686e8be4ddbb Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 3 Dec 2013 14:25:20 -0800 Subject: [PATCH 07/14] provisioners/docker: allow images to be configured with images: --- plugins/provisioners/docker/config.rb | 4 ++++ plugins/provisioners/docker/provisioner.rb | 1 + 2 files changed, 5 insertions(+) diff --git a/plugins/provisioners/docker/config.rb b/plugins/provisioners/docker/config.rb index f90335835..bd8ec5140 100644 --- a/plugins/provisioners/docker/config.rb +++ b/plugins/provisioners/docker/config.rb @@ -12,6 +12,10 @@ module VagrantPlugins @version = :latest end + def images=(images) + @images = Set.new(images) + end + def pull_images(*images) @images += images.map(&:to_s) end diff --git a/plugins/provisioners/docker/provisioner.rb b/plugins/provisioners/docker/provisioner.rb index 546c4b20f..eac195b22 100644 --- a/plugins/provisioners/docker/provisioner.rb +++ b/plugins/provisioners/docker/provisioner.rb @@ -12,6 +12,7 @@ module VagrantPlugins class Provisioner < Vagrant.plugin("2", :provisioner) def initialize(machine, config, installer = nil, client = nil) super(machine, config) + # TODO: Rename to installer / client (drop docker suffix) @installer = installer || DockerInstaller.new(@machine, config.version) @client = client || DockerClient.new(@machine) From 33d3c2808646f0a9c0e1ed99a6b14828079459fc Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 3 Dec 2013 14:33:13 -0800 Subject: [PATCH 08/14] provisioners/docker: simplify run, output which are running --- plugins/provisioners/docker/config.rb | 18 ++++-------------- plugins/provisioners/docker/docker_client.rb | 5 ++++- templates/locales/en.yml | 2 ++ 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/plugins/provisioners/docker/config.rb b/plugins/provisioners/docker/config.rb index bd8ec5140..b4a2d57c5 100644 --- a/plugins/provisioners/docker/config.rb +++ b/plugins/provisioners/docker/config.rb @@ -20,22 +20,12 @@ module VagrantPlugins @images += images.map(&:to_s) end - def run(*args) - container_name = args.shift - params = {} - - if args.empty? - params[:image] = container_name - elsif args.first.is_a?(String) - params[:image] = args.shift - params[:cmd] = container_name - else - params = args.shift - params[:cmd] ||= container_name - end + def run(name, **options) + params = options.dup + params[:image] = name # TODO: Validate provided parameters before assignment - @containers[container_name.to_s] = params + @containers[name.to_s] = params end def finalize! diff --git a/plugins/provisioners/docker/docker_client.rb b/plugins/provisioners/docker/docker_client.rb index 895d21ce1..16af2e028 100644 --- a/plugins/provisioners/docker/docker_client.rb +++ b/plugins/provisioners/docker/docker_client.rb @@ -30,8 +30,11 @@ module VagrantPlugins cids_dir = "/var/lib/vagrant/cids" config[:cidfile] ||= "#{cids_dir}/#{Digest::SHA1.hexdigest name}" + @machine.ui.info(I18n.t("vagrant.docker_running", name: name)) @machine.communicate.sudo("mkdir -p #{cids_dir}") - run_container({name: name}.merge config) + run_container({ + name: name + }.merge(config)) end end diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 0f0dfedbd..97b596e9e 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -47,6 +47,8 @@ en: Installing Docker onto machine... docker_pulling_images: Pulling Docker images... + docker_running: |- + -- Container: %{name} docker_starting_containers: Starting Docker containers... docker_auto_start_not_available: |- From 8d6cac959f0d3c69f3cef2df6f76393896e633ed Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 3 Dec 2013 14:35:56 -0800 Subject: [PATCH 09/14] provisioners/docker: only allow 'args' special --- plugins/provisioners/docker/docker_client.rb | 30 +------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/plugins/provisioners/docker/docker_client.rb b/plugins/provisioners/docker/docker_client.rb index 16af2e028..9c10e627c 100644 --- a/plugins/provisioners/docker/docker_client.rb +++ b/plugins/provisioners/docker/docker_client.rb @@ -65,41 +65,13 @@ module VagrantPlugins end def create_container(config) - # DISCUSS: Does this really belong here? - ensure_bind_mounts_exist(config) - args = "-cidfile=#{config[:cidfile]} -d " - args << prepare_run_arguments(config) + args << config[:args] if config[:args] @machine.communicate.sudo %[ rm -f #{config[:cidfile]} docker run #{args} #{config[:image]} #{config[:cmd]} ] end - - private - - def ensure_bind_mounts_exist(config) - Array(config[:volumes]).each do |volume| - if volume =~ /(.+):.+/ - guest_vm_path = $1 - @machine.communicate.sudo "mkdir -p #{guest_vm_path}" - end - end - end - - def prepare_run_arguments(config) - args = [] - - args << "-dns=#{config[:dns]}" if config[:dns] - args << "-name=#{config[:name]}" if config[:name] - args << "#{config[:additional_run_args]}" if config[:additional_run_args] - - args += Array(config[:volumes]).map { |volume| "-v #{volume}" } - args += Array(config[:ports]).map { |port| "-p #{port}" } - args += Array(config[:links]).map { |link| "-link #{link}" } - - args.compact.flatten.join ' ' - end end end end From ecbd0bfa85a964d1420d6f43fc260cf43c26f587 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 3 Dec 2013 14:36:14 -0800 Subject: [PATCH 10/14] provisioners/docker: style nitpicks --- plugins/provisioners/docker/docker_client.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/provisioners/docker/docker_client.rb b/plugins/provisioners/docker/docker_client.rb index 9c10e627c..40c3094c5 100644 --- a/plugins/provisioners/docker/docker_client.rb +++ b/plugins/provisioners/docker/docker_client.rb @@ -39,7 +39,7 @@ module VagrantPlugins end def run_container(config) - raise "Container's cidfile was not provided!" unless config[:cidfile] + raise "Container's cidfile was not provided!" if !config[:cidfile] id = "$(cat #{config[:cidfile]})" @@ -55,7 +55,7 @@ module VagrantPlugins end def start_container(id) - unless container_running?(id) + if !container_running?(id) @machine.communicate.sudo("docker start #{id}") end end From f7916c0cffd3e9b9c1f541c4b7cebfc72ceaf05a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 3 Dec 2013 14:38:38 -0800 Subject: [PATCH 11/14] provisioners/docker: output for each image pulling --- plugins/provisioners/docker/docker_client.rb | 1 + templates/locales/en.yml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/plugins/provisioners/docker/docker_client.rb b/plugins/provisioners/docker/docker_client.rb index 40c3094c5..535c6e9fc 100644 --- a/plugins/provisioners/docker/docker_client.rb +++ b/plugins/provisioners/docker/docker_client.rb @@ -10,6 +10,7 @@ module VagrantPlugins def pull_images(*images) @machine.communicate.tap do |comm| images.each do |image| + @machine.ui.info(I18n.t("vagrant.docker_pulling_single", name: image)) comm.sudo("docker images | grep -q #{image} || docker pull #{image}") end end diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 97b596e9e..084efc3b9 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -47,6 +47,8 @@ en: Installing Docker onto machine... docker_pulling_images: Pulling Docker images... + docker_pulling_single: |- + -- Image: %{name} docker_running: |- -- Container: %{name} docker_starting_containers: From 999ce223540f1fa406db0de922f85b9e4d3e3605 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 3 Dec 2013 14:39:32 -0800 Subject: [PATCH 12/14] provisioners/docker: output version when installing --- plugins/provisioners/docker/docker_installer.rb | 2 +- templates/locales/en.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/provisioners/docker/docker_installer.rb b/plugins/provisioners/docker/docker_installer.rb index 3cf444f41..7a1a0da14 100644 --- a/plugins/provisioners/docker/docker_installer.rb +++ b/plugins/provisioners/docker/docker_installer.rb @@ -16,7 +16,7 @@ module VagrantPlugins end if !@machine.guest.capability(:docker_installed) - @machine.ui.info(I18n.t("vagrant.docker_installing")) + @machine.ui.info(I18n.t("vagrant.docker_installing", version: @version.to_s)) @machine.guest.capability(:docker_install, @version) if !@machine.guest.capability(:docker_installed) diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 084efc3b9..6dc877d0a 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -44,7 +44,7 @@ en: Warning: Chef run list is empty. This may not be what you want. docker_installing: |- - Installing Docker onto machine... + Installing Docker (%{version}) onto machine... docker_pulling_images: Pulling Docker images... docker_pulling_single: |- From 8f4fa897d09a19d29062e4b2d25cd207b4e92222 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 3 Dec 2013 16:19:08 -0800 Subject: [PATCH 13/14] provisioners/docker: use proper UNSET_VALUE for no value --- plugins/provisioners/docker/config.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/provisioners/docker/config.rb b/plugins/provisioners/docker/config.rb index b4a2d57c5..362e442db 100644 --- a/plugins/provisioners/docker/config.rb +++ b/plugins/provisioners/docker/config.rb @@ -9,7 +9,7 @@ module VagrantPlugins def initialize @images = Set.new @containers = Hash.new - @version = :latest + @version = UNSET_VALUE end def images=(images) @@ -29,6 +29,7 @@ module VagrantPlugins end def finalize! + @version = "latest" if @version == UNSET_VALUE @version = @version.to_sym end From 76fd0e7efdf31a2d32e56fb4ed8a56c58df16674 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 3 Dec 2013 16:29:06 -0800 Subject: [PATCH 14/14] website/docs: document the Docker provisioner --- website/docs/source/layouts/layout.erb | 1 + .../source/v2/provisioning/docker.html.md | 112 ++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 website/docs/source/v2/provisioning/docker.html.md diff --git a/website/docs/source/layouts/layout.erb b/website/docs/source/layouts/layout.erb index 9f957dff3..33b51de4e 100644 --- a/website/docs/source/layouts/layout.erb +++ b/website/docs/source/layouts/layout.erb @@ -150,6 +150,7 @@ >Ansible >Chef Solo >Chef Client + >Docker >Puppet Apply >Puppet Agent >Salt diff --git a/website/docs/source/v2/provisioning/docker.html.md b/website/docs/source/v2/provisioning/docker.html.md new file mode 100644 index 000000000..c35cc8dca --- /dev/null +++ b/website/docs/source/v2/provisioning/docker.html.md @@ -0,0 +1,112 @@ +--- +page_title: "Docker - Provisioning" +sidebar_current: "provisioning-docker" +--- + +# Docker Provisioner + +**Provisioner name: `"docker"`** + +The docker provisioner can automatically install [Docker](http://www.docker.io), +pull Docker containers, and configure certain containers to run on boot. + +The docker provisioner is ideal for organizations that are using +Docker as a means to distribute things like their application or services. +Or, if you're just getting started with Docker, the Docker provisioner +provides the easiest possible way to begin using Docker since the provisioner +automates installing Docker for you. + +As with all provisioners, the Docker provisioner can be used along with +all the other provisioners Vagrant has in order to setup your working +environment the best way possible. For example, perhaps you use Puppet to +install services like databases or web servers but use Docker to house +your application runtime. You can use the Puppet provisioner along +with the Docker provisioner. + +## Options + +The docker provisioner takes various options. None are required. If +no options are required, the Docker provisioner will only install Docker +for you (if it isn't already installed). + +* `images` (array) - A list of images to pull using `docker pull`. You + can also use the `pull_images` function. See the example below this + section for more information. + +* `version` (string) - The version of Docker to install. This defaults to + "latest" and will install the latest version of Docker. + +## Pulling Images + +The docker provisioner can automatically pull images from the +Docker registry for you. There are two ways to specify images to +pull. The first is as an array using `images`: + +```ruby +Vagrant.configure("2") do |config| + config.vm.provision "docker", + images: ["ubuntu"] +end +``` + +This will cause Vagrant to pull the "ubuntu" image from the registry +for you automatically. + +The second way to pull images is to use the `pull_images` function. +Each call to `pull_images` will _append_ the images to be pulled. The +`images` variable, on the other hand, can only be used once. + +Additionally, the `pull_images` function cannot be used with the +simple configuration method for provisioners (specifying it all in one line). + +```ruby +Vagrant.configure("2") do |config| + config.vm.provision "docker" do |d| + d.pull_images "ubuntu" + d.pull_images "vagrant" + end +end +``` + +## Running Containers + +In addition to pulling images, the Docker provisioner can run and start +containers for you. This lets you automatically start services as part of +`vagrant up`. + +Running containers can only be configured using the Ruby block syntax with +the `do...end` blocks. An example of running a container is shown below: + +```ruby +Vagrant.configure("2") do |config| + config.vm.provision "docker" do |d| + d.run "rabbitmq" + end +end +``` + +This will `docker run` a container with the "rabbitmq" image. In addition +to the name, the `run` method accepts a set of options, all optional: + +* `image` (string) - The image to run. This defaults to the first argument + but can also be given here as an option. + +* `cmd` (string) - The command to start within the container. If not specified, + then the containers default "run" command will be used, such as the + "run" command specified when the container was built. + +* `args` (string) - Extra arguments for `docker run` on the command line. + These are raw arguments that are passed directly to Docker. + +For example, here is how you would configure Docker to run a container +with the Vagrant shared directory mounted inside of it: + +```ruby +Vagrant.configure("2") do |config| + config.vm.provision "docker" do |d| + d.run "ubuntu", + cmd: "bash -l", + args: "-v '/vagrant:/var/www'" + end +end +```