diff --git a/builder/remotecontext/git/gitutils.go b/builder/remotecontext/git/gitutils.go
index 7bc2268155..b579db9765 100644
--- a/builder/remotecontext/git/gitutils.go
+++ b/builder/remotecontext/git/gitutils.go
@@ -29,6 +29,10 @@ func Clone(remoteURL string) (string, error) {
 		return "", err
 	}
 
+	return cloneGitRepo(repo)
+}
+
+func cloneGitRepo(repo gitRepo) (string, error) {
 	fetch := fetchArgs(repo.remote, repo.ref)
 
 	root, err := ioutil.TempDir("", "docker-build-git")
@@ -50,7 +54,19 @@ func Clone(remoteURL string) (string, error) {
 		return "", errors.Wrapf(err, "error fetching: %s", output)
 	}
 
-	return checkoutGit(root, repo.ref, repo.subdir)
+	root, err = checkoutGit(root, repo.ref, repo.subdir)
+	if err != nil {
+		return "", err
+	}
+
+	cmd := exec.Command("git", "submodule", "update", "--init", "--recursive", "--depth=1")
+	cmd.Dir = root
+	output, err := cmd.CombinedOutput()
+	if err != nil {
+		return "", errors.Wrapf(err, "error initializing submodules: %s", output)
+	}
+
+	return root, nil
 }
 
 func parseRemoteURL(remoteURL string) (gitRepo, error) {
@@ -96,7 +112,7 @@ func getRefAndSubdir(fragment string) (ref string, subdir string) {
 }
 
 func fetchArgs(remoteURL string, ref string) []string {
-	args := []string{"fetch", "--recurse-submodules=yes"}
+	args := []string{"fetch"}
 
 	if supportsShallowClone(remoteURL) {
 		args = append(args, "--depth", "1")
diff --git a/builder/remotecontext/git/gitutils_test.go b/builder/remotecontext/git/gitutils_test.go
index c638a498f2..b4c49195f0 100644
--- a/builder/remotecontext/git/gitutils_test.go
+++ b/builder/remotecontext/git/gitutils_test.go
@@ -7,6 +7,7 @@ import (
 	"net/http/httptest"
 	"net/url"
 	"os"
+	"os/exec"
 	"path/filepath"
 	"runtime"
 	"strings"
@@ -61,7 +62,7 @@ func TestCloneArgsSmartHttp(t *testing.T) {
 	})
 
 	args := fetchArgs(serverURL.String(), "master")
-	exp := []string{"fetch", "--recurse-submodules=yes", "--depth", "1", "origin", "master"}
+	exp := []string{"fetch", "--depth", "1", "origin", "master"}
 	assert.Equal(t, exp, args)
 }
 
@@ -77,13 +78,13 @@ func TestCloneArgsDumbHttp(t *testing.T) {
 	})
 
 	args := fetchArgs(serverURL.String(), "master")
-	exp := []string{"fetch", "--recurse-submodules=yes", "origin", "master"}
+	exp := []string{"fetch", "origin", "master"}
 	assert.Equal(t, exp, args)
 }
 
 func TestCloneArgsGit(t *testing.T) {
 	args := fetchArgs("git://github.com/docker/docker", "master")
-	exp := []string{"fetch", "--recurse-submodules=yes", "--depth", "1", "origin", "master"}
+	exp := []string{"fetch", "--depth", "1", "origin", "master"}
 	assert.Equal(t, exp, args)
 }
 
@@ -165,24 +166,55 @@ func TestCheckoutGit(t *testing.T) {
 	_, err = gitWithinDir(gitDir, "checkout", "master")
 	require.NoError(t, err)
 
+	// set up submodule
+	subrepoDir := filepath.Join(root, "subrepo")
+	_, err = git("init", subrepoDir)
+	require.NoError(t, err)
+
+	_, err = gitWithinDir(subrepoDir, "config", "user.email", "test@docker.com")
+	require.NoError(t, err)
+
+	_, err = gitWithinDir(subrepoDir, "config", "user.name", "Docker test")
+	require.NoError(t, err)
+
+	err = ioutil.WriteFile(filepath.Join(subrepoDir, "subfile"), []byte("subcontents"), 0644)
+	require.NoError(t, err)
+
+	_, err = gitWithinDir(subrepoDir, "add", "-A")
+	require.NoError(t, err)
+
+	_, err = gitWithinDir(subrepoDir, "commit", "-am", "Subrepo initial")
+	require.NoError(t, err)
+
+	cmd := exec.Command("git", "submodule", "add", subrepoDir, "sub") // this command doesn't work with --work-tree
+	cmd.Dir = gitDir
+	require.NoError(t, cmd.Run())
+
+	_, err = gitWithinDir(gitDir, "add", "-A")
+	require.NoError(t, err)
+
+	_, err = gitWithinDir(gitDir, "commit", "-am", "With submodule")
+	require.NoError(t, err)
+
 	type singleCase struct {
-		frag string
-		exp  string
-		fail bool
+		frag      string
+		exp       string
+		fail      bool
+		submodule bool
 	}
 
 	cases := []singleCase{
-		{"", "FROM scratch", false},
-		{"master", "FROM scratch", false},
-		{":subdir", "FROM scratch" + eol + "EXPOSE 5000", false},
-		{":nosubdir", "", true},   // missing directory error
-		{":Dockerfile", "", true}, // not a directory error
-		{"master:nosubdir", "", true},
-		{"master:subdir", "FROM scratch" + eol + "EXPOSE 5000", false},
-		{"master:../subdir", "", true},
-		{"test", "FROM scratch" + eol + "EXPOSE 3000", false},
-		{"test:", "FROM scratch" + eol + "EXPOSE 3000", false},
-		{"test:subdir", "FROM busybox" + eol + "EXPOSE 5000", false},
+		{"", "FROM scratch", false, true},
+		{"master", "FROM scratch", false, true},
+		{":subdir", "FROM scratch" + eol + "EXPOSE 5000", false, false},
+		{":nosubdir", "", true, false},   // missing directory error
+		{":Dockerfile", "", true, false}, // not a directory error
+		{"master:nosubdir", "", true, false},
+		{"master:subdir", "FROM scratch" + eol + "EXPOSE 5000", false, false},
+		{"master:../subdir", "", true, false},
+		{"test", "FROM scratch" + eol + "EXPOSE 3000", false, false},
+		{"test:", "FROM scratch" + eol + "EXPOSE 3000", false, false},
+		{"test:subdir", "FROM busybox" + eol + "EXPOSE 5000", false, false},
 	}
 
 	if runtime.GOOS != "windows" {
@@ -197,11 +229,22 @@ func TestCheckoutGit(t *testing.T) {
 
 	for _, c := range cases {
 		ref, subdir := getRefAndSubdir(c.frag)
-		r, err := checkoutGit(gitDir, ref, subdir)
+		r, err := cloneGitRepo(gitRepo{remote: gitDir, ref: ref, subdir: subdir})
 
 		if c.fail {
 			assert.Error(t, err)
 			continue
+		} else {
+			require.NoError(t, err)
+			if c.submodule {
+				b, err := ioutil.ReadFile(filepath.Join(r, "sub/subfile"))
+				require.NoError(t, err)
+				assert.Equal(t, "subcontents", string(b))
+			} else {
+				_, err := os.Stat(filepath.Join(r, "sub/subfile"))
+				require.Error(t, err)
+				require.True(t, os.IsNotExist(err))
+			}
 		}
 
 		b, err := ioutil.ReadFile(filepath.Join(r, "Dockerfile"))