Skip to content

Commit

Permalink
GH-5214: feat: Add Docker service availability monitoring
Browse files Browse the repository at this point in the history
Introduces Docker service availability to monitor uptime
and status of Docker services alongside existing types.
Updates the database schema to support "docker_service".
Enhances the user interface to allow configuration of Docker
service parameters within the monitor setup.

This change allows for more granular monitoring capabilities
by checking the running state of services in a Docker environment.

Relates to implementing extended Docker monitoring functionalities.

implements #5214

Signed-off-by: Bryan Gonzalez <[email protected]>
  • Loading branch information
SheepReaper committed Oct 18, 2024
1 parent d7ffa33 commit bd719d9
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ It is a temporary live demo, all data will be deleted after 10 minutes. Sponsore

## ⭐ Features

- Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / HTTP(s) Json Query / Ping / DNS Record / Push / Steam Game Server / Docker Containers
- Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / HTTP(s) Json Query / Ping / DNS Record / Push / Steam Game Server / Docker Containers / Docker Services
- Fancy, Reactive, Fast UI/UX
- Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [90+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications)
- 20-second intervals
Expand Down
11 changes: 11 additions & 0 deletions db/knex_migrations/2024-10-17-0000-add-docker-service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
exports.up = function (knex) {
return knex.schema.alterTable("monitor", function (table) {
table.string("docker_service", 255);
});
};

exports.down = function (knex) {
return knex.schema.alterTable("monitor", function (table) {
table.dropColumn("docker_service");
});
};
49 changes: 49 additions & 0 deletions server/model/monitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ class Monitor extends BeanModel {
dns_resolve_server: this.dns_resolve_server,
dns_last_result: this.dns_last_result,
docker_container: this.docker_container,
docker_service: this.docker_service,
docker_host: this.docker_host,
proxyId: this.proxy_id,
notificationIDList: preloadData.notifications.get(this.id) || {},
Expand Down Expand Up @@ -754,6 +755,54 @@ class Monitor extends BeanModel {
} else {
throw Error("Container State is " + res.data.State.Status);
}
} else if (this.type === "docker-service-availability") { // TODO: add a service-health to count running vs desired (needs services api)
log.debug("monitor", `[${this.name}] Prepare Options for Axios`);

const options = {
url: `/tasks?filters={"service":{"${this.docker_service}":true}}`,
timeout: this.interval * 1000 * 0.8,
headers: {
"Accept": "*/*",
},
httpsAgent: new https.Agent({
maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940)
rejectUnauthorized: !this.getIgnoreTls(),
secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,
}),
httpAgent: new http.Agent({
maxCachedSessions: 0,
}),
};

const dockerHost = await R.load("docker_host", this.docker_host);

if (!dockerHost) {
throw new Error("Failed to load docker host config");
}

if (dockerHost._dockerType === "socket") {
options.socketPath = dockerHost._dockerDaemon;
} else if (dockerHost._dockerType === "tcp") {
options.baseURL = DockerHost.patchDockerURL(dockerHost._dockerDaemon);
options.httpsAgent = new https.Agent(
DockerHost.getHttpsAgentOptions(dockerHost._dockerType, options.baseURL)
);
}

log.debug("monitor", `[${this.name}] Axios Request (get service tasks)`);
let res = await axios.request(options);

if (res.data.message) {
throw Error(res.data.message);
}

if (res.data.filter((task) => task.Status.State === "running").length) {
bean.status = UP;
bean.msg = `Service: ${this.docker_service} is available`;
} else {
bean.status = DOWN;
bean.msg = `Service: ${this.docker_service} is Down. No replicas available`;
}
} else if (this.type === "sqlserver") {
let startTime = dayjs().valueOf();

Expand Down
1 change: 1 addition & 0 deletions server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,7 @@ let needSetup = false;
bean.dns_resolve_server = monitor.dns_resolve_server;
bean.pushToken = monitor.pushToken;
bean.docker_container = monitor.docker_container;
bean.docker_service = monitor.docker_service;
bean.docker_host = monitor.docker_host;
bean.proxyId = Number.isInteger(monitor.proxyId) ? monitor.proxyId : null;
bean.mqttUsername = monitor.mqttUsername;
Expand Down
15 changes: 13 additions & 2 deletions src/pages/EditMonitor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
<option value="docker">
{{ $t("Docker Container") }}
</option>
<option value="docker-service-availability">
{{ $t("Docker Service (Simple Availability)") }}
</option>

<option value="real-browser">
HTTP(s) - Browser Engine (Chrome/Chromium) (Beta)
Expand Down Expand Up @@ -367,9 +370,16 @@
<input id="docker_container" v-model="monitor.docker_container" type="text" class="form-control" required>
</div>

<!-- Docker Service Name / ID -->
<!-- For Docker Service Type -->
<div v-if="monitor.type === 'docker-service-availability'" class="my-3">
<label for="docker_service" class="form-label">{{ $t("Service Name / ID") }}</label>
<input id="docker_service" v-model="monitor.docker_service" type="text" class="form-control" required>
</div>

<!-- Docker Host -->
<!-- For Docker Type -->
<div v-if="monitor.type === 'docker'" class="my-3">
<div v-if="['docker', 'docker-service-availability'].includes(monitor.type)" class="my-3">
<div class="mb-3">
<label for="docker-host" class="form-label">{{ $t("Docker Host") }}</label>
<ActionSelect
Expand Down Expand Up @@ -1103,6 +1113,7 @@ const monitorDefaults = {
dns_resolve_type: "A",
dns_resolve_server: "1.1.1.1",
docker_container: "",
docker_service: "",
docker_host: null,
proxyId: null,
mqttUsername: "",
Expand Down Expand Up @@ -1730,7 +1741,7 @@ message HealthCheckResponse {
return false;
}
}
if (this.monitor.type === "docker") {
if ([ "docker", "docker-service-availability" ].includes(this.monitor.type)) {
if (this.monitor.docker_host == null) {
toast.error(this.$t("DockerHostRequired"));
return false;
Expand Down

0 comments on commit bd719d9

Please sign in to comment.