Files
dokploy/packages/server/src/setup/monitoring-setup.ts
T
2026-08-24 20:52:35 -04:00

212 lines
5.1 KiB
TypeScript

import { findServerById } from "@dokploy/server/services/server";
import { getWebServerSettings } from "@dokploy/server/services/web-server-settings";
import type { CreateServiceOptions } from "dockerode";
import { IS_CLOUD } from "../constants";
import { getDokployImageTag } from "../services/settings";
import { pullImage, pullRemoteImage } from "../utils/docker/utils";
import { execAsync, execAsyncRemote } from "../utils/process/execAsync";
import { getRemoteDocker } from "../utils/servers/remote-docker";
const getMonitoringImage = () => {
let imageName = "dokploy/monitoring:latest";
if (
(getDokployImageTag() !== "latest" ||
process.env.NODE_ENV === "development") &&
!IS_CLOUD
) {
imageName = "dokploy/monitoring:canary";
}
return imageName;
};
// Swarm tasks are dokploy-monitoring.<slot>.<id>, so this only matches the
// pre-v0.30.0 standalone container. A cleanup failure must not block the deploy.
const removeLegacyContainer = async (
docker: Awaited<ReturnType<typeof getRemoteDocker>>,
serviceName: string,
) => {
try {
await docker.getContainer(serviceName).remove({ force: true });
console.log("Removed legacy monitoring container ✅");
} catch (error: any) {
if (error?.statusCode !== 404) {
console.warn(
`Could not remove legacy monitoring container: ${error?.message ?? error}`,
);
}
}
};
const deployMonitoringService = async (
docker: Awaited<ReturnType<typeof getRemoteDocker>>,
serviceName: string,
settings: CreateServiceOptions,
) => {
await removeLegacyContainer(docker, serviceName);
try {
const service = docker.getService(serviceName);
const inspect = await service.inspect();
await service.update({
version: Number.parseInt(inspect.Version.Index),
...settings,
TaskTemplate: {
...settings.TaskTemplate,
ForceUpdate: (inspect.Spec.TaskTemplate.ForceUpdate ?? 0) + 1,
},
});
console.log("Monitoring Updated ✅");
} catch (error: any) {
if (error?.statusCode && error.statusCode !== 404) {
throw error;
}
await docker.createService(settings);
console.log("Monitoring Started ✅");
}
};
export const setupMonitoring = async (serverId: string) => {
const server = await findServerById(serverId);
const serviceName = "dokploy-monitoring";
const imageName = getMonitoringImage();
const settings: CreateServiceOptions = {
Name: serviceName,
TaskTemplate: {
ContainerSpec: {
Image: imageName,
Env: [`METRICS_CONFIG=${JSON.stringify(server?.metricsConfig)}`],
Mounts: [
{
Type: "bind",
Source: "/var/run/docker.sock",
Target: "/var/run/docker.sock",
ReadOnly: true,
},
{
Type: "bind",
Source: "/sys",
Target: "/host/sys",
ReadOnly: true,
},
{
Type: "bind",
Source: "/etc/os-release",
Target: "/etc/os-release",
ReadOnly: true,
},
{
Type: "bind",
Source: "/proc",
Target: "/host/proc",
ReadOnly: true,
},
{
Type: "bind",
Source: "/etc/dokploy/monitoring/monitoring.db",
Target: "/app/monitoring.db",
},
],
},
Networks: [{ Target: "host" }],
Placement: {
Constraints: ["node.role==manager"],
},
},
Mode: {
Replicated: {
Replicas: 1,
},
},
};
const docker = await getRemoteDocker(serverId);
await execAsyncRemote(
serverId,
"mkdir -p /etc/dokploy/monitoring && touch /etc/dokploy/monitoring/monitoring.db",
);
await pullRemoteImage(imageName, serverId);
await deployMonitoringService(docker, serviceName, settings);
};
export const setupWebMonitoring = async () => {
const webServerSettings = await getWebServerSettings();
const serviceName = "dokploy-monitoring";
const imageName = getMonitoringImage();
const port = webServerSettings?.metricsConfig?.server?.port;
const settings: CreateServiceOptions = {
Name: serviceName,
TaskTemplate: {
ContainerSpec: {
Image: imageName,
Env: [
`METRICS_CONFIG=${JSON.stringify(webServerSettings?.metricsConfig)}`,
],
Mounts: [
{
Type: "bind",
Source: "/var/run/docker.sock",
Target: "/var/run/docker.sock",
ReadOnly: true,
},
{
Type: "bind",
Source: "/sys",
Target: "/host/sys",
ReadOnly: true,
},
{
Type: "bind",
Source: "/etc/os-release",
Target: "/etc/os-release",
ReadOnly: true,
},
{
Type: "bind",
Source: "/proc",
Target: "/host/proc",
ReadOnly: true,
},
{
Type: "bind",
Source: "/etc/dokploy/monitoring/monitoring.db",
Target: "/app/monitoring.db",
},
],
},
Placement: {
Constraints: ["node.role==manager"],
},
},
Mode: {
Replicated: {
Replicas: 1,
},
},
EndpointSpec: {
Ports: [
{
TargetPort: port,
PublishedPort: port,
Protocol: "tcp",
PublishMode: "host",
},
],
},
};
const docker = await getRemoteDocker();
await execAsync(
"mkdir -p /etc/dokploy/monitoring && touch /etc/dokploy/monitoring/monitoring.db",
);
await pullImage(imageName);
await deployMonitoringService(docker, serviceName, settings);
};