diff --git a/lib/datasource/docker/index.js b/lib/datasource/docker/index.js
index 0cff2b6d9940fcbd767200f084bab3c71d858cac..7d29ddbedb69f11641375ebfacf2e8a101c63e8a 100644
--- a/lib/datasource/docker/index.js
+++ b/lib/datasource/docker/index.js
@@ -327,6 +327,120 @@ async function getTags(registry, repository) {
   }
 }
 
+/*
+ * docker.getLabels
+ *
+ * This function will:
+ *  - Return the labels for the requested image
+ */
+
+// istanbul ignore next
+async function getLabels(registry, repository, tag) {
+  logger.debug(`getLabels(${registry}, ${repository}, ${tag})`);
+  const cacheNamespace = 'datasource-docker-labels';
+  const cacheKey = `${registry}:${repository}:${tag}`;
+  const cachedResult = await renovateCache.get(cacheNamespace, cacheKey);
+  // istanbul ignore if
+  if (cachedResult) {
+    return cachedResult;
+  }
+  try {
+    const manifestResponse = await getManifestResponse(
+      registry,
+      repository,
+      tag
+    );
+    // If getting the manifest fails here, then abort
+    // This means that the latest tag doesn't have a manifest, which shouldn't
+    // be possible
+    if (!manifestResponse) {
+      logger.warn(
+        {
+          registry,
+          repository,
+          tag,
+        },
+        'docker registry failure: failed to get manifest for tag'
+      );
+      return {};
+    }
+    const manifest = JSON.parse(manifestResponse.body);
+    let labels = {};
+    if (manifest.schemaVersion === 1) {
+      labels = JSON.parse(manifest.history[0].v1Compatibility).container_config
+        .Labels;
+      if (!labels) {
+        labels = {};
+      }
+    }
+    if (manifest.schemaVersion === 2) {
+      const configDigest = manifest.config.digest;
+      const headers = await getAuthHeaders(registry, repository);
+      if (!headers) {
+        logger.info('No docker auth found - returning');
+        return {};
+      }
+      const url = `${registry}/v2/${repository}/blobs/${configDigest}`;
+      const configResponse = await got(url, {
+        headers,
+        timeout: 10000,
+      });
+      labels = JSON.parse(configResponse.body).config.Labels;
+    }
+
+    if (labels) {
+      logger.debug(
+        {
+          labels,
+        },
+        'found labels in manifest'
+      );
+    }
+    const cacheMinutes = 60;
+    await renovateCache.set(cacheNamespace, cacheKey, labels, cacheMinutes);
+    return labels;
+  } catch (err) {
+    if (err.statusCode === 401) {
+      logger.info(
+        { registry, dockerRepository: repository },
+        'Unauthorized docker lookup'
+      );
+      logger.debug({ err });
+    } else if (err.statusCode === 404) {
+      logger.warn(
+        {
+          err,
+          registry,
+          repository,
+          tag,
+        },
+        'Config Manifest is unknown'
+      );
+    } else if (err.statusCode === 429 && registry.endsWith('docker.io')) {
+      logger.warn({ err }, 'docker registry failure: too many requests');
+    } else if (err.statusCode >= 500 && err.statusCode < 600) {
+      logger.warn(
+        {
+          err,
+          registry,
+          repository,
+          tag,
+        },
+        'docker registry failure: internal error'
+      );
+    } else if (err.code === 'ETIMEDOUT') {
+      logger.info(
+        { registry },
+        'Timeout when attempting to connect to docker registry'
+      );
+      logger.debug({ err });
+    } else {
+      logger.warn({ err }, 'Unknown error getting Docker labels');
+    }
+    return {};
+  }
+}
+
 /*
  * docker.getPkgReleases
  *
@@ -354,5 +468,12 @@ async function getPkgReleases({ lookupName, registryUrls }) {
     dockerRepository: repository,
     releases,
   };
+
+  const latestTag = tags.includes('latest') ? 'latest' : tags[tags.length - 1];
+  const labels = await getLabels(registry, repository, latestTag);
+  // istanbul ignore if
+  if ('org.opencontainers.image.source' in labels) {
+    ret.sourceUrl = labels['org.opencontainers.image.source'];
+  }
   return ret;
 }
diff --git a/test/datasource/__snapshots__/docker.spec.js.snap b/test/datasource/__snapshots__/docker.spec.js.snap
index f4fec2c48a3271073329ee3afa0cfba240c1c80b..8df4e8b071dd4b133f4682d22e0a56404c4aa84a 100644
--- a/test/datasource/__snapshots__/docker.spec.js.snap
+++ b/test/datasource/__snapshots__/docker.spec.js.snap
@@ -29,6 +29,21 @@ exports[`api/docker getPkgReleases adds library/ prefix for Docker Hub (explicit
         "timeout": 10000,
       },
     ],
+    Array [
+      "https://index.docker.io/v2/",
+      Object {
+        "throwHttpErrors": false,
+      },
+    ],
+    Array [
+      "https://index.docker.io/v2/library/node/manifests/1.0.0",
+      Object {
+        "headers": Object {
+          "accept": "application/vnd.docker.distribution.manifest.v2+json",
+        },
+        "timeout": 10000,
+      },
+    ],
   ],
   "results": Array [
     Object {
@@ -59,6 +74,19 @@ exports[`api/docker getPkgReleases adds library/ prefix for Docker Hub (explicit
         "headers": Object {},
       },
     },
+    Object {
+      "isThrow": false,
+      "value": Object {
+        "headers": Object {},
+      },
+    },
+    Object {
+      "isThrow": false,
+      "value": Object {
+        "body": Object {},
+        "headers": Object {},
+      },
+    },
   ],
 }
 `;
@@ -92,6 +120,21 @@ exports[`api/docker getPkgReleases adds library/ prefix for Docker Hub (implicit
         "timeout": 10000,
       },
     ],
+    Array [
+      "https://index.docker.io/v2/",
+      Object {
+        "throwHttpErrors": false,
+      },
+    ],
+    Array [
+      "https://index.docker.io/v2/library/node/manifests/1.0.0",
+      Object {
+        "headers": Object {
+          "accept": "application/vnd.docker.distribution.manifest.v2+json",
+        },
+        "timeout": 10000,
+      },
+    ],
   ],
   "results": Array [
     Object {
@@ -122,6 +165,19 @@ exports[`api/docker getPkgReleases adds library/ prefix for Docker Hub (implicit
         "headers": Object {},
       },
     },
+    Object {
+      "isThrow": false,
+      "value": Object {
+        "headers": Object {},
+      },
+    },
+    Object {
+      "isThrow": false,
+      "value": Object {
+        "body": Object {},
+        "headers": Object {},
+      },
+    },
   ],
 }
 `;
@@ -155,6 +211,21 @@ exports[`api/docker getPkgReleases adds no library/ prefix for other registries
         "timeout": 10000,
       },
     ],
+    Array [
+      "https://k8s.gcr.io/v2/",
+      Object {
+        "throwHttpErrors": false,
+      },
+    ],
+    Array [
+      "https://k8s.gcr.io/v2/kubernetes-dashboard-amd64/manifests/1.0.0",
+      Object {
+        "headers": Object {
+          "accept": "application/vnd.docker.distribution.manifest.v2+json",
+        },
+        "timeout": 10000,
+      },
+    ],
   ],
   "results": Array [
     Object {
@@ -185,6 +256,19 @@ exports[`api/docker getPkgReleases adds no library/ prefix for other registries
         "headers": Object {},
       },
     },
+    Object {
+      "isThrow": false,
+      "value": Object {
+        "headers": Object {},
+      },
+    },
+    Object {
+      "isThrow": false,
+      "value": Object {
+        "body": Object {},
+        "headers": Object {},
+      },
+    },
   ],
 }
 `;
@@ -206,6 +290,12 @@ exports[`api/docker getPkgReleases uses custom registry in depName 1`] = `
         "timeout": 10000,
       },
     ],
+    Array [
+      "https://registry.company.com/v2/",
+      Object {
+        "throwHttpErrors": false,
+      },
+    ],
   ],
   "results": Array [
     Object {
@@ -225,6 +315,10 @@ exports[`api/docker getPkgReleases uses custom registry in depName 1`] = `
         "headers": Object {},
       },
     },
+    Object {
+      "isThrow": false,
+      "value": undefined,
+    },
   ],
 }
 `;
@@ -245,5 +339,20 @@ Array [
       "timeout": 10000,
     },
   ],
+  Array [
+    "https://registry.company.com/v2/",
+    Object {
+      "throwHttpErrors": false,
+    },
+  ],
+  Array [
+    "https://registry.company.com/v2/node/manifests/1.0.0",
+    Object {
+      "headers": Object {
+        "accept": "application/vnd.docker.distribution.manifest.v2+json",
+      },
+      "timeout": 10000,
+    },
+  ],
 ]
 `;
diff --git a/test/datasource/docker.spec.js b/test/datasource/docker.spec.js
index 812b5aa43982c05a91070149e0b3d9e886189d74..a81470ee2f171f10ff1ccadc27eb5842d2b4db49 100644
--- a/test/datasource/docker.spec.js
+++ b/test/datasource/docker.spec.js
@@ -198,6 +198,10 @@ describe('api/docker', () => {
         headers: {},
       });
       got.mockReturnValueOnce({ headers: {}, body: { tags } });
+      got.mockReturnValueOnce({
+        headers: {},
+      });
+      got.mockReturnValueOnce({ headers: {}, body: {} });
       const config = {
         datasource: 'docker',
         depName: 'node',
@@ -233,6 +237,10 @@ describe('api/docker', () => {
       });
       got.mockReturnValueOnce({ headers: {}, body: { token: 'some-token ' } });
       got.mockReturnValueOnce({ headers: {}, body: { tags } });
+      got.mockReturnValueOnce({
+        headers: {},
+      });
+      got.mockReturnValueOnce({ headers: {}, body: {} });
       const res = await getPkgReleases({
         datasource: 'docker',
         depName: 'node',
@@ -250,6 +258,10 @@ describe('api/docker', () => {
       });
       got.mockReturnValueOnce({ headers: {}, body: { token: 'some-token ' } });
       got.mockReturnValueOnce({ headers: {}, body: { tags } });
+      got.mockReturnValueOnce({
+        headers: {},
+      });
+      got.mockReturnValueOnce({ headers: {}, body: {} });
       const res = await getPkgReleases({
         datasource: 'docker',
         depName: 'docker.io/node',
@@ -267,6 +279,10 @@ describe('api/docker', () => {
       });
       got.mockReturnValueOnce({ headers: {}, body: { token: 'some-token ' } });
       got.mockReturnValueOnce({ headers: {}, body: { tags } });
+      got.mockReturnValueOnce({
+        headers: {},
+      });
+      got.mockReturnValueOnce({ headers: {}, body: {} });
       const res = await getPkgReleases({
         datasource: 'docker',
         depName: 'k8s.gcr.io/kubernetes-dashboard-amd64',