diff --git a/lib/manager/pipenv/__snapshots__/artifacts.spec.ts.snap b/lib/manager/pipenv/__snapshots__/artifacts.spec.ts.snap
index 32d9421f5a402fe0ef1db5e1f92e940c3aea012f..09432021e73e20915c05c5dedb080395cd72ebc9 100644
--- a/lib/manager/pipenv/__snapshots__/artifacts.spec.ts.snap
+++ b/lib/manager/pipenv/__snapshots__/artifacts.spec.ts.snap
@@ -58,7 +58,13 @@ Array [
 exports[`.updateArtifacts() supports docker mode 1`] = `
 Array [
   Object {
-    "cmd": "docker run --rm --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache/others/pipenv\\":\\"/tmp/renovate/cache/others/pipenv\\" -e LC_ALL -e LANG -e PIPENV_CACHE_DIR -w \\"/tmp/github/some/repo\\" renovate/pipenv pipenv lock",
+    "cmd": "docker pull renovate/pipenv",
+    "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/pipenv\\":\\"/tmp/renovate/cache/others/pipenv\\" -e PIPENV_CACHE_DIR -w \\"/tmp/github/some/repo\\" renovate/pipenv bash -l -c \\"pipenv lock\\"",
     "options": Object {
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
diff --git a/lib/manager/pipenv/artifacts.spec.ts b/lib/manager/pipenv/artifacts.spec.ts
index 040484fd8ffcd5dd6785aebed5cb7b49eb032409..44f60a78a1abfe4764883f4314daab734f5f7874 100644
--- a/lib/manager/pipenv/artifacts.spec.ts
+++ b/lib/manager/pipenv/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 pipenv from './artifacts';
@@ -7,6 +8,8 @@ import { StatusResult } from '../../platform/git/storage';
 import { envMock, mockExecAll } from '../../../test/execUtil';
 import * as _env from '../../util/exec/env';
 import { BinarySource } from '../../util/exec/common';
+import { resetPrefetchedImages } from '../../util/exec/docker';
+import { setUtilConfig } from '../../util';
 
 jest.mock('fs-extra');
 jest.mock('child_process');
@@ -19,14 +22,25 @@ const env = mocked(_env);
 const platform = mocked(_platform);
 
 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 dockerConfig = { ...config, binarySource: BinarySource.Docker };
+
 describe('.updateArtifacts()', () => {
   beforeEach(() => {
     jest.resetAllMocks();
-    env.getChildProcessEnv.mockReturnValue(envMock.basic);
+    env.getChildProcessEnv.mockReturnValue({
+      ...envMock.basic,
+      LANG: 'en_US.UTF-8',
+      LC_ALL: 'en_US',
+    });
+
+    setUtilConfig(config);
+    resetPrefetchedImages();
   });
 
   it('returns if no Pipfile.lock found', async () => {
@@ -71,6 +85,7 @@ describe('.updateArtifacts()', () => {
     expect(execSnapshots).toMatchSnapshot();
   });
   it('supports docker mode', async () => {
+    setUtilConfig(dockerConfig);
     platform.getFile.mockResolvedValueOnce('Current Pipfile.lock');
     const execSnapshots = mockExecAll(exec);
     platform.getRepoStatus.mockResolvedValue({
@@ -82,11 +97,7 @@ describe('.updateArtifacts()', () => {
         packageFileName: 'Pipfile',
         updatedDeps: [],
         newPackageFileContent: '{}',
-        config: {
-          ...config,
-          binarySource: BinarySource.Docker,
-          dockerUser: 'foobar',
-        },
+        config: dockerConfig,
       })
     ).not.toBeNull();
     expect(execSnapshots).toMatchSnapshot();
diff --git a/lib/manager/pipenv/artifacts.ts b/lib/manager/pipenv/artifacts.ts
index c7668606f02d0dfff220773e0c7a1f03316a1000..c3a715ae7702feb88fc59a52b08f0e015a88fea5 100644
--- a/lib/manager/pipenv/artifacts.ts
+++ b/lib/manager/pipenv/artifacts.ts
@@ -1,11 +1,9 @@
 import { ensureDir, outputFile, readFile } from 'fs-extra';
-import { join, dirname } from 'upath';
-import { exec } from '../../util/exec';
-import { getChildProcessEnv } from '../../util/exec/env';
+import { join } from 'upath';
+import { exec, ExecOptions } from '../../util/exec';
 import { logger } from '../../logger';
 import { UpdateArtifactsResult, UpdateArtifact } from '../common';
 import { platform } from '../../platform';
-import { BinarySource } from '../../util/exec/common';
 
 export async function updateArtifacts({
   packageFileName: pipfileName,
@@ -15,11 +13,10 @@ export async function updateArtifacts({
 }: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> {
   logger.debug(`pipenv.updateArtifacts(${pipfileName})`);
 
-  const env = getChildProcessEnv(['LC_ALL', 'LANG', 'PIPENV_CACHE_DIR']);
-  env.PIPENV_CACHE_DIR =
-    env.PIPENV_CACHE_DIR || join(config.cacheDir, './others/pipenv');
-  await ensureDir(env.PIPENV_CACHE_DIR);
-  logger.debug('Using pipenv cache ' + env.PIPENV_CACHE_DIR);
+  const cacheDir =
+    process.env.PIPENV_CACHE_DIR || join(config.cacheDir, './others/pipenv');
+  await ensureDir(cacheDir);
+  logger.debug('Using pipenv cache ' + cacheDir);
 
   const lockFileName = pipfileName + '.lock';
   const existingLockFileContent = await platform.getFile(lockFileName);
@@ -27,34 +24,22 @@ export async function updateArtifacts({
     logger.debug('No Pipfile.lock found');
     return null;
   }
-  const cwd = join(config.localDir, dirname(pipfileName));
   try {
     const localPipfileFileName = join(config.localDir, pipfileName);
     await outputFile(localPipfileFileName, newPipfileContent);
     const localLockFileName = join(config.localDir, lockFileName);
-    let cmd: string;
-    if (config.binarySource === BinarySource.Docker) {
-      logger.info('Running pipenv via docker');
-      cmd = `docker run --rm `;
-      if (config.dockerUser) {
-        cmd += `--user=${config.dockerUser} `;
-      }
-      const volumes = [config.localDir, env.PIPENV_CACHE_DIR];
-      cmd += volumes.map(v => `-v "${v}":"${v}" `).join('');
-      const envVars = ['LC_ALL', 'LANG', 'PIPENV_CACHE_DIR'];
-      cmd += envVars.map(e => `-e ${e} `).join('');
-      cmd += `-w "${cwd}" `;
-      cmd += `renovate/pipenv pipenv`;
-    } else {
-      logger.info('Running pipenv via global command');
-      cmd = 'pipenv';
-    }
-    const args = 'lock';
-    logger.debug({ cmd, args }, 'pipenv lock command');
-    await exec(`${cmd} ${args}`, {
-      cwd,
-      env,
-    });
+    const cmd = 'pipenv lock';
+    const execOptions: ExecOptions = {
+      extraEnv: {
+        PIPENV_CACHE_DIR: cacheDir,
+      },
+      docker: {
+        image: 'renovate/pipenv',
+        volumes: [cacheDir],
+      },
+    };
+    logger.debug({ cmd }, 'pipenv lock command');
+    await exec(cmd, execOptions);
     const status = await platform.getRepoStatus();
     if (!(status && status.modified.includes(lockFileName))) {
       return null;