Fix for docker strategy GID clash.

Fixes https://github.com/bazelbuild/bazel/issues/17535

PiperOrigin-RevId: 516200807
Change-Id: I29888a79869a7a0a6b404a2c689e9d608978ce4e
diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/DockerSandboxedSpawnRunner.java b/src/main/java/com/google/devtools/build/lib/sandbox/DockerSandboxedSpawnRunner.java
index 3e7dbc3..ef01b76 100644
--- a/src/main/java/com/google/devtools/build/lib/sandbox/DockerSandboxedSpawnRunner.java
+++ b/src/main/java/com/google/devtools/build/lib/sandbox/DockerSandboxedSpawnRunner.java
@@ -335,34 +335,47 @@
                       .getRelative(execRoot.getBaseName())
                       .getPathString();
               StringBuilder dockerfile = new StringBuilder();
-              dockerfile.append(String.format("FROM %s\n", image));
-              dockerfile.append(String.format("RUN [\"mkdir\", \"-p\", \"%s\"]\n", workDir));
-              // TODO(philwo) this will fail if a user / group with the given uid / gid already
-              // exists
-              // in the container. For now this seems reasonably unlikely, but we'll have to come up
-              // with a better way.
-              if (gid > 0) {
-                dockerfile.append(
-                    String.format("RUN [\"groupadd\", \"-g\", \"%d\", \"bazelbuild\"]\n", gid));
-              }
-              if (uid > 0) {
-                dockerfile.append(
-                    String.format(
-                        "RUN [\"useradd\", \"-l\", \"-m\", \"-g\", \"%d\", \"-d\", \"%s\", \"-N\","
-                            + " \"-u\", \"%d\", \"bazelbuild\"]\n",
-                        gid, workDir, uid));
-              }
+              dockerfile.append("ARG image\n");
+              dockerfile.append("FROM $image\n");
+              dockerfile.append("ARG work_dir\n");
+              dockerfile.append("RUN mkdir --parents $work_dir\n"); // could this be a VOLUME?
+              dockerfile.append("ARG group_name\n");
+              dockerfile.append("ARG gid\n");
+              dockerfile.append("RUN groupadd --non-unique --gid $gid $group_name\n");
+              dockerfile.append("ARG user_name\n");
+              dockerfile.append("ARG uid\n");
               dockerfile.append(
-                  String.format("RUN [\"chown\", \"-R\", \"%d:%d\", \"%s\"]\n", uid, gid, workDir));
-              dockerfile.append(String.format("USER %d:%d\n", uid, gid));
-              dockerfile.append(String.format("ENV HOME %s\n", workDir));
-              if (uid > 0) {
-                dockerfile.append(String.format("ENV USER bazelbuild\n"));
-              }
-              dockerfile.append(String.format("WORKDIR %s\n", workDir));
+                  "RUN useradd --non-unique --no-log-init --create-home --gid $gid --home-dir"
+                      + " $work_dir --no-user-group --uid"
+                      + " $uid"
+                      + " $user_name\n"); // we've already created home above?
+              dockerfile.append(
+                  "RUN chown --recursive $uid:$gid $work_dir\n"); // if we create home with useradd
+              // it'd already have the right
+              // ownership
+              dockerfile.append("USER $user_name:$group_name\n");
+              dockerfile.append("ENV HOME $work_dir\n");
+              dockerfile.append("ENV USER $user_name\n");
+              dockerfile.append("WORKDIR $work_dir\n");
               try {
                 return executeCommand(
-                    ImmutableList.of(dockerClient.getPathString(), "build", "-q", "-"),
+                    ImmutableList.of(
+                        dockerClient.getPathString(),
+                        "build",
+                        "--build-arg",
+                        String.format("image=%s", image),
+                        "--build-arg",
+                        String.format("work_dir=%s", workDir),
+                        "--build-arg",
+                        String.format("group_name=%s", "bazelbuild"),
+                        "--build-arg",
+                        String.format("gid=%d", gid),
+                        "--build-arg",
+                        String.format("user_name=%s", "bazelbuild"),
+                        "--build-arg",
+                        String.format("uid=%d", uid),
+                        "-q",
+                        "-"),
                     new ByteArrayInputStream(
                         dockerfile.toString().getBytes(Charset.defaultCharset())));
               } catch (UserExecException e) {