diff --git a/lib/datasource/docker/__snapshots__/index.spec.ts.snap b/lib/datasource/docker/__snapshots__/index.spec.ts.snap
index c2017225d3e206e96604fee9b7f429c143b6955d..701d6a7a2047b2b3969a5858413eac074649f07b 100644
--- a/lib/datasource/docker/__snapshots__/index.spec.ts.snap
+++ b/lib/datasource/docker/__snapshots__/index.spec.ts.snap
@@ -14,7 +14,6 @@ Array [
   },
   Object {
     "headers": Object {
-      "accept": "application/json",
       "accept-encoding": "gzip, deflate",
       "host": "123456789.dkr.ecr.us-east-1.amazonaws.com",
       "user-agent": "https://github.com/renovatebot/renovate",
@@ -30,7 +29,6 @@ Array [
   Object {
     "headers": Object {
       "accept-encoding": "gzip, deflate",
-      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
       "host": "123456789.dkr.ecr.us-east-1.amazonaws.com",
       "user-agent": "https://github.com/renovatebot/renovate",
     },
@@ -39,7 +37,6 @@ Array [
   },
   Object {
     "headers": Object {
-      "accept": "application/json",
       "accept-encoding": "gzip, deflate",
       "host": "123456789.dkr.ecr.us-east-1.amazonaws.com",
       "user-agent": "https://github.com/renovatebot/renovate",
@@ -118,7 +115,6 @@ Array [
   Object {
     "headers": Object {
       "accept-encoding": "gzip, deflate",
-      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
       "host": "index.docker.io",
       "user-agent": "https://github.com/renovatebot/renovate",
     },
@@ -129,7 +125,6 @@ Array [
     "headers": Object {
       "accept": "application/json",
       "accept-encoding": "gzip, deflate",
-      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
       "host": "auth.docker.io",
       "user-agent": "https://github.com/renovatebot/renovate",
     },
@@ -164,7 +159,6 @@ Array [
   },
   Object {
     "headers": Object {
-      "accept": "application/json",
       "accept-encoding": "gzip, deflate",
       "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
       "host": "index.docker.io",
@@ -176,6 +170,32 @@ Array [
 ]
 `;
 
+exports[`datasource/docker/index getDigest returns null if empty header 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
+      "host": "index.docker.io",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://index.docker.io/v2/",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/vnd.docker.distribution.manifest.v2+json",
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
+      "host": "index.docker.io",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://index.docker.io/v2/library/some-dep/manifests/some-new-value",
+  },
+]
+`;
+
 exports[`datasource/docker/index getDigest returns null if errored 1`] = `
 Array [
   Object {
@@ -242,7 +262,6 @@ Array [
   },
   Object {
     "headers": Object {
-      "accept": "application/json",
       "accept-encoding": "gzip, deflate",
       "authorization": "Basic abcdef",
       "host": "123456789.dkr.ecr.us-east-1.amazonaws.com",
@@ -279,7 +298,6 @@ Array [
   },
   Object {
     "headers": Object {
-      "accept": "application/json",
       "accept-encoding": "gzip, deflate",
       "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
       "host": "index.docker.io",
@@ -547,6 +565,29 @@ Array [
 ]
 `;
 
+exports[`datasource/docker/index getReleases returns null if no auth 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept-encoding": "gzip, deflate",
+      "host": "index.docker.io",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://index.docker.io/v2/",
+  },
+  Object {
+    "headers": Object {
+      "accept-encoding": "gzip, deflate",
+      "host": "index.docker.io",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://index.docker.io/v2/",
+  },
+]
+`;
+
 exports[`datasource/docker/index getReleases returns null if no token 1`] = `
 Array [
   Object {
@@ -599,6 +640,166 @@ Array [
 ]
 `;
 
+exports[`datasource/docker/index getReleases supports labels 1`] = `
+Object {
+  "dockerRegistry": "https://registry.company.com",
+  "dockerRepository": "node",
+  "releases": Array [],
+  "sourceUrl": "https://github.com/renovatebot/renovate",
+}
+`;
+
+exports[`datasource/docker/index getReleases supports labels 2`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
+      "host": "registry.company.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.company.com/v2/",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
+      "host": "registry.company.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.company.com/v2/node/tags/list?n=10000",
+  },
+  Object {
+    "headers": Object {
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
+      "host": "registry.company.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.company.com/v2/",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/vnd.docker.distribution.manifest.v2+json",
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
+      "host": "registry.company.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.company.com/v2/node/manifests/latest",
+  },
+  Object {
+    "headers": Object {
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
+      "host": "registry.company.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.company.com/v2/",
+  },
+  Object {
+    "headers": Object {
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
+      "host": "registry.company.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.company.com/v2/node/blobs/some-config-digest",
+  },
+]
+`;
+
+exports[`datasource/docker/index getReleases supports redirect 1`] = `
+Object {
+  "dockerRegistry": "https://registry.company.com",
+  "dockerRepository": "node",
+  "releases": Array [],
+}
+`;
+
+exports[`datasource/docker/index getReleases supports redirect 2`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
+      "host": "registry.company.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.company.com/v2/",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
+      "host": "registry.company.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.company.com/v2/node/tags/list?n=10000",
+  },
+  Object {
+    "headers": Object {
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
+      "host": "registry.company.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.company.com/v2/",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/vnd.docker.distribution.manifest.v2+json",
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
+      "host": "registry.company.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.company.com/v2/node/manifests/latest",
+  },
+  Object {
+    "headers": Object {
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
+      "host": "registry.company.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.company.com/v2/",
+  },
+  Object {
+    "headers": Object {
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk",
+      "host": "registry.company.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://registry.company.com/v2/node/blobs/some-config-digest",
+  },
+  Object {
+    "headers": Object {
+      "accept-encoding": "gzip, deflate",
+      "host": "abc.s3.amazon.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "GET",
+    "url": "https://abc.s3.amazon.com/some-config-digest?X-Amz-Algorithm=xxxx",
+  },
+]
+`;
+
 exports[`datasource/docker/index getReleases uses custom registry in depName 1`] = `
 Array [
   Object {
diff --git a/lib/datasource/docker/index.spec.ts b/lib/datasource/docker/index.spec.ts
index e837fd28a5032333bcea3a6fbe3be7c12ec274fd..b6f5b38d80284a5d9d51b56013657f74406343c2 100644
--- a/lib/datasource/docker/index.spec.ts
+++ b/lib/datasource/docker/index.spec.ts
@@ -75,6 +75,20 @@ describe(getName(__filename), () => {
       expect(res).toBeNull();
       expect(httpMock.getTrace()).toMatchSnapshot();
     });
+    it('returns null if empty header', async () => {
+      httpMock
+        .scope(baseUrl)
+        .get('/')
+        .reply(200, { token: 'some-token' })
+        .get('/library/some-dep/manifests/some-new-value')
+        .reply(200, undefined, { 'docker-content-digest': '' });
+      const res = await getDigest(
+        { datasource: 'docker', depName: 'some-dep' },
+        'some-new-value'
+      );
+      expect(res).toBeNull();
+      expect(httpMock.getTrace()).toMatchSnapshot();
+    });
     it('returns digest', async () => {
       httpMock
         .scope(baseUrl)
@@ -91,6 +105,8 @@ describe(getName(__filename), () => {
           '/token?service=registry.docker.io&scope=repository:library/some-dep:pull'
         )
         .reply(200, { token: 'some-token' });
+
+      hostRules.find.mockReturnValue({});
       const res = await getDigest({
         datasource: 'docker',
         depName: 'some-dep',
@@ -262,6 +278,7 @@ describe(getName(__filename), () => {
       AWSMock.restore('ECR');
     });
     it('continues without token if ECR authentication fails', async () => {
+      hostRules.find.mockReturnValue({});
       httpMock
         .scope(amazonUrl)
         .get('/')
@@ -320,7 +337,7 @@ describe(getName(__filename), () => {
         .get(
           '/token?service=registry.docker.io&scope=repository:library/some-other-dep:pull'
         )
-        .reply(200, { token: 'some-token' });
+        .reply(200, { access_token: 'some-token' });
       const res = await getDigest(
         { datasource: 'docker', depName: 'some-other-dep' },
         '8.0.0-alpine'
@@ -522,5 +539,92 @@ describe(getName(__filename), () => {
       expect(res).toBeNull();
       expect(httpMock.getTrace()).toMatchSnapshot();
     });
+
+    it('returns null if no auth', async () => {
+      hostRules.find.mockReturnValue({});
+      httpMock
+        .scope(baseUrl)
+        .get('/')
+        .reply(200, undefined, {
+          'www-authenticate': 'Basic realm="My Private Docker Registry Server"',
+        })
+        .get('/')
+        .reply(403);
+      const res = await getPkgReleases({
+        datasource: docker.id,
+        depName: 'node',
+      });
+      expect(res).toBeNull();
+      expect(httpMock.getTrace()).toMatchSnapshot();
+    });
+
+    it('supports labels', async () => {
+      httpMock
+        .scope('https://registry.company.com/v2')
+        .get('/')
+        .times(3)
+        .reply(200)
+        .get('/node/tags/list?n=10000')
+        .reply(200, { tags: ['latest'] })
+        .get('/node/manifests/latest')
+        .reply(200, {
+          schemaVersion: 2,
+          config: { digest: 'some-config-digest' },
+        })
+        .get('/node/blobs/some-config-digest')
+        .reply(200, {
+          config: {
+            Labels: {
+              'org.opencontainers.image.source':
+                'https://github.com/renovatebot/renovate',
+            },
+          },
+        });
+      const res = await getPkgReleases({
+        datasource: docker.id,
+        depName: 'registry.company.com/node',
+      });
+      const trace = httpMock.getTrace();
+      expect(res).toMatchSnapshot();
+      expect(trace).toMatchSnapshot();
+    });
+
+    it('supports redirect', async () => {
+      httpMock
+        .scope('https://registry.company.com/v2')
+        .get('/')
+        .times(3)
+        .reply(200)
+        .get('/node/tags/list?n=10000')
+        .reply(200, { tags: ['latest'] })
+        .get('/node/manifests/latest')
+        .reply(200, {
+          schemaVersion: 2,
+          config: { digest: 'some-config-digest' },
+        })
+        .get('/node/blobs/some-config-digest')
+        .reply(302, undefined, {
+          location:
+            'https://abc.s3.amazon.com/some-config-digest?X-Amz-Algorithm=xxxx',
+        });
+      httpMock
+        .scope('https://abc.s3.amazon.com')
+        .get('/some-config-digest')
+        .query({ 'X-Amz-Algorithm': 'xxxx' })
+        .reply(200, {
+          config: {},
+        });
+      const res = await getPkgReleases({
+        datasource: docker.id,
+        depName: 'registry.company.com/node',
+      });
+      const trace = httpMock.getTrace();
+      expect(res).toMatchSnapshot();
+      expect(trace).toMatchSnapshot();
+      expect(trace[1].headers.authorization).toBe(
+        'Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk'
+      );
+      expect(trace[trace.length - 1].headers.authorization).toBeUndefined();
+    });
   });
 });
diff --git a/lib/datasource/docker/index.ts b/lib/datasource/docker/index.ts
index bb7d57448347109be34a94ecc6ffa2099f97c9d9..6fd9874dc7b1bd172b4db37a12e5c4197d4edd3f 100644
--- a/lib/datasource/docker/index.ts
+++ b/lib/datasource/docker/index.ts
@@ -155,7 +155,6 @@ async function getAuthHeaders(
     const opts: HostRule & {
       headers?: Record<string, string>;
     } = hostRules.find({ hostType: id, url: apiCheckUrl });
-    opts.json = true;
     if (ecrRegex.test(registry)) {
       const [, region] = ecrRegex.exec(registry);
       const auth = await getECRAuthToken(region, opts);
@@ -449,7 +448,6 @@ async function getTags(
  *  - Return the labels for the requested image
  */
 
-// istanbul ignore next
 async function getLabels(
   registry: string,
   repository: string,
@@ -475,6 +473,7 @@ async function getLabels(
     // If getting the manifest fails here, then abort
     // This means that the latest tag doesn't have a manifest, which shouldn't
     // be possible
+    // istanbul ignore if
     if (!manifestResponse) {
       logger.debug(
         {
@@ -498,6 +497,7 @@ async function getLabels(
     let labels: Record<string, string> = {};
     const configDigest = manifest.config.digest;
     const headers = await getAuthHeaders(registry, repository);
+    // istanbul ignore if: Should never be happen
     if (!headers) {
       logger.debug('No docker auth found - returning');
       return {};
@@ -519,7 +519,7 @@ async function getLabels(
     const cacheMinutes = 60;
     await packageCache.set(cacheNamespace, cacheKey, labels, cacheMinutes);
     return labels;
-  } catch (err) {
+  } catch (err) /* istanbul ignore next: should be tested in future */ {
     if (err instanceof ExternalHostError) {
       throw err;
     }
@@ -605,7 +605,6 @@ export async function getReleases({
 
   const latestTag = tags.includes('latest') ? 'latest' : tags[tags.length - 1];
   const labels = await getLabels(registry, repository, latestTag);
-  // istanbul ignore if
   if (labels && 'org.opencontainers.image.source' in labels) {
     ret.sourceUrl = labels['org.opencontainers.image.source'];
   }
diff --git a/lib/datasource/terraform-module/index.spec.ts b/lib/datasource/terraform-module/index.spec.ts
index a5d7a0f1331d2297c576564473c954d6d07b292e..931520dc74b03fb9b8acd071f88d930e6bd0a368 100644
--- a/lib/datasource/terraform-module/index.spec.ts
+++ b/lib/datasource/terraform-module/index.spec.ts
@@ -139,7 +139,7 @@ describe('datasource/terraform-module', () => {
         .reply(200, serviceDiscoveryCustomResult);
       const res = await getPkgReleases({
         datasource,
-        registryUrls: ['terraform.foo.bar'],
+        registryUrls: ['https://terraform.foo.bar'],
         depName: 'hashicorp/consul/aws',
       });
       expect(res).toMatchSnapshot();