Skip to content

Commit c78736c

Browse files
committed
feat(Docker): avoid repulling existing images
1 parent cb85785 commit c78736c

File tree

1 file changed

+38
-15
lines changed

1 file changed

+38
-15
lines changed

admin/app/services/docker_service.ts

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -310,11 +310,7 @@ export class DockerService {
310310
}
311311
} catch (error) {
312312
logger.warn(`Error during container cleanup: ${error.message}`)
313-
this._broadcast(
314-
serviceName,
315-
'cleanup-warning',
316-
`Warning during cleanup: ${error.message}`
317-
)
313+
this._broadcast(serviceName, 'cleanup-warning', `Warning during cleanup: ${error.message}`)
318314
}
319315

320316
// Step 3: Clear volumes/data if needed
@@ -356,7 +352,7 @@ export class DockerService {
356352
// Step 5: Recreate the container
357353
this._broadcast(serviceName, 'recreating', `Recreating container...`)
358354
const containerConfig = this._parseContainerConfig(service.container_config)
359-
355+
360356
// Execute installation asynchronously and handle cleanup
361357
this._createContainer(service, containerConfig).catch(async (error) => {
362358
logger.error(`Reinstallation failed for ${serviceName}: ${error.message}`)
@@ -427,14 +423,23 @@ export class DockerService {
427423
}
428424
}
429425

430-
// Start pulling the Docker image and wait for it to complete
431-
const pullStream = await this.docker.pull(service.container_image)
432-
this._broadcast(
433-
service.service_name,
434-
'pulling',
435-
`Pulling Docker image ${service.container_image}...`
436-
)
437-
await new Promise((res) => this.docker.modem.followProgress(pullStream, res))
426+
const imageExists = await this._checkImageExists(service.container_image)
427+
if (imageExists) {
428+
this._broadcast(
429+
service.service_name,
430+
'image-exists',
431+
`Docker image ${service.container_image} already exists locally. Skipping pull...`
432+
)
433+
} else {
434+
// Start pulling the Docker image and wait for it to complete
435+
const pullStream = await this.docker.pull(service.container_image)
436+
this._broadcast(
437+
service.service_name,
438+
'pulling',
439+
`Pulling Docker image ${service.container_image}...`
440+
)
441+
await new Promise((res) => this.docker.modem.followProgress(pullStream, res))
442+
}
438443

439444
if (service.service_name === DockerService.KIWIX_SERVICE_NAME) {
440445
await this._runPreinstallActions__KiwixServe()
@@ -466,7 +471,7 @@ export class DockerService {
466471
[DockerService.NOMAD_NETWORK]: {},
467472
},
468473
},
469-
})
474+
}),
470475
})
471476

472477
this._broadcast(
@@ -632,4 +637,22 @@ export class DockerService {
632637
throw new Error(`Invalid container configuration: ${error.message}`)
633638
}
634639
}
640+
641+
/**
642+
* Check if a Docker image exists locally.
643+
* @param imageName - The name and tag of the image (e.g., "nginx:latest")
644+
* @returns - True if the image exists locally, false otherwise
645+
*/
646+
private async _checkImageExists(imageName: string): Promise<boolean> {
647+
try {
648+
const images = await this.docker.listImages()
649+
650+
// Check if any image has a RepoTag that matches the requested image
651+
return images.some((image) => image.RepoTags && image.RepoTags.includes(imageName))
652+
} catch (error) {
653+
logger.warn(`Error checking if image exists: ${error.message}`)
654+
// If run into an error, assume the image does not exist
655+
return false
656+
}
657+
}
635658
}

0 commit comments

Comments
 (0)