mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-15 20:25:23 +02:00
refactor(dokploy): add flag to prevent run commands when is cloud
This commit is contained in:
@@ -53,7 +53,10 @@ export const apiCreateDestination = createSchema
|
||||
endpoint: true,
|
||||
secretAccessKey: true,
|
||||
})
|
||||
.required();
|
||||
.required()
|
||||
.extend({
|
||||
serverId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const apiFindOneDestination = createSchema
|
||||
.pick({
|
||||
@@ -77,4 +80,7 @@ export const apiUpdateDestination = createSchema
|
||||
secretAccessKey: true,
|
||||
destinationId: true,
|
||||
})
|
||||
.required();
|
||||
.required()
|
||||
.extend({
|
||||
serverId: z.string().optional(),
|
||||
});
|
||||
|
||||
@@ -37,7 +37,6 @@ export * from "./services/application";
|
||||
export * from "./setup/config-paths";
|
||||
export * from "./setup/postgres-setup";
|
||||
export * from "./setup/redis-setup";
|
||||
export * from "./setup/registry-setup";
|
||||
export * from "./setup/server-setup";
|
||||
export * from "./setup/setup";
|
||||
export * from "./setup/traefik-setup";
|
||||
@@ -97,7 +96,6 @@ export * from "./utils/traefik/domain";
|
||||
export * from "./utils/traefik/file-types";
|
||||
export * from "./utils/traefik/middleware";
|
||||
export * from "./utils/traefik/redirect";
|
||||
export * from "./utils/traefik/registry";
|
||||
export * from "./utils/traefik/security";
|
||||
export * from "./utils/traefik/types";
|
||||
export * from "./utils/traefik/web-server";
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreateRegistry, registry } from "@/server/db/schema";
|
||||
import { initializeRegistry } from "@/server/setup/registry-setup";
|
||||
import { removeService } from "@/server/utils/docker/utils";
|
||||
import { execAsync, execAsyncRemote } from "@/server/utils/process/execAsync";
|
||||
import {
|
||||
manageRegistry,
|
||||
removeSelfHostedRegistry,
|
||||
} from "@/server/utils/traefik/registry";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { IS_CLOUD } from "../constants";
|
||||
|
||||
export type Registry = typeof registry.$inferSelect;
|
||||
|
||||
@@ -32,6 +27,13 @@ export const createRegistry = async (
|
||||
message: "Error input: Inserting registry",
|
||||
});
|
||||
}
|
||||
|
||||
if (IS_CLOUD && !input.serverId && input.serverId !== "none") {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Select a server to add the registry",
|
||||
});
|
||||
}
|
||||
const loginCommand = `echo ${input.password} | docker login ${input.registryUrl} --username ${input.username} --password-stdin`;
|
||||
if (input.serverId && input.serverId !== "none") {
|
||||
await execAsyncRemote(input.serverId, loginCommand);
|
||||
@@ -58,13 +60,10 @@ export const removeRegistry = async (registryId: string) => {
|
||||
});
|
||||
}
|
||||
|
||||
if (response.registryType === "selfHosted") {
|
||||
await removeSelfHostedRegistry();
|
||||
await removeService("dokploy-registry");
|
||||
if (!IS_CLOUD) {
|
||||
await execAsync(`docker logout ${response.registryUrl}`);
|
||||
}
|
||||
|
||||
await execAsync(`docker logout ${response.registryUrl}`);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
@@ -89,12 +88,19 @@ export const updateRegistry = async (
|
||||
.returning()
|
||||
.then((res) => res[0]);
|
||||
|
||||
if (response?.registryType === "selfHosted") {
|
||||
await manageRegistry(response);
|
||||
await initializeRegistry(response.username, response.password);
|
||||
}
|
||||
const loginCommand = `echo ${response?.password} | docker login ${response?.registryUrl} --username ${response?.username} --password-stdin`;
|
||||
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
!registryData?.serverId &&
|
||||
registryData?.serverId !== "none"
|
||||
) {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Select a server to add the registry",
|
||||
});
|
||||
}
|
||||
|
||||
if (registryData?.serverId && registryData?.serverId !== "none") {
|
||||
await execAsyncRemote(registryData.serverId, loginCommand);
|
||||
} else if (response?.registryType === "cloud") {
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
import type { CreateServiceOptions } from "dockerode";
|
||||
import { docker, paths } from "../constants";
|
||||
import { generatePassword } from "../templates/utils";
|
||||
import { pullImage } from "../utils/docker/utils";
|
||||
import { execAsync } from "../utils/process/execAsync";
|
||||
|
||||
export const initializeRegistry = async (
|
||||
username: string,
|
||||
password: string,
|
||||
) => {
|
||||
const { REGISTRY_PATH } = paths();
|
||||
const imageName = "registry:2.8.3";
|
||||
const containerName = "dokploy-registry";
|
||||
await generateRegistryPassword(username, password);
|
||||
const randomPass = generatePassword();
|
||||
const settings: CreateServiceOptions = {
|
||||
Name: containerName,
|
||||
TaskTemplate: {
|
||||
ContainerSpec: {
|
||||
Image: imageName,
|
||||
Env: [
|
||||
"REGISTRY_STORAGE_DELETE_ENABLED=true",
|
||||
"REGISTRY_AUTH=htpasswd",
|
||||
"REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm",
|
||||
"REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd",
|
||||
`REGISTRY_HTTP_SECRET=${randomPass}`,
|
||||
],
|
||||
Mounts: [
|
||||
{
|
||||
Type: "bind",
|
||||
Source: `${REGISTRY_PATH}/htpasswd`,
|
||||
Target: "/auth/htpasswd",
|
||||
ReadOnly: true,
|
||||
},
|
||||
{
|
||||
Type: "volume",
|
||||
Source: "registry-data",
|
||||
Target: "/var/lib/registry",
|
||||
ReadOnly: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
Networks: [{ Target: "dokploy-network" }],
|
||||
Placement: {
|
||||
Constraints: ["node.role==manager"],
|
||||
},
|
||||
},
|
||||
Mode: {
|
||||
Replicated: {
|
||||
Replicas: 1,
|
||||
},
|
||||
},
|
||||
EndpointSpec: {
|
||||
Ports: [
|
||||
{
|
||||
TargetPort: 5000,
|
||||
PublishedPort: 5000,
|
||||
Protocol: "tcp",
|
||||
PublishMode: "host",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
try {
|
||||
await pullImage(imageName);
|
||||
|
||||
const service = docker.getService(containerName);
|
||||
const inspect = await service.inspect();
|
||||
await service.update({
|
||||
version: Number.parseInt(inspect.Version.Index),
|
||||
...settings,
|
||||
});
|
||||
console.log("Registry Started ✅");
|
||||
} catch (error) {
|
||||
await docker.createService(settings);
|
||||
console.log("Registry Not Found: Starting ✅");
|
||||
}
|
||||
};
|
||||
|
||||
const generateRegistryPassword = async (username: string, password: string) => {
|
||||
try {
|
||||
const { REGISTRY_PATH } = paths();
|
||||
const command = `htpasswd -nbB ${username} "${password}" > ${REGISTRY_PATH}/htpasswd`;
|
||||
const result = await execAsync(command);
|
||||
console.log("Password generated ✅");
|
||||
return result.stdout.trim();
|
||||
} catch (error) {
|
||||
console.error("Error generating password:", error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -55,8 +55,6 @@ export const cloneGitRepository = async (
|
||||
await addHostToKnownHosts(customGitUrl);
|
||||
}
|
||||
await recreateDirectory(outputPath);
|
||||
// const command = `GIT_SSH_COMMAND="ssh -i ${keyPath} -o UserKnownHostsFile=${knownHostsPath}" git clone --branch ${customGitBranch} --depth 1 ${customGitUrl} ${gitCopyPath} --progress`;
|
||||
// const { stdout, stderr } = await execAsync(command);
|
||||
writeStream.write(
|
||||
`\nCloning Repo Custom ${customGitUrl} to ${outputPath}: ✅\n`,
|
||||
);
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import type { Registry } from "@/server/services/registry";
|
||||
import { dump, load } from "js-yaml";
|
||||
import { removeDirectoryIfExistsContent } from "../filesystem/directory";
|
||||
import type { FileConfig, HttpRouter } from "./file-types";
|
||||
|
||||
export const manageRegistry = async (registry: Registry) => {
|
||||
const { REGISTRY_PATH } = paths();
|
||||
if (!existsSync(REGISTRY_PATH)) {
|
||||
mkdirSync(REGISTRY_PATH, { recursive: true });
|
||||
}
|
||||
|
||||
const appName = "dokploy-registry";
|
||||
const config: FileConfig = loadOrCreateConfig();
|
||||
|
||||
const serviceName = `${appName}-service`;
|
||||
const routerName = `${appName}-router`;
|
||||
|
||||
config.http = config.http || { routers: {}, services: {} };
|
||||
config.http.routers = config.http.routers || {};
|
||||
config.http.services = config.http.services || {};
|
||||
|
||||
config.http.routers[routerName] = await createRegistryRouterConfig(registry);
|
||||
|
||||
config.http.services[serviceName] = {
|
||||
loadBalancer: {
|
||||
servers: [{ url: `http://${appName}:5000` }],
|
||||
passHostHeader: true,
|
||||
},
|
||||
};
|
||||
|
||||
const yamlConfig = dump(config);
|
||||
const configFile = join(REGISTRY_PATH, "registry.yml");
|
||||
writeFileSync(configFile, yamlConfig);
|
||||
};
|
||||
|
||||
export const removeSelfHostedRegistry = async () => {
|
||||
const { REGISTRY_PATH } = paths();
|
||||
await removeDirectoryIfExistsContent(REGISTRY_PATH);
|
||||
};
|
||||
|
||||
const createRegistryRouterConfig = async (registry: Registry) => {
|
||||
const { registryUrl } = registry;
|
||||
const routerConfig: HttpRouter = {
|
||||
rule: `Host(\`${registryUrl}\`)`,
|
||||
service: "dokploy-registry-service",
|
||||
middlewares: ["redirect-to-https"],
|
||||
entryPoints: [
|
||||
"web",
|
||||
...(process.env.NODE_ENV === "production" ? ["websecure"] : []),
|
||||
],
|
||||
...(process.env.NODE_ENV === "production"
|
||||
? {
|
||||
tls: { certResolver: "letsencrypt" },
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
|
||||
return routerConfig;
|
||||
};
|
||||
|
||||
const loadOrCreateConfig = (): FileConfig => {
|
||||
const { REGISTRY_PATH } = paths();
|
||||
const configPath = join(REGISTRY_PATH, "registry.yml");
|
||||
if (existsSync(configPath)) {
|
||||
const yamlStr = readFileSync(configPath, "utf8");
|
||||
const parsedConfig = (load(yamlStr) as FileConfig) || {
|
||||
http: { routers: {}, services: {} },
|
||||
};
|
||||
return parsedConfig;
|
||||
}
|
||||
return { http: { routers: {}, services: {} } };
|
||||
};
|
||||
Reference in New Issue
Block a user