diff --git a/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap b/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap
index d524642ff16a022827d55b05fd492527a1c21ad2..7ee74cb187c32aef3d6280b1f2b1cc6b3835b4aa 100644
--- a/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap
+++ b/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap
@@ -23,7 +23,10 @@ Array [
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
       "env": Object {
+        "CGO_ENABLED": "1",
+        "GONOSUMDB": "1",
         "GOPATH": "/tmp/renovate/cache/others/go",
+        "GOPROXY": "proxy.example.com",
         "HOME": "/home/user",
         "HTTPS_PROXY": "https://example.com",
         "HTTP_PROXY": "http://example.com",
@@ -45,7 +48,10 @@ Array [
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
       "env": Object {
+        "CGO_ENABLED": "1",
+        "GONOSUMDB": "1",
         "GOPATH": "/tmp/renovate/cache/others/go",
+        "GOPROXY": "proxy.example.com",
         "HOME": "/home/user",
         "HTTPS_PROXY": "https://example.com",
         "HTTP_PROXY": "http://example.com",
@@ -62,12 +68,21 @@ Array [
 exports[`.updateArtifacts() supports docker mode with credentials 1`] = `
 Array [
   Object {
-    "cmd": "docker run --rm -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache/others/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED=0 -w \\"/tmp/github/some/repo\\" renovate/go bash -c \\"git config --global url.\\\\\\"https://some-token@github.com/\\\\\\".insteadOf \\\\\\"https://github.com/\\\\\\" && go get -d ./...\\"",
+    "cmd": "docker pull renovate/go",
+    "options": Object {
+      "encoding": "utf-8",
+    },
+  },
+  Object {
+    "cmd": "docker run --rm --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -v \\"/tmp/renovate/cache/others/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go bash -l -c \\"git config --global url.\\\\\\\\\\\\\\"https://some-token@github.com/\\\\\\\\\\\\\\".insteadOf \\\\\\\\\\\\\\"https://github.com/\\\\\\\\\\\\\\" && go get -d ./...\\"",
     "options": Object {
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
       "env": Object {
+        "CGO_ENABLED": "1",
+        "GONOSUMDB": "1",
         "GOPATH": "/tmp/renovate/cache/others/go",
+        "GOPROXY": "proxy.example.com",
         "HOME": "/home/user",
         "HTTPS_PROXY": "https://example.com",
         "HTTP_PROXY": "http://example.com",
@@ -84,12 +99,21 @@ Array [
 exports[`.updateArtifacts() supports docker mode with credentials and appMode enabled 1`] = `
 Array [
   Object {
-    "cmd": "docker run --rm -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache/others/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED=0 -w \\"/tmp/github/some/repo\\" renovate/go bash -c \\"git config --global url.\\\\\\"https://x-access-token:some-token@github.com/\\\\\\".insteadOf \\\\\\"https://github.com/\\\\\\" && go get -d ./...\\"",
+    "cmd": "docker pull renovate/go",
+    "options": Object {
+      "encoding": "utf-8",
+    },
+  },
+  Object {
+    "cmd": "docker run --rm --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -v \\"/tmp/renovate/cache/others/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go bash -l -c \\"git config --global url.\\\\\\\\\\\\\\"https://x-access-token:some-token@github.com/\\\\\\\\\\\\\\".insteadOf \\\\\\\\\\\\\\"https://github.com/\\\\\\\\\\\\\\" && go get -d ./...\\"",
     "options": Object {
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
       "env": Object {
+        "CGO_ENABLED": "1",
+        "GONOSUMDB": "1",
         "GOPATH": "/tmp/renovate/cache/others/go",
+        "GOPROXY": "proxy.example.com",
         "HOME": "/home/user",
         "HTTPS_PROXY": "https://example.com",
         "HTTP_PROXY": "http://example.com",
@@ -101,12 +125,15 @@ Array [
     },
   },
   Object {
-    "cmd": "docker run --rm -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache/others/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED=0 -w \\"/tmp/github/some/repo\\" renovate/go bash -c \\"git config --global url.\\\\\\"https://x-access-token:some-token@github.com/\\\\\\".insteadOf \\\\\\"https://github.com/\\\\\\" && go mod tidy\\"",
+    "cmd": "docker run --rm --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -v \\"/tmp/renovate/cache/others/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go bash -l -c \\"git config --global url.\\\\\\\\\\\\\\"https://x-access-token:some-token@github.com/\\\\\\\\\\\\\\".insteadOf \\\\\\\\\\\\\\"https://github.com/\\\\\\\\\\\\\\" && go mod tidy\\"",
     "options": Object {
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
       "env": Object {
+        "CGO_ENABLED": "1",
+        "GONOSUMDB": "1",
         "GOPATH": "/tmp/renovate/cache/others/go",
+        "GOPROXY": "proxy.example.com",
         "HOME": "/home/user",
         "HTTPS_PROXY": "https://example.com",
         "HTTP_PROXY": "http://example.com",
@@ -123,12 +150,21 @@ Array [
 exports[`.updateArtifacts() supports docker mode without credentials 1`] = `
 Array [
   Object {
-    "cmd": "docker run --rm --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache/others/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED=0 -w \\"/tmp/github/some/repo\\" renovate/go go get -d ./...",
+    "cmd": "docker pull renovate/go",
+    "options": Object {
+      "encoding": "utf-8",
+    },
+  },
+  Object {
+    "cmd": "docker run --rm --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -v \\"/tmp/renovate/cache/others/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go bash -l -c \\"go get -d ./...\\"",
     "options": Object {
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
       "env": Object {
+        "CGO_ENABLED": "1",
+        "GONOSUMDB": "1",
         "GOPATH": "/tmp/renovate/cache/others/go",
+        "GOPROXY": "proxy.example.com",
         "HOME": "/home/user",
         "HTTPS_PROXY": "https://example.com",
         "HTTP_PROXY": "http://example.com",
@@ -150,7 +186,10 @@ Array [
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
       "env": Object {
+        "CGO_ENABLED": "1",
+        "GONOSUMDB": "1",
         "GOPATH": "/tmp/renovate/cache/others/go",
+        "GOPROXY": "proxy.example.com",
         "HOME": "/home/user",
         "HTTPS_PROXY": "https://example.com",
         "HTTP_PROXY": "http://example.com",
diff --git a/lib/manager/gomod/artifacts.spec.ts b/lib/manager/gomod/artifacts.spec.ts
index 47902cf24bb21cc6fdadfe9c0c96d63ffe19fa54..52b5332ec992c80b5b3480d8948fb6578676ffeb 100644
--- a/lib/manager/gomod/artifacts.spec.ts
+++ b/lib/manager/gomod/artifacts.spec.ts
@@ -1,3 +1,4 @@
+import { join } from 'upath';
 import _fs from 'fs-extra';
 import { exec as _exec } from 'child_process';
 import * as gomod from './artifacts';
@@ -6,7 +7,9 @@ import { mocked } from '../../../test/util';
 import { StatusResult } from '../../platform/git/storage';
 import { envMock, mockExecAll } from '../../../test/execUtil';
 import * as _env from '../../util/exec/env';
+import { setUtilConfig } from '../../util';
 import { BinarySource } from '../../util/exec/common';
+import { resetPrefetchedImages } from '../../util/exec/docker';
 
 jest.mock('fs-extra');
 jest.mock('child_process');
@@ -33,8 +36,16 @@ replace github.com/pkg/errors => ../errors
 `;
 
 const config = {
-  localDir: '/tmp/github/some/repo',
-  cacheDir: '/tmp/renovate/cache',
+  // `join` fixes Windows CI
+  localDir: join('/tmp/github/some/repo'),
+  cacheDir: join('/tmp/renovate/cache'),
+  dockerUser: 'foobar',
+};
+
+const goEnv = {
+  GONOSUMDB: '1',
+  GOPROXY: 'proxy.example.com',
+  CGO_ENABLED: '1',
 };
 
 describe('.updateArtifacts()', () => {
@@ -42,7 +53,9 @@ describe('.updateArtifacts()', () => {
     jest.resetAllMocks();
     jest.resetModules();
 
-    env.getChildProcessEnv.mockReturnValue(envMock.basic);
+    env.getChildProcessEnv.mockReturnValue({ ...envMock.basic, ...goEnv });
+    setUtilConfig(config);
+    resetPrefetchedImages();
   });
   it('returns if no go.sum found', async () => {
     const execSnapshots = mockExecAll(exec);
@@ -90,6 +103,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('supports docker mode without credentials', async () => {
+    setUtilConfig({ ...config, binarySource: BinarySource.Docker });
     platform.getFile.mockResolvedValueOnce('Current go.sum');
     const execSnapshots = mockExecAll(exec);
     platform.getRepoStatus.mockResolvedValueOnce({
@@ -104,7 +118,6 @@ describe('.updateArtifacts()', () => {
         config: {
           ...config,
           binarySource: BinarySource.Docker,
-          dockerUser: 'foobar',
         },
       })
     ).not.toBeNull();
@@ -131,6 +144,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('supports docker mode with credentials', async () => {
+    setUtilConfig({ ...config, binarySource: BinarySource.Docker });
     hostRules.find.mockReturnValueOnce({
       token: 'some-token',
     });
@@ -154,6 +168,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('supports docker mode with credentials and appMode enabled', async () => {
+    setUtilConfig({ ...config, binarySource: BinarySource.Docker });
     hostRules.find.mockReturnValueOnce({
       token: 'some-token',
     });
diff --git a/lib/manager/gomod/artifacts.ts b/lib/manager/gomod/artifacts.ts
index 63b1fde5f6fcbc61f212a2c081ddf54897855fd9..6c7c02f855b608180cc79594d8796a4c0e722859 100644
--- a/lib/manager/gomod/artifacts.ts
+++ b/lib/manager/gomod/artifacts.ts
@@ -1,14 +1,31 @@
-import { ensureDir, outputFile, readFile } from 'fs-extra';
+import { ensureDir } from 'fs-extra';
 import { join, dirname } from 'upath';
-import { exec } from '../../util/exec';
+import { exec, ExecOptions } from '../../util/exec';
 import { find } from '../../util/host-rules';
-import { getChildProcessEnv } from '../../util/exec/env';
 import { logger } from '../../logger';
 import { UpdateArtifact, UpdateArtifactsResult } from '../common';
 import { platform } from '../../platform';
 import { BinarySource } from '../../util/exec/common';
+import { readLocalFile, writeLocalFile } from '../../util/fs';
 import { PLATFORM_TYPE_GITHUB } from '../../constants/platforms';
 
+function getPreCommands(): string[] | null {
+  const credentials = find({
+    hostType: PLATFORM_TYPE_GITHUB,
+    url: 'https://api.github.com/',
+  });
+  let preCommands = null;
+  if (credentials && credentials.token) {
+    const token = global.appMode
+      ? `x-access-token:${credentials.token}`
+      : credentials.token;
+    preCommands = [
+      `git config --global url.\\\\"https://${token}@github.com/\\\\".insteadOf \\\\"https://github.com/\\\\"`,
+    ];
+  }
+  return preCommands;
+}
+
 export async function updateArtifacts({
   packageFileName: goModFileName,
   updatedDeps: _updatedDeps,
@@ -16,20 +33,18 @@ export async function updateArtifacts({
   config,
 }: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> {
   logger.debug(`gomod.updateArtifacts(${goModFileName})`);
-  const customEnv = ['GOPATH', 'GOPROXY', 'GONOSUMDB'];
-  const env = getChildProcessEnv(customEnv);
-  env.GOPATH = env.GOPATH || join(config.cacheDir, './others/go');
-  await ensureDir(env.GOPATH);
-  logger.debug('Using GOPATH: ' + env.GOPATH);
+
+  const goPath = process.env.GOPATH || join(config.cacheDir, './others/go');
+  await ensureDir(goPath);
+  logger.debug(`Using GOPATH: ${goPath}`);
+
   const sumFileName = goModFileName.replace(/\.mod$/, '.sum');
   const existingGoSumContent = await platform.getFile(sumFileName);
   if (!existingGoSumContent) {
     logger.debug('No go.sum found');
     return null;
   }
-  const cwd = join(config.localDir, dirname(goModFileName));
   try {
-    const localGoModFileName = join(config.localDir, goModFileName);
     const massagedGoMod = newGoModContent.replace(
       /\n(replace\s+[^\s]+\s+=>\s+\.\.\/.*)/g,
       '\n// renovate-replace $1'
@@ -37,68 +52,32 @@ export async function updateArtifacts({
     if (massagedGoMod !== newGoModContent) {
       logger.debug('Removed some relative replace statements from go.mod');
     }
-    await outputFile(localGoModFileName, massagedGoMod);
-    const localGoSumFileName = join(config.localDir, sumFileName);
-    let cmd: string;
-    if (config.binarySource === BinarySource.Docker) {
-      logger.info('Running go via docker');
-      cmd = `docker run --rm `;
-      if (config.dockerUser) {
-        cmd += `--user=${config.dockerUser} `;
-      }
-      const volumes = [config.localDir, env.GOPATH];
-      cmd += volumes.map(v => `-v "${v}":"${v}" `).join('');
-      const envVars = customEnv;
-      cmd += envVars.map(e => `-e ${e} `).join('');
-      cmd += '-e CGO_ENABLED=0 ';
-      cmd += `-w "${cwd}" `;
-      cmd += `renovate/go `;
-      const credentials = find({
-        hostType: PLATFORM_TYPE_GITHUB,
-        url: 'https://api.github.com/',
-      });
-      if (credentials && credentials.token) {
-        logger.debug('Setting github.com credentials');
-        cmd += `bash -c "git config --global url.\\"https://${
-          global.appMode
-            ? `x-access-token:${credentials.token}`
-            : credentials.token
-        }@github.com/\\".insteadOf \\"https://github.com/\\" && go`;
-      } else {
-        cmd += 'go';
-      }
-    } else if (
-      config.binarySource === BinarySource.Auto ||
-      config.binarySource === BinarySource.Global
-    ) {
-      logger.info('Running go via global command');
-      cmd = 'go';
-    } else {
-      logger.warn({ config }, 'Unsupported binarySource');
-      cmd = 'go';
-    }
+    await writeLocalFile(goModFileName, massagedGoMod);
+    const cmd = 'go';
+    const execOptions: ExecOptions = {
+      cwd: join(config.localDir, dirname(goModFileName)),
+      extraEnv: {
+        GOPATH: goPath,
+        GOPROXY: process.env.GOPROXY,
+        GONOSUMDB: process.env.GONOSUMDB,
+        CGO_ENABLED: config.binarySource === BinarySource.Docker ? '0' : null,
+      },
+      docker: {
+        image: 'renovate/go',
+        volumes: [goPath],
+        preCommands: getPreCommands(),
+      },
+    };
     let args = 'get -d ./...';
-    if (cmd.includes('.insteadOf')) {
-      args += '"';
-    }
     logger.debug({ cmd, args }, 'go get command');
-    await exec(`${cmd} ${args}`, {
-      cwd,
-      env,
-    });
+    await exec(`${cmd} ${args}`, execOptions);
     if (
       config.postUpdateOptions &&
       config.postUpdateOptions.includes('gomodTidy')
     ) {
       args = 'mod tidy';
-      if (cmd.includes('.insteadOf')) {
-        args += '"';
-      }
       logger.debug({ cmd, args }, 'go mod tidy command');
-      await exec(`${cmd} ${args}`, {
-        cwd,
-        env,
-      });
+      await exec(`${cmd} ${args}`, execOptions);
     }
     const res = [];
     let status = await platform.getRepoStatus();
@@ -109,7 +88,7 @@ export async function updateArtifacts({
     res.push({
       file: {
         name: sumFileName,
-        contents: await readFile(localGoSumFileName, 'utf8'),
+        contents: await readLocalFile(sumFileName),
       },
     });
     const vendorDir = join(dirname(goModFileName), 'vendor/');
@@ -117,14 +96,8 @@ export async function updateArtifacts({
     // istanbul ignore if
     if (await platform.getFile(vendorModulesFileName)) {
       args = 'mod vendor';
-      if (cmd.includes('.insteadOf')) {
-        args += '"';
-      }
       logger.debug({ cmd, args }, 'go mod vendor command');
-      await exec(`${cmd} ${args}`, {
-        cwd,
-        env,
-      });
+      await exec(`${cmd} ${args}`, execOptions);
       if (
         config.postUpdateOptions &&
         config.postUpdateOptions.includes('gomodTidy')
@@ -134,19 +107,15 @@ export async function updateArtifacts({
           args += '"';
         }
         logger.debug({ cmd, args }, 'go mod tidy command');
-        await exec(`${cmd} ${args}`, {
-          cwd,
-          env,
-        });
+        await exec(`${cmd} ${args}`, execOptions);
       }
       status = await platform.getRepoStatus();
       for (const f of status.modified.concat(status.not_added)) {
         if (f.startsWith(vendorDir)) {
-          const localModified = join(config.localDir, f);
           res.push({
             file: {
               name: f,
-              contents: await readFile(localModified, 'utf8'),
+              contents: await readLocalFile(f),
             },
           });
         }
@@ -160,9 +129,10 @@ export async function updateArtifacts({
         });
       }
     }
-    const finalGoModContent = (
-      await readFile(localGoModFileName, 'utf8')
-    ).replace(/\/\/ renovate-replace /g, '');
+    const finalGoModContent = (await readLocalFile(goModFileName)).replace(
+      /\/\/ renovate-replace /g,
+      ''
+    );
     if (finalGoModContent !== newGoModContent) {
       logger.info('Found updated go.mod after go.sum update');
       res.push({