mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-07-06 14:35:26 +02:00
feat: initial commit
This commit is contained in:
39
server/setup/config-paths.ts
Normal file
39
server/setup/config-paths.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { existsSync, mkdirSync } from "node:fs";
|
||||
import {
|
||||
APPLICATIONS_PATH,
|
||||
BASE_PATH,
|
||||
CERTIFICATES_PATH,
|
||||
LOGS_PATH,
|
||||
MONITORING_PATH,
|
||||
SSH_PATH,
|
||||
DYNAMIC_TRAEFIK_PATH,
|
||||
MAIN_TRAEFIK_PATH,
|
||||
} from "../constants";
|
||||
|
||||
const createDirectoryIfNotExist = (dirPath: string) => {
|
||||
if (!existsSync(dirPath)) {
|
||||
mkdirSync(dirPath, { recursive: true });
|
||||
console.log(`Directory created: ${dirPath}`);
|
||||
}
|
||||
};
|
||||
|
||||
export const setupDirectories = () => {
|
||||
const directories = [
|
||||
BASE_PATH,
|
||||
MAIN_TRAEFIK_PATH,
|
||||
DYNAMIC_TRAEFIK_PATH,
|
||||
LOGS_PATH,
|
||||
APPLICATIONS_PATH,
|
||||
SSH_PATH,
|
||||
CERTIFICATES_PATH,
|
||||
MONITORING_PATH,
|
||||
];
|
||||
|
||||
for (const dir of directories) {
|
||||
try {
|
||||
createDirectoryIfNotExist(dir);
|
||||
} catch (error) {
|
||||
console.log(error, " On path: ", dir);
|
||||
}
|
||||
}
|
||||
};
|
||||
63
server/setup/postgres-setup.ts
Normal file
63
server/setup/postgres-setup.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { docker } from "../constants";
|
||||
import { pullImage } from "../utils/docker/utils";
|
||||
import type { CreateServiceOptions } from "dockerode";
|
||||
export const initializePostgres = async () => {
|
||||
const imageName = "postgres:16";
|
||||
const containerName = "dokploy-postgres";
|
||||
const settings: CreateServiceOptions = {
|
||||
Name: containerName,
|
||||
TaskTemplate: {
|
||||
ContainerSpec: {
|
||||
Image: imageName,
|
||||
Env: [
|
||||
"POSTGRES_USER=dokploy",
|
||||
"POSTGRES_DB=dokploy",
|
||||
"POSTGRES_PASSWORD=amukds4wi9001583845717ad2",
|
||||
],
|
||||
Mounts: [
|
||||
{
|
||||
Type: "volume",
|
||||
Source: "dokploy-postgres-database",
|
||||
Target: "/var/lib/postgresql/data",
|
||||
},
|
||||
],
|
||||
},
|
||||
Networks: [{ Target: "dokploy-network" }],
|
||||
RestartPolicy: {
|
||||
Condition: "on-failure",
|
||||
},
|
||||
},
|
||||
Mode: {
|
||||
Replicated: {
|
||||
Replicas: 1,
|
||||
},
|
||||
},
|
||||
EndpointSpec: {
|
||||
Ports: [
|
||||
{
|
||||
TargetPort: 5432,
|
||||
...(process.env.NODE_ENV === "development"
|
||||
? { PublishedPort: 5432 }
|
||||
: {}),
|
||||
Protocol: "tcp",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
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("Postgres Started ✅");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
await docker.createService(settings);
|
||||
console.log("Postgres Not Found: Starting ✅");
|
||||
}
|
||||
};
|
||||
56
server/setup/redis-setup.ts
Normal file
56
server/setup/redis-setup.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import type { CreateServiceOptions } from "dockerode";
|
||||
import { docker } from "../constants";
|
||||
import { pullImage } from "../utils/docker/utils";
|
||||
|
||||
export const initializeRedis = async () => {
|
||||
const imageName = "redis:7";
|
||||
const containerName = "dokploy-redis";
|
||||
|
||||
const settings: CreateServiceOptions = {
|
||||
Name: containerName,
|
||||
TaskTemplate: {
|
||||
ContainerSpec: {
|
||||
Image: imageName,
|
||||
Mounts: [
|
||||
{
|
||||
Type: "volume",
|
||||
Source: "redis-data-volume",
|
||||
Target: "/data",
|
||||
},
|
||||
],
|
||||
},
|
||||
Networks: [{ Target: "dokploy-network" }],
|
||||
RestartPolicy: {
|
||||
Condition: "on-failure",
|
||||
},
|
||||
},
|
||||
Mode: {
|
||||
Replicated: {
|
||||
Replicas: 1,
|
||||
},
|
||||
},
|
||||
EndpointSpec: {
|
||||
Ports: [
|
||||
{
|
||||
TargetPort: 6379,
|
||||
PublishedPort: 6379,
|
||||
Protocol: "tcp",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
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("Redis Started ✅");
|
||||
} catch (error) {
|
||||
await docker.createService(settings);
|
||||
console.log("Redis Not Found: Starting ✅");
|
||||
}
|
||||
};
|
||||
48
server/setup/setup.ts
Normal file
48
server/setup/setup.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { docker } from "../constants";
|
||||
|
||||
export const initializeSwarm = async () => {
|
||||
const swarmInitialized = await dockerSwarmInitialized();
|
||||
if (swarmInitialized) {
|
||||
console.log("Swarm is already initilized");
|
||||
} else {
|
||||
await docker.swarmInit({
|
||||
AdvertiseAddr: "127.0.0.1",
|
||||
ListenAddr: "0.0.0.0",
|
||||
});
|
||||
console.log("Swarm was initilized");
|
||||
}
|
||||
};
|
||||
|
||||
export const dockerSwarmInitialized = async () => {
|
||||
try {
|
||||
await docker.swarmInspect();
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const initializeNetwork = async () => {
|
||||
const networkInitialized = await dockerNetworkInitialized();
|
||||
if (networkInitialized) {
|
||||
console.log("Network is already initilized");
|
||||
} else {
|
||||
docker.createNetwork({
|
||||
Attachable: true,
|
||||
Name: "dokploy-network",
|
||||
Driver: "overlay",
|
||||
});
|
||||
console.log("Network was initilized");
|
||||
}
|
||||
};
|
||||
|
||||
export const dockerNetworkInitialized = async () => {
|
||||
try {
|
||||
await docker.getNetwork("dokploy-network").inspect();
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
210
server/setup/traefik-setup.ts
Normal file
210
server/setup/traefik-setup.ts
Normal file
@@ -0,0 +1,210 @@
|
||||
import path from "node:path";
|
||||
import { MAIN_TRAEFIK_PATH, DYNAMIC_TRAEFIK_PATH, docker } from "../constants";
|
||||
import { pullImage } from "../utils/docker/utils";
|
||||
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
||||
import { dump } from "js-yaml";
|
||||
import type { MainTraefikConfig } from "../utils/traefik/types";
|
||||
import type { FileConfig } from "../utils/traefik/file-types";
|
||||
import type { CreateServiceOptions } from "dockerode";
|
||||
|
||||
export const initializeTraefik = async () => {
|
||||
const imageName = "traefik:v2.5";
|
||||
const containerName = "dokploy-traefik";
|
||||
const settings: CreateServiceOptions = {
|
||||
Name: containerName,
|
||||
TaskTemplate: {
|
||||
ContainerSpec: {
|
||||
Image: imageName,
|
||||
Mounts: [
|
||||
{
|
||||
Type: "bind",
|
||||
Source: `${MAIN_TRAEFIK_PATH}/traefik.yml`,
|
||||
Target: "/etc/traefik/traefik.yml",
|
||||
},
|
||||
{
|
||||
Type: "bind",
|
||||
Source: DYNAMIC_TRAEFIK_PATH,
|
||||
Target: "/etc/dokploy/traefik/dynamic",
|
||||
},
|
||||
{
|
||||
Type: "bind",
|
||||
Source: "/var/run/docker.sock",
|
||||
Target: "/var/run/docker.sock",
|
||||
},
|
||||
],
|
||||
},
|
||||
Networks: [{ Target: "dokploy-network" }],
|
||||
RestartPolicy: {
|
||||
Condition: "on-failure",
|
||||
},
|
||||
},
|
||||
Mode: {
|
||||
Replicated: {
|
||||
Replicas: 1,
|
||||
},
|
||||
},
|
||||
EndpointSpec: {
|
||||
Ports: [
|
||||
{
|
||||
TargetPort: 443,
|
||||
PublishedPort: 443,
|
||||
PublishMode: "host",
|
||||
},
|
||||
{
|
||||
TargetPort: 80,
|
||||
PublishedPort: 80,
|
||||
PublishMode: "host",
|
||||
},
|
||||
{
|
||||
TargetPort: 8080,
|
||||
PublishedPort: 8080,
|
||||
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("Traefik Started ✅");
|
||||
} catch (error) {
|
||||
await docker.createService(settings);
|
||||
console.log("Traefik Not Found: Starting ✅");
|
||||
}
|
||||
};
|
||||
|
||||
export const createDefaultServerTraefikConfig = () => {
|
||||
const configFilePath = path.join(DYNAMIC_TRAEFIK_PATH, "dokploy.yml");
|
||||
if (existsSync(configFilePath)) {
|
||||
console.log("Default traefik config already exists");
|
||||
return;
|
||||
}
|
||||
|
||||
const appName = "dokploy";
|
||||
const serviceURLDefault = `http://${appName}:${process.env.PORT || 3000}`;
|
||||
const config: FileConfig = {
|
||||
http: {
|
||||
routers: {
|
||||
[`${appName}-router-app`]: {
|
||||
rule: `Host(\`${appName}.docker.localhost\`) && PathPrefix(\`/\`)`,
|
||||
service: `${appName}-service-app`,
|
||||
entryPoints: ["web", "websecure"],
|
||||
tls: {},
|
||||
},
|
||||
},
|
||||
services: {
|
||||
[`${appName}-service-app`]: {
|
||||
loadBalancer: {
|
||||
servers: [{ url: serviceURLDefault }],
|
||||
passHostHeader: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const yamlStr = dump(config);
|
||||
mkdirSync(DYNAMIC_TRAEFIK_PATH, { recursive: true });
|
||||
writeFileSync(
|
||||
path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`),
|
||||
yamlStr,
|
||||
"utf8",
|
||||
);
|
||||
};
|
||||
|
||||
export const createDefaultTraefikConfig = () => {
|
||||
const mainConfig = path.join(MAIN_TRAEFIK_PATH, "traefik.yml");
|
||||
if (existsSync(mainConfig)) {
|
||||
console.log("Main config already exists");
|
||||
return;
|
||||
}
|
||||
const configObject: MainTraefikConfig = {
|
||||
providers: {
|
||||
...(process.env.NODE_ENV === "development" && {
|
||||
docker: {
|
||||
defaultRule: "Host(`{{ trimPrefix `/` .Name }}.docker.localhost`)",
|
||||
},
|
||||
}),
|
||||
file: {
|
||||
directory: DYNAMIC_TRAEFIK_PATH,
|
||||
watch: true,
|
||||
},
|
||||
},
|
||||
entryPoints: {
|
||||
web: {
|
||||
address: ":80",
|
||||
...(process.env.NODE_ENV === "production" && {
|
||||
http: {
|
||||
redirections: {
|
||||
entryPoint: {
|
||||
to: "websecure",
|
||||
scheme: "https",
|
||||
permanent: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
websecure: {
|
||||
address: ":443",
|
||||
...(process.env.NODE_ENV === "production" && {
|
||||
http: {
|
||||
tls: {
|
||||
certResolver: "letsencrypt",
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
api: {
|
||||
insecure: true,
|
||||
},
|
||||
...(process.env.NODE_ENV === "production" && {
|
||||
certificatesResolvers: {
|
||||
letsencrypt: {
|
||||
acme: {
|
||||
email: "test@localhost.com",
|
||||
storage: "/etc/dokploy/traefik/dynamic/acme.json",
|
||||
httpChallenge: {
|
||||
entryPoint: "web",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
const yamlStr = dump(configObject);
|
||||
mkdirSync(MAIN_TRAEFIK_PATH, { recursive: true });
|
||||
writeFileSync(mainConfig, yamlStr, "utf8");
|
||||
};
|
||||
|
||||
export const createDefaultMiddlewares = () => {
|
||||
const middlewaresPath = path.join(DYNAMIC_TRAEFIK_PATH, "middlewares.yml");
|
||||
if (existsSync(middlewaresPath)) {
|
||||
console.log("Default middlewares already exists");
|
||||
return;
|
||||
}
|
||||
const defaultMiddlewares = {
|
||||
http: {
|
||||
middlewares: {
|
||||
"redirect-to-https": {
|
||||
redirectScheme: {
|
||||
scheme: "https",
|
||||
permanent: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const yamlStr = dump(defaultMiddlewares);
|
||||
mkdirSync(DYNAMIC_TRAEFIK_PATH, { recursive: true });
|
||||
writeFileSync(middlewaresPath, yamlStr, "utf8");
|
||||
};
|
||||
Reference in New Issue
Block a user