docker: better error message when out of disk space
This commit is contained in:
@@ -40,6 +40,7 @@ const apps = require('./apps.js'),
|
||||
delay = require('./delay.js'),
|
||||
Docker = require('dockerode'),
|
||||
paths = require('./paths.js'),
|
||||
promiseRetry = require('./promise-retry.js'),
|
||||
services = require('./services.js'),
|
||||
settings = require('./settings.js'),
|
||||
shell = require('./shell.js'),
|
||||
@@ -113,24 +114,28 @@ async function pullImage(manifest) {
|
||||
if (error) throw new BoxError(BoxError.DOCKER_ERROR, `Unable to pull image ${manifest.dockerImage}. Please check the network or if the image needs authentication. statusCode: ${error.statusCode}`);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
// https://github.com/dotcloud/docker/issues/1074 says each status message
|
||||
// is emitted as a chunk
|
||||
// https://github.com/dotcloud/docker/issues/1074 says each status message is emitted as a chunk
|
||||
let layerError = null;
|
||||
stream.on('data', function (chunk) {
|
||||
const data = safe.JSON.parse(chunk) || { };
|
||||
debug('pullImage: %j', data);
|
||||
|
||||
// The data.status here is useless because this is per layer as opposed to per image
|
||||
if (!data.status && data.error) {
|
||||
debug('pullImage error %s: %s', manifest.dockerImage, data.errorDetail.message);
|
||||
if (!data.status && data.error) { // data is { errorDetail: { message: xx } , error: xx }
|
||||
debug(`pullImage error ${manifest.dockerImage}: ${data.errorDetail.message}`);
|
||||
layerError = data.errorDetail;
|
||||
}
|
||||
});
|
||||
|
||||
stream.on('end', function () {
|
||||
debug('downloaded image %s', manifest.dockerImage);
|
||||
resolve();
|
||||
debug(`downloaded image ${manifest.dockerImage} . error: ${!!layerError}`);
|
||||
|
||||
if (!layerError) return resolve();
|
||||
|
||||
reject(new BoxError(layerError.includes('no space') ? BoxError.FS_ERROR : BoxError.DOCKER_ERROR, layerError.message));
|
||||
});
|
||||
|
||||
stream.on('error', function (error) {
|
||||
stream.on('error', function (error) { // this is only hit for stream error and not for some download error
|
||||
debug('error pulling image %s: %j', manifest.dockerImage, error);
|
||||
reject(new BoxError(BoxError.DOCKER_ERROR, error.message));
|
||||
});
|
||||
@@ -147,14 +152,9 @@ async function downloadImage(manifest) {
|
||||
const [error, result] = await safe(image.inspect());
|
||||
if (!error && result) return; // image is already present locally
|
||||
|
||||
for (let times = 0; times < 10; times++) {
|
||||
debug(`downloadImage: pulling image. attempt ${times+1}`);
|
||||
const [pullError] = await safe(pullImage(manifest));
|
||||
if (pullError && pullError.reason === BoxError.NOT_FOUND) throw pullError;
|
||||
if (!pullError) break;
|
||||
|
||||
await delay(5000);
|
||||
}
|
||||
await promiseRetry({ times: 10, interval: 5000, retry: (pullError) => pullError.reason !== BoxError.NOT_FOUND && pullError.reason !== BoxError.FS_ERROR }, async () => {
|
||||
await pullImage(manifest);
|
||||
});
|
||||
}
|
||||
|
||||
async function getVolumeMounts(app) {
|
||||
|
||||
Reference in New Issue
Block a user