fix: docker hosts and ports env variable wrongly used (#2050)
* fix: docker hosts and ports env variable wrongly used * fix: ci issues
This commit is contained in:
9
packages/docker/eslint.config.js
Normal file
9
packages/docker/eslint.config.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import baseConfig from "@homarr/eslint-config/base";
|
||||
|
||||
/** @type {import('typescript-eslint').Config} */
|
||||
export default [
|
||||
{
|
||||
ignores: [],
|
||||
},
|
||||
...baseConfig,
|
||||
];
|
||||
1
packages/docker/index.ts
Normal file
1
packages/docker/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./src";
|
||||
38
packages/docker/package.json
Normal file
38
packages/docker/package.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "@homarr/docker",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./index.ts",
|
||||
"./env": "./src/env.ts"
|
||||
},
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"*": [
|
||||
"src/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rm -rf .turbo node_modules",
|
||||
"format": "prettier --check . --ignore-path ../../.gitignore",
|
||||
"lint": "eslint",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"prettier": "@homarr/prettier-config",
|
||||
"dependencies": {
|
||||
"@homarr/common": "workspace:^0.1.0",
|
||||
"@t3-oss/env-nextjs": "^0.11.1",
|
||||
"dockerode": "^4.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"@types/dockerode": "^3.3.34",
|
||||
"eslint": "^9.18.0",
|
||||
"typescript": "^5.7.3"
|
||||
}
|
||||
}
|
||||
18
packages/docker/src/env.ts
Normal file
18
packages/docker/src/env.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { createEnv } from "@t3-oss/env-nextjs";
|
||||
import { z } from "zod";
|
||||
|
||||
import { shouldSkipEnvValidation } from "@homarr/common/env-validation";
|
||||
|
||||
export const env = createEnv({
|
||||
server: {
|
||||
// Comma separated list of docker hostnames that can be used to connect to query the docker endpoints (localhost:2375,host.docker.internal:2375, ...)
|
||||
DOCKER_HOSTNAMES: z.string().optional(),
|
||||
DOCKER_PORTS: z.string().optional(),
|
||||
},
|
||||
runtimeEnv: {
|
||||
DOCKER_HOSTNAMES: process.env.DOCKER_HOSTNAMES,
|
||||
DOCKER_PORTS: process.env.DOCKER_PORTS,
|
||||
},
|
||||
skipValidation: shouldSkipEnvValidation(),
|
||||
emptyStringAsUndefined: true,
|
||||
});
|
||||
10
packages/docker/src/index.ts
Normal file
10
packages/docker/src/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import type Docker from "dockerode";
|
||||
|
||||
export type { DockerInstance } from "./singleton";
|
||||
export { DockerSingleton } from "./singleton";
|
||||
export type { ContainerInfo, Container, Port } from "dockerode";
|
||||
export type { Docker };
|
||||
|
||||
export const containerStates = ["created", "running", "paused", "restarting", "exited", "removing", "dead"] as const;
|
||||
|
||||
export type ContainerState = (typeof containerStates)[number];
|
||||
53
packages/docker/src/singleton.ts
Normal file
53
packages/docker/src/singleton.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import Docker from "dockerode";
|
||||
|
||||
import { env } from "./env";
|
||||
|
||||
export interface DockerInstance {
|
||||
host: string;
|
||||
instance: Docker;
|
||||
}
|
||||
|
||||
export class DockerSingleton {
|
||||
private static instances: DockerInstance[] | null = null;
|
||||
|
||||
private createInstances() {
|
||||
const hostVariable = env.DOCKER_HOSTNAMES;
|
||||
const portVariable = env.DOCKER_PORTS;
|
||||
if (hostVariable === undefined || portVariable === undefined) {
|
||||
return [{ host: "socket", instance: new Docker() }];
|
||||
}
|
||||
const hostnames = hostVariable.split(",");
|
||||
const ports = portVariable.split(",");
|
||||
|
||||
if (hostnames.length !== ports.length) {
|
||||
throw new Error("The number of hosts and ports must match");
|
||||
}
|
||||
|
||||
return hostnames.map((host, i) => {
|
||||
// Check above ensures that ports[i] is not undefined
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const port = ports[i]!;
|
||||
|
||||
return {
|
||||
host: `${host}:${port}`,
|
||||
instance: new Docker({
|
||||
host,
|
||||
port: parseInt(port, 10),
|
||||
}),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public static findInstance(host: string): DockerInstance | undefined {
|
||||
return this.instances?.find((instance) => instance.host === host);
|
||||
}
|
||||
|
||||
public static getInstances(): DockerInstance[] {
|
||||
if (this.instances) {
|
||||
return this.instances;
|
||||
}
|
||||
|
||||
this.instances = new DockerSingleton().createInstances();
|
||||
return this.instances;
|
||||
}
|
||||
}
|
||||
8
packages/docker/tsconfig.json
Normal file
8
packages/docker/tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "@homarr/tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json"
|
||||
},
|
||||
"include": ["*.ts", "src"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
Reference in New Issue
Block a user