diff --git a/lib/manager/cocoapods/__snapshots__/artifacts.spec.ts.snap b/lib/manager/cocoapods/__snapshots__/artifacts.spec.ts.snap
index 62b4123ef4903a73c3b4e257de85b75672360591..1d56f775ee338bfdbfcae1753f15f276b3caa98d 100644
--- a/lib/manager/cocoapods/__snapshots__/artifacts.spec.ts.snap
+++ b/lib/manager/cocoapods/__snapshots__/artifacts.spec.ts.snap
@@ -15,6 +15,12 @@ exports[`.updateArtifacts() catches write error 2`] = `Array []`;
 
 exports[`.updateArtifacts() dynamically selects Docker image tag 1`] = `
 Array [
+  Object {
+    "cmd": "docker ps --filter label=renovate_child -aq | xargs docker rm -f",
+    "options": Object {
+      "encoding": "utf-8",
+    },
+  },
   Object {
     "cmd": "docker pull renovate/cocoapods:1.2.4",
     "options": Object {
@@ -49,6 +55,12 @@ Array [
 
 exports[`.updateArtifacts() falls back to the \`latest\` Docker image tag 1`] = `
 Array [
+  Object {
+    "cmd": "docker ps --filter label=renovate_child -aq | xargs docker rm -f",
+    "options": Object {
+      "encoding": "utf-8",
+    },
+  },
   Object {
     "cmd": "docker pull renovate/cocoapods:latest",
     "options": Object {
@@ -163,6 +175,12 @@ Array [
 
 exports[`.updateArtifacts() returns updated Podfile 2`] = `
 Array [
+  Object {
+    "cmd": "docker ps --filter label=renovate_child -aq | xargs docker rm -f",
+    "options": Object {
+      "encoding": "utf-8",
+    },
+  },
   Object {
     "cmd": "docker pull renovate/cocoapods",
     "options": Object {
diff --git a/lib/util/exec/__snapshots__/exec.spec.ts.snap b/lib/util/exec/__snapshots__/exec.spec.ts.snap
index 0c830a3709f73e67c3cceb84705bcbd8240a889e..052196846bc08f4d60ebb7d912702751444ba93f 100644
--- a/lib/util/exec/__snapshots__/exec.spec.ts.snap
+++ b/lib/util/exec/__snapshots__/exec.spec.ts.snap
@@ -4,6 +4,7 @@ exports[`Child process execution wrapper Supports image prefetch 1`] = `
 Array [
   "echo hello",
   "echo hello",
+  "docker ps --filter label=renovate_child -aq | xargs docker rm -f",
   "docker pull example/image",
   "docker ps --filter name=example_image -aq | xargs docker rm -f",
   "docker run --rm --name=example_image --label=renovate_child example/image bash -l -c \\"echo hello\\"",
@@ -11,6 +12,7 @@ Array [
   "docker run --rm --name=example_image --label=renovate_child example/image bash -l -c \\"echo hello\\"",
   "echo hello",
   "echo hello",
+  "docker ps --filter label=renovate_child -aq | xargs docker rm -f",
   "docker ps --filter name=example_image -aq | xargs docker rm -f",
   "docker run --rm --name=example_image --label=renovate_child example/image bash -l -c \\"echo hello\\"",
   "docker ps --filter name=example_image -aq | xargs docker rm -f",
diff --git a/lib/util/exec/docker/index.ts b/lib/util/exec/docker/index.ts
index 031989ada9ba7c4a8acf0130436ae468c17ca4c4..f1043fa1bc3f1e3c877a1fee6ff3515f5f6ea59e 100644
--- a/lib/util/exec/docker/index.ts
+++ b/lib/util/exec/docker/index.ts
@@ -134,6 +134,28 @@ export async function removeDockerContainer(image): Promise<void> {
   }
 }
 
+// istanbul ignore next
+export async function removeDanglingContainers(): Promise<void> {
+  try {
+    const res = await rawExec(
+      `docker ps --filter label=renovate_child -aq | xargs docker rm -f`,
+      { encoding: 'utf-8' }
+    );
+    if (res?.stdout?.trim().length) {
+      const containerIds = res.stdout
+        .trim()
+        .split('\n')
+        .map(container => container.trim())
+        .filter(Boolean);
+      logger.debug({ containerIds }, 'Removed dangling child containers');
+    } else {
+      logger.trace('No dangling containers to remove');
+    }
+  } catch (err) {
+    logger.warn({ err }, 'Error removing dangling containers');
+  }
+}
+
 export async function generateDockerCommand(
   commands: string[],
   options: DockerOptions,
diff --git a/lib/util/exec/index.ts b/lib/util/exec/index.ts
index 2593b295526fd0e55c2e3d9ce4c0647e275f4b64..0ed33a1df996741e2fa78dbf0caa481a005b3c8c 100644
--- a/lib/util/exec/index.ts
+++ b/lib/util/exec/index.ts
@@ -1,7 +1,11 @@
 import { dirname, join } from 'path';
 import { hrtime } from 'process';
 import { ExecOptions as ChildProcessExecOptions } from 'child_process';
-import { generateDockerCommand, removeDockerContainer } from './docker';
+import {
+  generateDockerCommand,
+  removeDockerContainer,
+  removeDanglingContainers,
+} from './docker';
 import { getChildProcessEnv } from './env';
 import { logger } from '../../logger';
 import {
@@ -22,11 +26,16 @@ const execConfig: ExecConfig = {
   cacheDir: null,
 };
 
-export function setExecConfig(config: Partial<RenovateConfig>): void {
+export async function setExecConfig(
+  config: Partial<RenovateConfig>
+): Promise<void> {
   for (const key of Object.keys(execConfig)) {
     const value = config[key];
     execConfig[key] = value || null;
   }
+  if (execConfig.binarySource === 'docker') {
+    await removeDanglingContainers();
+  }
 }
 
 type ExtraEnv<T = unknown> = Record<string, T>;
diff --git a/lib/util/index.ts b/lib/util/index.ts
index 181fa5ee30c1403baf389a03a14ac8480b2878f2..ca1081ab0e9fd628a4615e4bb017521c3f888fab 100644
--- a/lib/util/index.ts
+++ b/lib/util/index.ts
@@ -1,7 +1,7 @@
 import { setExecConfig } from './exec';
 import { setFsConfig } from './fs';
 
-export function setUtilConfig(config: any): void {
-  setExecConfig(config);
+export async function setUtilConfig(config: any): Promise<void> {
+  await setExecConfig(config);
   setFsConfig(config);
 }
diff --git a/lib/workers/global/index.ts b/lib/workers/global/index.ts
index 9131e7e461e1bb4b8bf8691168fbcff70add72ad..d633666b3f40a95489441fe673bbf901531eb48b 100644
--- a/lib/workers/global/index.ts
+++ b/lib/workers/global/index.ts
@@ -77,7 +77,7 @@ export async function start(): Promise<0 | 1> {
         break;
       }
       const repoConfig = await getRepositoryConfig(config, repository);
-      setUtilConfig(repoConfig);
+      await setUtilConfig(repoConfig);
       if (repoConfig.hostRules) {
         hostRules.clear();
         repoConfig.hostRules.forEach(rule => hostRules.add(rule));