     end
   end
 
-  defp docker_image_create do
-    cmd = "docker"
-    args = ["build", "--label", @label, "--tag", "nerves_system_br:latest", @dockerfile]
+  defp container_create(pkg, name, tag) do
+    Nerves.Utils.Shell.info "Creating Docker container #{name}"
+    build_paths = build_paths(pkg)
+    base_dir = Artifact.base_dir(pkg)
+
+    args = [tag, "bash"]
+
+    args =
+      Enum.reduce(build_paths, args, fn({_, host,target}, acc) ->
+        ["-v" | ["#{host}:#{target}" | acc]]
+      end)
+    args = ["-v" | ["nerves_cache:/nerves/cache" | args]]
+    args = ["-v" | ["#{base_dir}:/nerves/host/artifacts" | args]]
+
+    cmd = "docker"
+    args = ["create", "-it", "--name", name , "-w", @working_dir | args]
+    case System.cmd(cmd, args, stderr_to_stdout: true) do
+      {error, code} when code != 0 ->
+        Mix.raise "Docker provider encountered error: #{error}"
+      {<<"Cannot connect to the Docker daemon", _tail :: binary>>, _} ->
+        Mix.raise "Unable to connect to docker daemon"
+      _ -> :ok
+    end
+  end
+
+  defp docker_image?(tag) do
+    cmd = "docker"
+    args = ["images", "-q", "#{tag}", "-q"]
+    case System.cmd(cmd, args, stderr_to_stdout: true) do
+      {"", _} ->
+        false
+      {<<"Cannot connect to the Docker daemon", _tail :: binary>>, _} ->
+        Mix.raise "Unable to connect to docker daemon"
+      {_, 0} ->
+        true
+    end
+  end
+
+  defp docker_image_create(dockerfile, tag) do
+    cmd = "docker"
+    path = Path.dirname(dockerfile)
+    args = ["build", "--tag", "#{tag}", path]
     Nerves.Utils.Shell.info "Docker provider needs to create the image."
     if Mix.shell.yes?("Continue?") do
       case Mix.Nerves.Utils.shell(cmd, args) do


  @version "~> 1.12 or ~> 1.12.0-rc2"
  @config "~/.nerves/provider/docker"
  @machine "nerves_system_br"

  @sh "/bin/sh"
  @bash "/bin/bash"


  @label "org.nerves-project.nerves_system_br=1.0"
  @dockerfile File.cwd!
              |> Path.join("template/Dockerfile")
  @working_dir "/nerves/build"

  def artifact(pkg, toolchain, _opts) do
    container = preflight(pkg)
    artifact_name = Artifact.name(pkg, toolchain)

    {:ok, pid} = Nerves.Utils.Stream.start_link(file: "build.log")
    stream = IO.stream(pid, :line)

    container_ensure_started(container)

    :ok = create_build(pkg, container, stream)
    :ok = make(container, stream)
    :ok = make_artifact(artifact_name, container, stream)
    :ok = copy_artifact(pkg, toolchain, container, stream)

    container_stop(container)
  end

  # def shell(pkg, _opts) do
  #   _container = preflight(pkg)
  #   :ok
  # end
  #
  # def clean(_pkg, _opts) do
  #   :ok
  # end

  defp preflight(pkg) do
    checksum = Nerves.Package.checksum(pkg)

    id_file =
      Mix.Project.build_path
      |> Path.join("nerves/.docker_id")

    id =
      if File.exists?(id_file) do
        File.read!(id_file)
      else
        id = :crypto.strong_rand_bytes(16) |> Base.encode64 |> binary_part(0, 16)
        Path.dirname(id_file)
        |> File.mkdir_p!
        File.write!(id_file, id)
        id
      end

    name = "#{id}-#{pkg.app}-#{checksum}"

    _ = host_check()
    _ = config_check(pkg, name)

    name
  end

  defp create_build(pkg, container, stream) do
    platform_config = pkg.config[:platform_config][:defconfig]
    defconfig = Path.join("/nerves/env/#{pkg.app}", platform_config)

    Nerves.Utils.Shell.info "Starting Docker Build...(this may take a while)"
    args = [
      "exec",
      "-i",
      container,
      "/nerves/env/platform/create-build.sh",
      defconfig,
      @working_dir]

    case Mix.Nerves.Utils.shell("docker", args, stream: stream) do
      {_result, 0} ->
        :ok
      {_result, _} ->
        Mix.raise """
        Docker provider encountered an error.
        See build.log for more details.
        """
    end
  end

  defp make(container, stream) do

    args = [
      "exec",
      "-i",
      container,
      "make"]

    case Mix.Nerves.Utils.shell("docker", args, stream: stream) do
      {_result, 0} ->
        :ok
      {_result, _} ->
        Mix.raise """
        Docker provider encountered an error.
        See build.log for more details.
        """
    end
  end

  defp make_artifact(name, container, stream) do
    Nerves.Utils.Shell.info "Compressing artifact"
    args = [
      "exec",
      "-i",
      container,
      "make",
      "system",
      "NERVES_ARTIFACT_NAME=#{name}"]

    case Mix.Nerves.Utils.shell("docker", args, stream: stream) do
      {_result, 0} ->
        :ok
      {_result, _} ->
        Mix.raise """
        Docker provider encountered an error.
        See build.log for more details.
        """
    end
  end

  defp copy_artifact(pkg, toolchain, container, stream) do
    Nerves.Utils.Shell.info "Copying artifact to host"
    name = Artifact.name(pkg, toolchain)

    args = [
      "exec",
      "-i",
      container,
      "cp",
      "#{name}.tar.gz",
      "/nerves/host/artifacts/#{name}.tar.gz"]

    case Mix.Nerves.Utils.shell("docker", args, stream: stream) do
      {_result, 0} ->
        :ok
      {_result, _} ->
        Mix.raise """
        Docker provider encountered an error.
        See build.log for more details.
        """
    end

    base_dir = Artifact.base_dir(pkg)
    tar_file = Path.join(base_dir, "#{Artifact.name(pkg, toolchain)}.tar.gz")

    if File.exists?(tar_file) do
      dir = Artifact.dir(pkg, toolchain)
      File.mkdir_p(dir)
