diff --git a/lib/datasource/docker.js b/lib/datasource/docker.js
index 35f1b3a1be18cf41c052dea31702580f5747421f..23fb2efb17b3911f9ca926694df76982291098aa 100644
--- a/lib/datasource/docker.js
+++ b/lib/datasource/docker.js
@@ -1,17 +1,31 @@
 const got = require('got');
+const parseLinkHeader = require('parse-link-header');
 
 module.exports = {
   getDigest,
   getTags,
 };
 
-const registry = 'https://index.docker.io/v2';
+function massageRegistry(input) {
+  let registry = input;
+  if (!registry || registry === 'docker.io') {
+    registry = 'index.docker.io'; // eslint-disable-line no-param-reassign
+  }
+  if (!registry.match('$https?://')) {
+    registry = `https://${registry}`; // eslint-disable-line no-param-reassign
+  }
+  return registry;
+}
 
 function getRepository(pkgName) {
   return pkgName.includes('/') ? pkgName : `library/${pkgName}`;
 }
 
-async function getHeaders(repository) {
+async function getAuthHeaders(registry, repository) {
+  // istanbul ignore if
+  if (registry !== 'https://index.docker.io') {
+    return {};
+  }
   try {
     const authUrl = `https://auth.docker.io/token?service=registry.docker.io&scope=repository:${repository}:pull`;
     logger.debug(`Obtaining docker registry token for ${repository}`);
@@ -35,18 +49,19 @@ async function getHeaders(repository) {
   }
 }
 
-async function getDigest(name, tag = 'latest') {
+async function getDigest(registry, name, tag = 'latest') {
+  logger.debug(`getDigest(${registry}, ${name}, ${tag})`);
+  const massagedRegistry = massageRegistry(registry);
+  const repository = getRepository(name);
   try {
-    const repository = getRepository(name);
-    const headers = await getHeaders(repository);
-    const url = `${registry}/${repository}/manifests/${tag}`;
-    const digest = (await got(url, { json: true, headers })).headers[
-      'docker-content-digest'
-    ];
+    const url = `${massagedRegistry}/v2/${repository}/manifests/${tag}`;
+    const headers = await getAuthHeaders(massagedRegistry, repository);
+    headers.accept = 'application/vnd.docker.distribution.manifest.v2+json';
+    const digest = (await got(url, { json: true, headers, timeout: 10000 }))
+      .headers['docker-content-digest'];
     logger.debug({ digest }, 'Got docker digest');
     return digest;
-  } catch (err) {
-    // istanbul ignore if
+  } catch (err) /* istanbul ignore next */ {
     if (err.statusCode === 401) {
       logger.info(
         { err, body: err.response ? err.response.body : undefined, name, tag },
@@ -54,7 +69,6 @@ async function getDigest(name, tag = 'latest') {
       );
       return null;
     }
-    // istanbul ignore if
     if (err.statusCode === 404) {
       logger.info(
         { err, body: err.response ? err.response.body : undefined, name, tag },
@@ -62,7 +76,6 @@ async function getDigest(name, tag = 'latest') {
       );
       return null;
     }
-    // istanbul ignore if
     if (err.statusCode >= 500 && err.statusCode < 600) {
       logger.warn(
         { err, body: err.response ? err.response.body : undefined, name, tag },
@@ -70,6 +83,14 @@ async function getDigest(name, tag = 'latest') {
       );
       throw new Error('registry-failure');
     }
+    if (err.code === 'ETIMEDOUT') {
+      logger.info(
+        { massagedRegistry },
+        'Timeout when attempting to connect to docker registry'
+      );
+      logger.debug({ err });
+      return null;
+    }
     logger.info(
       { err, body: err.response ? err.response.body : undefined, name, tag },
       'Unknown Error looking up docker image digest'
@@ -78,20 +99,38 @@ async function getDigest(name, tag = 'latest') {
   }
 }
 
-async function getTags(name) {
+async function getTags(registry, name) {
+  logger.debug(`getTags(${registry}, ${name})`);
+  const massagedRegistry = massageRegistry(registry);
+  const repository = getRepository(name);
   try {
-    const repository = getRepository(name);
-    const url = `${registry}/${repository}/tags/list?n=10000`;
-    const headers = await getHeaders(repository);
-    const { tags } = (await got(url, { json: true, headers })).body;
-    logger.debug({ tags }, 'Got docker tags');
+    let url = `${massagedRegistry}/v2/${repository}/tags/list?n=10000`;
+    const headers = await getAuthHeaders(massagedRegistry, repository);
+    let tags = [];
+    let page = 1;
+    do {
+      const res = await got(url, { json: true, headers, timeout: 10000 });
+      tags = tags.concat(res.body.tags);
+      const linkHeader = parseLinkHeader(res.headers.link);
+      url = linkHeader && linkHeader.next ? linkHeader.next.url : null;
+      page += 1;
+    } while (url && page < 20);
+    logger.debug({ length: tags.length }, 'Got docker tags');
+    logger.trace({ tags });
     return tags;
-  } catch (err) {
-    // istanbul ignore if
+  } catch (err) /* istanbul ignore next */ {
     if (err.statusCode >= 500 && err.statusCode < 600) {
       logger.warn({ err }, 'docker registry failure: internal error');
       throw new Error('registry-failure');
     }
+    if (err.code === 'ETIMEDOUT') {
+      logger.info(
+        { massagedRegistry },
+        'Timeout when attempting to connect to docker registry'
+      );
+      logger.debug({ err });
+      return null;
+    }
     logger.warn({ err, name }, 'Error getting docker image tags');
     return null;
   }
diff --git a/lib/manager/docker/package.js b/lib/manager/docker/package.js
index b3d04dc7fd5c282e859fd2b6d997badd165f7951..fa70d03b094bb79e390a8d8d1c2e243520fe06b5 100644
--- a/lib/manager/docker/package.js
+++ b/lib/manager/docker/package.js
@@ -11,7 +11,6 @@ module.exports = {
 async function getPackageUpdates(config) {
   const {
     dockerRegistry,
-    currentFrom,
     depName,
     currentDepTag,
     currentTag,
@@ -19,17 +18,14 @@ async function getPackageUpdates(config) {
     unstablePattern,
     ignoreUnstable,
   } = config;
-  if (dockerRegistry) {
-    logger.info(
-      { currentFrom, dockerRegistry },
-      'Skipping Dockerfile image with custom host'
-    );
-    return [];
-  }
   const upgrades = [];
   if (currentDigest || config.pinDigests) {
     logger.debug('Checking docker pinDigests');
-    const newDigest = await dockerApi.getDigest(depName, currentTag);
+    const newDigest = await dockerApi.getDigest(
+      dockerRegistry,
+      depName,
+      currentTag
+    );
     if (!newDigest) {
       logger.debug({ content: config.content }, 'Dockerfile no digest');
     }
@@ -38,7 +34,13 @@ async function getPackageUpdates(config) {
       upgrade.newTag = currentTag || 'latest';
       upgrade.newDigest = newDigest;
       upgrade.newDigestShort = newDigest.slice(7, 13);
-      upgrade.newFrom = `${depName}:${upgrade.newTag}@${newDigest}`;
+      if (dockerRegistry) {
+        upgrade.newFrom = `${dockerRegistry}/`;
+      } else {
+        upgrade.newFrom = '';
+      }
+      upgrade.newFrom += `${depName}:${upgrade.newTag}@${newDigest}`;
+
       if (currentDigest) {
         upgrade.type = 'digest';
         upgrade.isDigest = true;
@@ -62,7 +64,7 @@ async function getPackageUpdates(config) {
     const currentMajor = semver.major(padRange(tagVersion));
     const currentlyStable = isStable(tagVersion, unstablePattern);
     let versionList = [];
-    const allTags = await dockerApi.getTags(config.depName);
+    const allTags = await dockerApi.getTags(dockerRegistry, config.depName);
     if (allTags) {
       versionList = allTags
         .filter(tag => getSuffix(tag) === tagSuffix)
@@ -130,15 +132,20 @@ async function getPackageUpdates(config) {
       };
       upgrade.newVersion = newTag;
       upgrade.newDepTag = `${config.depName}:${upgrade.newTag}`;
-      let newFrom = upgrade.newDepTag;
+      if (dockerRegistry) {
+        upgrade.newFrom = `${dockerRegistry}/`;
+      } else {
+        upgrade.newFrom = '';
+      }
+      upgrade.newFrom += `${depName}:${upgrade.newTag}`;
       if (config.currentDigest || config.pinDigests) {
         upgrade.newDigest = await dockerApi.getDigest(
+          dockerRegistry,
           config.depName,
           upgrade.newTag
         );
-        newFrom = `${newFrom}@${upgrade.newDigest}`;
+        upgrade.newFrom += `@${upgrade.newDigest}`;
       }
-      upgrade.newFrom = newFrom;
       if (newVersionMajor > currentMajor) {
         upgrade.type = 'major';
         upgrade.isMajor = true;
diff --git a/lib/manager/docker/update.js b/lib/manager/docker/update.js
index 0a2c868d7f8a76b0f1be3364a0ce1118008add31..6d39255587014855cbeee7f175190b5c50f5b861 100644
--- a/lib/manager/docker/update.js
+++ b/lib/manager/docker/update.js
@@ -6,9 +6,9 @@ function setNewValue(currentFileContent, upgrade) {
   try {
     logger.debug(`setNewValue: ${upgrade.newFrom}`);
     const oldLine = new RegExp(
-      `(^|\\n)${upgrade.fromPrefix}(\\s+)${upgrade.depName}[^\\s]*(\\s?)${
-        upgrade.fromSuffix
-      }\\n`
+      `(^|\\n)${upgrade.fromPrefix}(\\s+)${
+        upgrade.dockerRegistry ? upgrade.dockerRegistry + '/' : ''
+      }${upgrade.depName}[^\\s]*(\\s?)${upgrade.fromSuffix}\\n`
     );
     const newLine = `$1${upgrade.fromPrefix}$2${upgrade.newFrom}$3${
       upgrade.fromSuffix
diff --git a/test/datasource/docker.spec.js b/test/datasource/docker.spec.js
index cbd7efaa105cb3884c082c8860398979a9c62ad8..d0b1d58714f9804ab1aa0fcc6b117fe10e8bdb32 100644
--- a/test/datasource/docker.spec.js
+++ b/test/datasource/docker.spec.js
@@ -10,12 +10,12 @@ describe('api/docker', () => {
     });
     it('returns null if no token', async () => {
       got.mockReturnValueOnce({ body: {} });
-      const res = await docker.getDigest('some-name', undefined);
+      const res = await docker.getDigest(undefined, 'some-name', undefined);
       expect(res).toBe(null);
     });
     it('returns null if errored', async () => {
       got.mockReturnValueOnce({ body: { token: 'some-token' } });
-      const res = await docker.getDigest('some-name', undefined);
+      const res = await docker.getDigest(undefined, 'some-name', undefined);
       expect(res).toBe(null);
     });
     it('returns digest', async () => {
@@ -23,7 +23,7 @@ describe('api/docker', () => {
       got.mockReturnValueOnce({
         headers: { 'docker-content-digest': 'some-digest' },
       });
-      const res = await docker.getDigest('some-name', undefined);
+      const res = await docker.getDigest(undefined, 'some-name', undefined);
       expect(res).toBe('some-digest');
     });
     it('supports scoped names', async () => {
@@ -31,26 +31,26 @@ describe('api/docker', () => {
       got.mockReturnValueOnce({
         headers: { 'docker-content-digest': 'some-digest' },
       });
-      const res = await docker.getDigest('some/name', undefined);
+      const res = await docker.getDigest(undefined, 'some/name', undefined);
       expect(res).toBe('some-digest');
     });
   });
   describe('getTags', () => {
     it('returns null if no token', async () => {
       got.mockReturnValueOnce({ body: {} });
-      const res = await docker.getTags('node');
+      const res = await docker.getTags(undefined, 'node');
       expect(res).toBe(null);
     });
     it('returns tags', async () => {
       const tags = ['a', 'b'];
-      got.mockReturnValueOnce({ body: { token: 'some-token ' } });
-      got.mockReturnValueOnce({ body: { tags } });
-      const res = await docker.getTags('my/node');
-      expect(res).toBe(tags);
+      got.mockReturnValueOnce({ headers: {}, body: { token: 'some-token ' } });
+      got.mockReturnValueOnce({ headers: {}, body: { tags } });
+      const res = await docker.getTags(undefined, 'my/node');
+      expect(res).toEqual(tags);
     });
     it('returns null on error', async () => {
       got.mockReturnValueOnce({});
-      const res = await docker.getTags('node');
+      const res = await docker.getTags(undefined, 'node');
       expect(res).toBe(null);
     });
   });
diff --git a/test/manager/docker/__snapshots__/package.spec.js.snap b/test/manager/docker/__snapshots__/package.spec.js.snap
index 6eec3282adecfeb6d5f0f57b9762585c53fc83e3..f891a37523558ed4787b889c30ef925fa698482b 100644
--- a/test/manager/docker/__snapshots__/package.spec.js.snap
+++ b/test/manager/docker/__snapshots__/package.spec.js.snap
@@ -37,6 +37,19 @@ Array [
 ]
 `;
 
+exports[`lib/workers/package/docker getPackageUpdates returns a digest when registry is present 1`] = `
+Array [
+  Object {
+    "isDigest": true,
+    "newDigest": "sha256:1234567890",
+    "newDigestShort": "123456",
+    "newFrom": "docker.io/some-dep:1.0.0@sha256:1234567890",
+    "newTag": "1.0.0",
+    "type": "digest",
+  },
+]
+`;
+
 exports[`lib/workers/package/docker getPackageUpdates returns major and minor upgrades 1`] = `
 Array [
   Object {
@@ -118,7 +131,7 @@ Array [
     "isMajor": true,
     "newDepTag": "some-dep:3.0.0",
     "newDigest": "sha256:one",
-    "newFrom": "some-dep:3.0.0@sha256:one",
+    "newFrom": "docker.io/some-dep:3.0.0@sha256:one",
     "newTag": "3.0.0",
     "newVersion": "3.0.0",
     "newVersionMajor": "3",
diff --git a/test/manager/docker/package.spec.js b/test/manager/docker/package.spec.js
index 7ee98d2fa53f2af051d198698ac5c2b66fa151ec..4105764f5e9dd96d55338e074786e27bd594a878 100644
--- a/test/manager/docker/package.spec.js
+++ b/test/manager/docker/package.spec.js
@@ -47,6 +47,15 @@ describe('lib/workers/package/docker', () => {
       expect(res).toHaveLength(1);
       expect(res[0].type).toEqual('digest');
     });
+    it('returns a digest when registry is present', async () => {
+      config.dockerRegistry = 'docker.io';
+      config.currentFrom = 'docker.io/some-dep:1.0.0@sha256:abcdefghijklmnop';
+      dockerApi.getDigest.mockReturnValueOnce('sha256:1234567890');
+      const res = await docker.getPackageUpdates(config);
+      expect(res).toMatchSnapshot();
+      expect(res).toHaveLength(1);
+      expect(res[0].type).toEqual('digest');
+    });
     it('adds latest tag', async () => {
       delete config.currentTag;
       dockerApi.getDigest.mockReturnValueOnce('sha256:1234567890');
@@ -67,6 +76,7 @@ describe('lib/workers/package/docker', () => {
       expect(await docker.getPackageUpdates(config)).toEqual([]);
     });
     it('returns only one upgrade if automerging major', async () => {
+      config.dockerRegistry = 'docker.io';
       dockerApi.getDigest.mockReturnValueOnce(config.currentDigest);
       dockerApi.getDigest.mockReturnValueOnce('sha256:one');
       dockerApi.getTags.mockReturnValueOnce([