diff --git a/lib/manager/docker-compose/__fixtures__/docker-compose.3-default-val.yml b/lib/manager/docker-compose/__fixtures__/docker-compose.3-default-val.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0ff42a995d7c432c8e2ec27e23dd4777d68fcd41
--- /dev/null
+++ b/lib/manager/docker-compose/__fixtures__/docker-compose.3-default-val.yml
@@ -0,0 +1,4 @@
+version: "3.7"
+services:
+  redis:
+    image: ${REDIS_IMAGE:-redis:5.0.0@sha256:abcd}
\ No newline at end of file
diff --git a/lib/manager/docker-compose/extract.spec.ts b/lib/manager/docker-compose/extract.spec.ts
index e0b09bddf84c60cd14a7f1f8569a448e0432596e..5067db6164ecabe408cc1f26ff11a8938d6f1f2f 100644
--- a/lib/manager/docker-compose/extract.spec.ts
+++ b/lib/manager/docker-compose/extract.spec.ts
@@ -4,6 +4,7 @@ import { extractPackageFile } from './extract';
 const yamlFile1 = loadFixture('docker-compose.1.yml');
 const yamlFile3 = loadFixture('docker-compose.3.yml');
 const yamlFile3NoVersion = loadFixture('docker-compose.3-no-version.yml');
+const yamlFile3DefaultValue = loadFixture('docker-compose.3-default-val.yml');
 
 describe('manager/docker-compose/extract', () => {
   describe('extractPackageFile()', () => {
@@ -31,5 +32,21 @@ describe('manager/docker-compose/extract', () => {
       expect(res.deps).toMatchSnapshot();
       expect(res.deps).toHaveLength(8);
     });
+    it('extracts default variable values for version 3', () => {
+      const res = extractPackageFile(yamlFile3DefaultValue);
+      expect(res.deps).toMatchInlineSnapshot(`
+        Array [
+          Object {
+            "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}",
+            "currentDigest": "sha256:abcd",
+            "currentValue": "5.0.0",
+            "datasource": "docker",
+            "depName": "redis",
+            "replaceString": "redis:5.0.0@sha256:abcd",
+          },
+        ]
+      `);
+      expect(res.deps).toHaveLength(1);
+    });
   });
 });
diff --git a/lib/manager/dockerfile/extract.spec.ts b/lib/manager/dockerfile/extract.spec.ts
index ac320fe8035819210d1d8399bbcca1f17b54969a..f038205134248471ef913b20b741e4dd62e502bb 100644
--- a/lib/manager/dockerfile/extract.spec.ts
+++ b/lib/manager/dockerfile/extract.spec.ts
@@ -617,5 +617,44 @@ describe('manager/dockerfile/extract', () => {
     it('rejects null', () => {
       expect(getDep(null)).toEqual({ skipReason: 'invalid-value' });
     });
+
+    it('handles default environment variable values', () => {
+      // eslint-disable-next-line no-template-curly-in-string
+      const res = getDep('${REDIS_IMAGE:-redis:5.0.0@sha256:abcd}');
+      expect(res).toMatchInlineSnapshot(`
+Object {
+  "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}",
+  "currentDigest": "sha256:abcd",
+  "currentValue": "5.0.0",
+  "datasource": "docker",
+  "depName": "redis",
+  "replaceString": "redis:5.0.0@sha256:abcd",
+}
+`);
+
+      // eslint-disable-next-line no-template-curly-in-string
+      const res2 = getDep('${REDIS_IMAGE:-redis:5.0.0}');
+      expect(res2).toMatchInlineSnapshot(`
+Object {
+  "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}",
+  "currentValue": "5.0.0",
+  "datasource": "docker",
+  "depName": "redis",
+  "replaceString": "redis:5.0.0",
+}
+`);
+
+      // eslint-disable-next-line no-template-curly-in-string
+      const res3 = getDep('${REDIS_IMAGE:-redis@sha256:abcd}');
+      expect(res3).toMatchInlineSnapshot(`
+Object {
+  "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}",
+  "currentDigest": "sha256:abcd",
+  "datasource": "docker",
+  "depName": "redis",
+  "replaceString": "redis@sha256:abcd",
+}
+`);
+    });
   });
 });
diff --git a/lib/manager/dockerfile/extract.ts b/lib/manager/dockerfile/extract.ts
index eb0bacfae270674e30391a39156e12598fc3aab5..0fe8d607ece0b71c6dd09397d9098b89aa4c09b2 100644
--- a/lib/manager/dockerfile/extract.ts
+++ b/lib/manager/dockerfile/extract.ts
@@ -6,13 +6,43 @@ import { regEx } from '../../util/regex';
 import * as ubuntuVersioning from '../../versioning/ubuntu';
 import type { PackageDependency, PackageFile } from '../types';
 
+const variableOpen = '${';
+const variableClose = '}';
+const variableDefaultValueSplit = ':-';
+
 export function splitImageParts(currentFrom: string): PackageDependency {
-  if (currentFrom.includes('$')) {
-    return {
-      skipReason: SkipReason.ContainsVariable,
-    };
+  // Check if we have a variable in format of "${VARIABLE:-<image>:<defaultVal>@<digest>}"
+  // If so, remove everything except the image, defaultVal and digest.
+  let isVariable = false;
+  let cleanedCurrentFrom: string = currentFrom;
+  if (
+    currentFrom.startsWith(variableOpen) &&
+    currentFrom.endsWith(variableClose)
+  ) {
+    isVariable = true;
+
+    // If the variable contains exactly one $ and has the default value, we consider it as a valid dependency;
+    // otherwise skip it.
+    if (
+      currentFrom.split('$').length !== 2 ||
+      currentFrom.indexOf(variableDefaultValueSplit) === -1
+    ) {
+      return {
+        skipReason: SkipReason.ContainsVariable,
+      };
+    }
+
+    cleanedCurrentFrom = currentFrom.substr(
+      variableOpen.length,
+      currentFrom.length - (variableClose.length + 2)
+    );
+    cleanedCurrentFrom = cleanedCurrentFrom.substr(
+      cleanedCurrentFrom.indexOf(variableDefaultValueSplit) +
+        variableDefaultValueSplit.length
+    );
   }
-  const [currentDepTag, currentDigest] = currentFrom.split('@');
+
+  const [currentDepTag, currentDigest] = cleanedCurrentFrom.split('@');
   const depTagSplit = currentDepTag.split(':');
   let depName: string;
   let currentValue: string;
@@ -25,6 +55,29 @@ export function splitImageParts(currentFrom: string): PackageDependency {
     currentValue = depTagSplit.pop();
     depName = depTagSplit.join(':');
   }
+
+  if (isVariable) {
+    // If we have the variable and it contains the default value, we need to return
+    // it as a valid dependency.
+
+    const dep = {
+      depName,
+      currentValue,
+      currentDigest,
+      replaceString: cleanedCurrentFrom,
+    };
+
+    if (!dep.currentValue) {
+      delete dep.currentValue;
+    }
+
+    if (!dep.currentDigest) {
+      delete dep.currentDigest;
+    }
+
+    return dep;
+  }
+
   const dep: PackageDependency = {
     depName,
     currentValue,
@@ -46,7 +99,9 @@ export function getDep(
   }
   const dep = splitImageParts(currentFrom);
   if (specifyReplaceString) {
-    dep.replaceString = currentFrom;
+    if (!dep.replaceString) {
+      dep.replaceString = currentFrom;
+    }
     dep.autoReplaceStringTemplate =
       '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}';
   }