diff --git a/tools/gce_setup/grpc_docker.sh b/tools/gce_setup/grpc_docker.sh
index 314ccb0ca8bf21e8a692e32647293cdfefdf9c25..a19915594a7c3b0483d4e40ae1be44e33d9b1e41 100755
--- a/tools/gce_setup/grpc_docker.sh
+++ b/tools/gce_setup/grpc_docker.sh
@@ -86,6 +86,7 @@ grpc_add_docker_user() {
 }
 
 _grpc_update_image_args() {
+  echo "image_args $@"
   # default the host, root storage uri and docker file root
   grpc_gs_root='gs://tmp-grpc-dev/admin/'
   grpc_dockerfile_root='tools/dockerfile'
@@ -95,7 +96,7 @@ _grpc_update_image_args() {
   # see if -p or -z is used to override the the project or zone
   local OPTIND
   local OPTARG
-  while getopts :r:d:h name
+  while getopts :r:d:h: name
   do
     case $name in
       d)  grpc_dockerfile_root=$OPTARG ;;
@@ -261,7 +262,7 @@ _grpc_set_project_and_zone() {
   local OPTIND
   local OPTARG
   local arg_func
-  while getopts :p:z:f:n name
+  while getopts :np:z:f: name
   do
     case $name in
       f)   declare -F $OPTARG >> /dev/null && {
@@ -392,6 +393,65 @@ grpc_interop_test_args() {
   }
 }
 
+_grpc_sync_scripts_args() {
+  grpc_gce_script_root='tools/gce_setup'
+
+  local OPTIND
+  local OPTARG
+  while getopts :s: name
+  do
+    case $name in
+      s)  grpc_gce_script_root=$OPTARG ;;
+      :)  continue ;; # ignore -s without args, just use the defaults
+      \?)  echo "-$OPTARG: unknown flag; it's ignored" 1>&2;  continue ;;
+    esac
+  done
+  shift $((OPTIND-1))
+
+  [[ -d $grpc_gce_script_root ]] || {
+    echo "Could not locate gce script dir: $grpc_gce_script_root" 1>&2
+    return 1
+  }
+
+  [[ $# -lt 1  ]] && {
+    echo "$FUNCNAME: missing arg: host1 [host2 ... hostN]" 1>&2
+    return 1
+  }
+  grpc_hosts="$@"
+}
+
+# Updates the latest version of the support scripts on some hosts.
+#
+# call-seq;
+#   grpc_sync_scripts <server_name1>, <server_name2> .. <server_name3>
+#
+# Updates the GCE docker instance <server_name>
+grpc_sync_scripts() {
+  _grpc_ensure_gcloud_ssh || return 1;
+
+  # declare vars local so that they don't pollute the shell environment
+  # where they this func is used.
+  local grpc_zone grpc_project dry_run  # set by _grpc_set_project_and_zone
+  local grpc_hosts grpc_gce_script_root
+
+  # set the project zone and check that all necessary args are provided
+  _grpc_set_project_and_zone -f _grpc_sync_scripts_args "$@" || return 1
+
+  local func_lib="shared_startup_funcs.sh"
+  local gce_func_lib="/var/local/startup_scripts/$func_lib"
+  local project_opt="--project $grpc_project"
+  local zone_opt="--zone $grpc_zone"
+  local host
+  for host in $grpc_hosts
+  do
+    gce_has_instance $grpc_project $host || return 1;
+    # Update the remote copy of the GCE func library.
+    local src_func_lib="$grpc_gce_script_root/$func_lib"
+    local rmt_func_lib="$host:$gce_func_lib"
+    gcloud compute copy-files $src_func_lib $rmt_func_lib $project_opt $zone_opt || return 1
+  done
+}
+
 grpc_sync_images_args() {
   [[ $# -lt 1  ]] && {
     echo "$FUNCNAME: missing arg: host1 [host2 ... hostN]" 1>&2
diff --git a/tools/gce_setup/shared_startup_funcs.sh b/tools/gce_setup/shared_startup_funcs.sh
index 9c747466a911118908b637ad2aa8e17c571fdd79..f9a6aafb095e6ece3bc3a1606d80d8995d01549e 100755
--- a/tools/gce_setup/shared_startup_funcs.sh
+++ b/tools/gce_setup/shared_startup_funcs.sh
@@ -367,7 +367,7 @@ grpc_docker_launch_registry() {
 grpc_docker_pull_known() {
   local addr=$1
   [[ -n $addr ]] || addr="0.0.0.0:5000"
-  local known="base cxx php_base php ruby_base ruby java_base java"
+  local known="base cxx php_base php ruby_base ruby java_base java go"
   echo "... pulling docker images for '$known'"
   for i in $known
   do
@@ -402,10 +402,15 @@ grpc_dockerfile_install() {
 
   [[ -d $dockerfile_dir ]] || { echo "$FUNCNAME: not a valid dir: $dockerfile_dir"; return 1; }
 
-  # For grpc/base, sync the ssh key into the  .ssh dir in the dockerfile context
-
+  # For specific base images, sync the ssh key into the .ssh dir in the dockerfile context
   [[ $image_label == "grpc/base" ]] && {
-    grpc_docker_sync_github_key $dockerfile_dir/.ssh || return 1;
+    grpc_docker_sync_github_key $dockerfile_dir/.ssh 'base_ssh_key'|| return 1;
+  }
+  [[ $image_label == "grpc/go" ]] && {
+    grpc_docker_sync_github_key $dockerfile_dir/.ssh 'go_ssh_key'|| return 1;
+  }
+  [[ $image_label == "grpc/java_base" ]] && {
+    grpc_docker_sync_github_key $dockerfile_dir/.ssh 'java_base_ssh_key'|| return 1;
   }
 
   # TODO(temiola): maybe make cache/no-cache a func option?
@@ -445,6 +450,9 @@ grpc_docker_sync_github_key() {
   local target_dir=$1
   [[ -n $target_dir ]] || { echo "$FUNCNAME: missing arg: target_dir" >&2; return 1; }
 
+  local key_file=$2
+  [[ -n $key_file ]] || { echo "$FUNCNAME: missing arg: key_file" >&2; return 1; }
+
   # determine the admin root; the parent of the dockerfile root,
   local gs_dockerfile_root=$(load_metadata "attributes/gs_dockerfile_root")
   [[ -n $gs_dockerfile_root ]] || {
@@ -454,7 +462,7 @@ grpc_docker_sync_github_key() {
   local gcs_admin_root=$(dirname $gs_dockerfile_root)
 
   # cp the file from gsutil to a known local area
-  local gcs_key_path=$gcs_admin_root/github/ssh_key
+  local gcs_key_path=$gcs_admin_root/github/$key_file
   local local_key_path=$target_dir/github.rsa
   mkdir -p $target_dir || {
     echo "$FUNCNAME: could not create dir: $target_dir" 1>&2