diff --git a/README.md b/README.md index eb57a35..87fa35e 100644 --- a/README.md +++ b/README.md @@ -148,13 +148,13 @@ Yes, you can. However, you need to move your compose file into the stacks direct 3. In Dockge, click the " Scan Stacks Folder" button in the top-right corner's dropdown menu 4. Now you should see your stack in the list -#### Is Dockge a Portainer replcement? +#### Is Dockge a Portainer replacement? Yes or no. Portainer provides a lot of Docker features. While Dockge is currently only focusing on docker-compose with a better user interface and better user experience. If you want to manage your container with docker-compose only, the answer may be yes. -If you still need to manage something like docker networks, signle containers, the answer may be no. +If you still need to manage something like docker networks, single containers, the answer may be no. #### Can I install both Dockge and Portainer? diff --git a/backend/check-version.ts b/backend/check-version.ts index acfb5fb..cd6508a 100644 --- a/backend/check-version.ts +++ b/backend/check-version.ts @@ -3,69 +3,55 @@ import compareVersions from "compare-versions"; import packageJSON from "../package.json"; import { Settings } from "./settings"; -export const obj = { - version: packageJSON.version, - latestVersion: null, -}; -export default obj; - // How much time in ms to wait between update checks const UPDATE_CHECKER_INTERVAL_MS = 1000 * 60 * 60 * 48; const CHECK_URL = "https://dockge.kuma.pet/version"; -let interval : NodeJS.Timeout; +class CheckVersion { + version = packageJSON.version; + latestVersion? : string; + interval? : NodeJS.Timeout; -export function startInterval() { - const check = async () => { - if (await Settings.get("checkUpdate") === false) { - return; - } - - log.debug("update-checker", "Retrieving latest versions"); - - try { - const res = await fetch(CHECK_URL); - const data = await res.json(); - - // For debug - if (process.env.TEST_CHECK_VERSION === "1") { - data.slow = "1000.0.0"; + async startInterval() { + const check = async () => { + if (await Settings.get("checkUpdate") === false) { + return; } - const checkBeta = await Settings.get("checkBeta"); + log.debug("update-checker", "Retrieving latest versions"); - if (checkBeta && data.beta) { - if (compareVersions.compare(data.beta, data.slow, ">")) { - obj.latestVersion = data.beta; - return; + try { + const res = await fetch(CHECK_URL); + const data = await res.json(); + + // For debug + if (process.env.TEST_CHECK_VERSION === "1") { + data.slow = "1000.0.0"; } + + const checkBeta = await Settings.get("checkBeta"); + + if (checkBeta && data.beta) { + if (compareVersions.compare(data.beta, data.slow, ">")) { + this.latestVersion = data.beta; + return; + } + } + + if (data.slow) { + this.latestVersion = data.slow; + } + + } catch (_) { + log.info("update-checker", "Failed to check for new versions"); } - if (data.slow) { - obj.latestVersion = data.slow; - } + }; - } catch (_) { - log.info("update-checker", "Failed to check for new versions"); - } - - }; - - check(); - interval = setInterval(check, UPDATE_CHECKER_INTERVAL_MS); -} - -/** - * Enable the check update feature - * @param value Should the check update feature be enabled? - * @returns - */ -export async function enableCheckUpdate(value : boolean) { - await Settings.set("checkUpdate", value); - - clearInterval(interval); - - if (value) { - startInterval(); + await check(); + this.interval = setInterval(check, UPDATE_CHECKER_INTERVAL_MS); } } + +const checkVersion = new CheckVersion(); +export default checkVersion; diff --git a/backend/docker.ts b/backend/docker.ts deleted file mode 100644 index 4083a73..0000000 --- a/backend/docker.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class Docker { - -} diff --git a/backend/dockge-server.ts b/backend/dockge-server.ts index 0833efd..f2eb50a 100644 --- a/backend/dockge-server.ts +++ b/backend/dockge-server.ts @@ -341,6 +341,7 @@ export class DockgeServer { this.sendStackList(true); }); + checkVersion.startInterval(); }); gracefulShutdown(this.httpServer, { diff --git a/backend/util-common.ts b/backend/util-common.ts index 7c1544d..c7eabec 100644 --- a/backend/util-common.ts +++ b/backend/util-common.ts @@ -1,13 +1,17 @@ /* * Common utilities for backend and frontend */ -import { Document } from "yaml"; +import yaml, { Document, Pair, Scalar } from "yaml"; +import { DotenvParseOutput } from "dotenv"; // Init dayjs import dayjs from "dayjs"; import timezone from "dayjs/plugin/timezone"; import utc from "dayjs/plugin/utc"; import relativeTime from "dayjs/plugin/relativeTime"; +// @ts-ignore +import { replaceVariablesSync } from "@inventage/envsubst"; + dayjs.extend(utc); dayjs.extend(timezone); dayjs.extend(relativeTime); @@ -345,3 +349,48 @@ export function parseDockerPort(input : string, defaultHostname : string = "loca display: display, }; } + +export function envsubst(string : string, variables : LooseObject) : string { + return replaceVariablesSync(string, variables)[0]; +} + +/** + * Traverse all values in the yaml and for each value, if there are template variables, replace it environment variables + * Emulates the behavior of how docker-compose handles environment variables in yaml files + * @param content Yaml string + * @param env Environment variables + * @returns string Yaml string with environment variables replaced + */ +export function envsubstYAML(content : string, env : DotenvParseOutput) : string { + const doc = yaml.parseDocument(content); + if (doc.contents) { + // @ts-ignore + for (const item of doc.contents.items) { + traverseYAML(item, env); + } + } + return doc.toString(); +} + +/** + * Used for envsubstYAML(...) + * @param pair + * @param env + */ +function traverseYAML(pair : Pair, env : DotenvParseOutput) : void { + // @ts-ignore + if (pair.value && pair.value.items) { + // @ts-ignore + for (const item of pair.value.items) { + if (item instanceof Pair) { + traverseYAML(item, env); + } else if (item instanceof Scalar) { + item.value = envsubst(item.value, env); + } + } + // @ts-ignore + } else if (pair.value && typeof(pair.value.value) === "string") { + // @ts-ignore + pair.value.value = envsubst(pair.value.value, env); + } +} diff --git a/frontend/src/components/Container.vue b/frontend/src/components/Container.vue index 604e068..0a20182 100644 --- a/frontend/src/components/Container.vue +++ b/frontend/src/components/Container.vue @@ -9,7 +9,7 @@
{{ status }} - + {{ parsePort(port).display }}
@@ -213,16 +213,29 @@ export default defineComponent({ jsonObject() { return this.$parent.$parent.jsonConfig; }, + + envsubstJSONConfig() { + return this.$parent.$parent.envsubstJSONConfig; + }, + + envsubstService() { + if (!this.envsubstJSONConfig.services[this.name]) { + return {}; + } + return this.envsubstJSONConfig.services[this.name]; + }, + imageName() { - if (this.service.image) { - return this.service.image.split(":")[0]; + if (this.envsubstService.image) { + return this.envsubstService.image.split(":")[0]; } else { return ""; } }, + imageTag() { - if (this.service.image) { - let tag = this.service.image.split(":")[1]; + if (this.envsubstService.image) { + let tag = this.envsubstService.image.split(":")[1]; if (tag) { return tag; diff --git a/frontend/src/lang/en.json b/frontend/src/lang/en.json index f029201..c30b92c 100644 --- a/frontend/src/lang/en.json +++ b/frontend/src/lang/en.json @@ -98,5 +98,6 @@ "reconnecting...": "Reconnecting…", "connecting...": "Connecting to the socket server…", "url": "URL | URLs", - "extra": "Extra" + "extra": "Extra", + "newUpdate": "New Update" } diff --git a/frontend/src/layouts/Layout.vue b/frontend/src/layouts/Layout.vue index ae0d8ae..ef793c7 100644 --- a/frontend/src/layouts/Layout.vue +++ b/frontend/src/layouts/Layout.vue @@ -16,8 +16,8 @@ Dockge - - {{ $t("New Update") }} + + {{ $t("newUpdate") }}