diff --git a/common/global.d.ts b/common/global.d.ts index 8a392758f..85723261f 100644 --- a/common/global.d.ts +++ b/common/global.d.ts @@ -48,6 +48,7 @@ declare global { interface IGlobalInstanceDockerConfig { containerName?: string; + pullPolicy?: boolean; image?: string; memory?: number; ports?: string[]; diff --git a/daemon/package-lock.json b/daemon/package-lock.json index 8229f1c9e..945009723 100644 --- a/daemon/package-lock.json +++ b/daemon/package-lock.json @@ -4726,10 +4726,9 @@ } }, "node_modules/tar-fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz", - "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", - "license": "MIT", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -9071,9 +9070,9 @@ "dev": true }, "tar-fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz", - "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "requires": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", diff --git a/daemon/src/entity/commands/docker/docker_pull.ts b/daemon/src/entity/commands/docker/docker_pull.ts index 3f1bda09a..775cb28d3 100644 --- a/daemon/src/entity/commands/docker/docker_pull.ts +++ b/daemon/src/entity/commands/docker/docker_pull.ts @@ -50,28 +50,32 @@ export default class DockerPullCommand extends InstanceCommand { async exec(instance: Instance) { const imageName = instance.config.docker.image; + const pullPolicy = instance.config.docker.pullPolicy; if (!imageName) throw new Error(t("TXT_CODE_17be5f70")); const cachedStartCount = instance.startCount; // If the image exists, there is no need to pull again. - if (await checkImage(imageName)) return; + if(pullPolicy === false ) { + if (await checkImage(imageName)) return; + } else { - try { - const docker = new DefaultDocker(); - instance.println("CONTAINER", t("TXT_CODE_2fa46b8c") + imageName); - instance.asynchronousTask = this; + try { + const docker = new DefaultDocker(); + instance.println("CONTAINER", t("TXT_CODE_2fa46b8c") + imageName); + instance.asynchronousTask = this; - await docker.pull(imageName, {}); + await docker.pull(imageName, {}); - await this.awaitImageDone(instance, imageName); - if (cachedStartCount !== instance.startCount) return; - instance.println("CONTAINER", t("TXT_CODE_c68b0bef")); - } catch (err: any) { - if (cachedStartCount !== instance.startCount) return; - throw new Error([t("TXT_CODE_db37b7f9"), err?.message].join("\n")); - } finally { - this.stopped(instance); - } + await this.awaitImageDone(instance, imageName); + if (cachedStartCount !== instance.startCount) return; + instance.println("CONTAINER", t("TXT_CODE_c68b0bef")); + } catch (err: any) { + if (cachedStartCount !== instance.startCount) return; + throw new Error([t("TXT_CODE_db37b7f9"), err?.message].join("\n")); + } finally { + this.stopped(instance); + } } +} async stop(instance: Instance): Promise { this.stopped(instance); diff --git a/daemon/src/entity/instance/Instance_config.ts b/daemon/src/entity/instance/Instance_config.ts index b55a52179..f6863d4b3 100755 --- a/daemon/src/entity/instance/Instance_config.ts +++ b/daemon/src/entity/instance/Instance_config.ts @@ -55,6 +55,7 @@ export default class InstanceConfig implements IGlobalInstanceConfig { public docker: IGlobalInstanceDockerConfig = { containerName: "", image: "", + pullPolicy: false, ports: [], extraVolumes: [], memory: 0, diff --git a/daemon/src/entity/instance/instance.ts b/daemon/src/entity/instance/instance.ts index 5ea8f5fb8..b4d656566 100755 --- a/daemon/src/entity/instance/instance.ts +++ b/daemon/src/entity/instance/instance.ts @@ -196,6 +196,7 @@ export default class Instance extends EventEmitter { if (cfg.docker) { configureEntityParams(this.config.docker, cfg.docker, "containerName", String); + configureEntityParams(this.config.docker, cfg.docker, "pullPolicy", Boolean); configureEntityParams(this.config.docker, cfg.docker, "image", String); configureEntityParams(this.config.docker, cfg.docker, "memory", Number); configureEntityParams(this.config.docker, cfg.docker, "ports"); diff --git a/frontend/src/widgets/instance/dialogs/InstanceDetail.vue b/frontend/src/widgets/instance/dialogs/InstanceDetail.vue index 23a961e22..af00d1335 100644 --- a/frontend/src/widgets/instance/dialogs/InstanceDetail.vue +++ b/frontend/src/widgets/instance/dialogs/InstanceDetail.vue @@ -667,6 +667,29 @@ defineExpose({ + + + + Always pull image + + + + Always pull Docker image + + + + + + + + + + {{ t("TXT_CODE_10194e6a") }} diff --git a/frontend/src/widgets/setupApp/CreateInstanceForm.vue b/frontend/src/widgets/setupApp/CreateInstanceForm.vue index bac906b53..ce6fe3b67 100644 --- a/frontend/src/widgets/setupApp/CreateInstanceForm.vue +++ b/frontend/src/widgets/setupApp/CreateInstanceForm.vue @@ -60,6 +60,7 @@ const formData = reactive({ docker: { containerName: "", image: "", + pullPolicy: false, ports: [], extraVolumes: [], networkMode: "bridge",