feat: initial commit

This commit is contained in:
Mauricio Siu
2024-04-28 23:57:52 -06:00
parent 8857a20344
commit be56ba046c
412 changed files with 60777 additions and 1 deletions

View 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);
}
}
};

View 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 ✅");
}
};

View 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
View 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;
}
};

View 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");
};