Skip to content

Commit

Permalink
Add monitors support (#20)
Browse files Browse the repository at this point in the history
* Add monitors support

Added support for Docker Up and Docker Container Up monitor
Cleaned up Dockerfile for DIND rootless
Minor cleanup
  • Loading branch information
dave-lang authored Dec 13, 2024
1 parent 9a28d9e commit 73ae0ca
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 40 deletions.
35 changes: 24 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,26 @@ Created to manage a local Docker install for a home server. Current supports:
* Viewing docker system info
* View, automatically refresh and filter container logs
* View container properties
* 2 new monitor types for [System and server status](https://webmin.com/docs/modules/system-and-server-status/) - 'Docker Up' & 'Docker Container Up'

Currently translated to English, Italian and Polish. UI is responsive across all device sizes.

If you're after a full Docker web interface you should consider https://www.portainer.io or https://yacht.sh.

## How does it work?
It uses the Docker CLI and abuses the `--format {{}}` arg for output parsing. This should work for normal installs of docker - rootless docker and other alternative installs is currently not supported.
It uses the Docker CLI and abuses the `--format {{}}` arg for output parsing. This should work for normal installs of Docker and Rootless Docker installs where the webmin user has an appropriate Docker context and permissions applied (see [Rootless Docker](#rootless-docker)).

For monitors checks, `docker info` is used to get the current Docker status to avoid complexities in determining how Docker is set to startup and run. Container health is checked via `docker container inspect`.

## Install
The fastest way to install is to follow the "Http URL" method (https://webmin.com/docs/modules/webmin-configuration/#installing) and use the latest release package using [https://github.com/dave-lang/webmin-docker/releases/latest/download/docker.wbm.gz](https://github.com/dave-lang/webmin-docker/releases/latest/download/docker.wbm.gz).

Alternatively you can download and install it directly from the [releases page](https://github.com/dave-lang/webmin-docker/releases) or it build manually, the packaging steps are in the GitHub action in the repo.

Once installed a new option 'Docker Containers' will appear in the menu under 'Servers'.
Once installed:
- 'View docker containers' will appear in the menu under 'Servers'
- If you are using an alternative context for Docker, set this under the module configuration link in the top left of "View docker containers"
- 'Docker Up' & 'Docker Container Up' will appear in the monitors that can be configured under 'Tools' > 'System and server status'

## Rootless Docker

Expand All @@ -36,16 +42,23 @@ Experimental rootless docker support has been added via [docker contexts](https:

## Functionality

### Container listing/actions
<img width="1728" alt="image" src="https://github.com/user-attachments/assets/58de37c1-2f8b-42d9-9b49-ea9f541f9e53">
**Container listing/actions**

<img width="480" alt="Screenshot showing container listing" src="https://github.com/user-attachments/assets/58de37c1-2f8b-42d9-9b49-ea9f541f9e53">

**Container inspection and logs**

<img width="480" alt="Screenshot showing container info" src="https://github.com/user-attachments/assets/940c98c8-fe8d-442c-acc5-9757a3ff4102">

<img width="480" alt="Screenshot showing container logs" src="https://github.com/user-attachments/assets/17bdeec8-c285-41bc-a6d1-3ddcffd34e36">

**Host docker information**

### Container inspection and logs
<img width="1728" alt="image" src="https://github.com/user-attachments/assets/940c98c8-fe8d-442c-acc5-9757a3ff4102">
<img width="480" alt="Screenshot showing docker info display" src="https://github.com/user-attachments/assets/d059e89b-8f29-4ee1-b0dc-5caac3d3d8bc">

<img width="1728" alt="image" src="https://github.com/user-attachments/assets/17bdeec8-c285-41bc-a6d1-3ddcffd34e36">
**Monitors**

### Host docker information
<img width="1728" alt="image" src="https://github.com/user-attachments/assets/d059e89b-8f29-4ee1-b0dc-5caac3d3d8bc">
<img width="480" alt="Screenshot showing monitor support options" src="https://github.com/user-attachments/assets/b50d10ae-de5b-4329-8d49-b13e6efae09c">

## Contributing

Expand All @@ -59,7 +72,7 @@ The development environment creates 2 containers:
- webmin_master - Webmin on focal ubuntu with docker & webmin auto start, available on port 10000 on the host
- docker_dd - DIND container with rootless docker and webmin, available on port 20000 on the host (DOES NOT AUTO START). Very hacky.

### To use
### Setup
1. `cd tools`
1. `docker-compose up -d` to run docker compose as daemon
1. Open http://localhost:10000 to access the webmin console for docker on Ubuntu
Expand Down Expand Up @@ -98,4 +111,4 @@ To start a test container
1. `cd /home/dind`
2. `docker-compose --context rootless up -d`

Use `docker exec -it docker_dd /bin/sh` to get a console.
Use `docker exec -it docker_dd /bin/sh` to get a console.
6 changes: 3 additions & 3 deletions docker/container.cgi
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ our (%in);
my $container = $in{'container'};
my $tab = $in{'tab'};

my ($code, $container_name) = get_container_attr($container, 'Name');
my ($code, $result) = get_container_attr($container, 'Name');
if ($code) { # Bad container id
ui_print_header(undef, text('view_container_title', "not found"), "", undef, undef, $in{'nonavlinks'});
&ui_print_endpage(ui_alert_box($code, 'danger'), "Back", "/");
&ui_print_endpage(ui_alert_box($result, 'danger'), "Back", "/");
}

# Trim leading /
$container_name = substr $container_name, 1;
my $container_name = substr($result, 1);
ui_print_header(undef, text('view_container_title', $container_name), "", undef, undef, $in{'nonavlinks'});

my @tabs = ( [ 'log', &text('tab_log') ],
Expand Down
30 changes: 18 additions & 12 deletions docker/docker-lib.pl
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,37 @@

init_config();

sub docker_command {
sub get_context {
our (%config);
my $context = "";

if ($config{'docker_context'}) {
$context = ' --context "' . $config{'docker_context'} . '"';
}

return $context;
}

sub docker_command {
my($command, $format, $safe) = @_;
$format ||= "";
my $context = "";
$safe ||= 1;

if ($format) {
$format = ' --format "' . $format . '"'
}

# If there's a context set, use it
if ($config{'docker_context'}) {
$context = ' --context "' . $config{'docker_context'} . '"';
}
my $context = &get_context();

my ($result, $fail);
my $code = execute_command('docker' . $context . ' ' . $command . $format, undef, \$result, \$fail, 0, $safe);

if ($code != 0) {
my $trimEnd = index($fail, "errors pretty printing info");
if ($trimEnd > 0) {
$fail = substr($fail, 0, $trimEnd);
}
return $code, $fail;
}

Expand All @@ -41,7 +52,7 @@ sub docker_command {
sub get_status {
my ($code, $result) = docker_command('info');
if ($code != 0) {
return $result;
return $code, $result;
}

# my $json = decode_json($result);
Expand Down Expand Up @@ -78,12 +89,7 @@ sub get_container_attr
{
my($container, $attr) = @_;
my ($code, $result) = docker_command('inspect --type=container ' . $container, '{{.' . $attr . '}}');
if ($code != 0) {
print "Bang";
return $result;
}

return 0, $result;
return $code, $result;
}

sub get_stats
Expand Down
9 changes: 8 additions & 1 deletion docker/index.cgi
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/perl
$trust_unknown_referers = 1;
use strict;
use warnings;
use Data::Dumper;
Expand Down Expand Up @@ -27,11 +28,12 @@ print ui_tabs_start(\@tabs, 'info', 'containers', 1);
print ui_tabs_start_tab('mode', 'info');
my($status_fail, $status) = get_status();
if ($status_fail) {
print ui_alert_box($status_fail, 'danger');
print ui_alert_box($status, 'danger');
} else {
#print circular_grid($status); # Ugly recursive output
print "<pre>" . html_escape($status) . "</pre>";
}

print ui_tabs_end_tab('mode', 'info');

# CONTAINERS TAB
Expand All @@ -46,6 +48,10 @@ if ($fail) {
print &ui_submit(text('label_refresh'));
print &ui_form_end(),"<br>\n";

if (scalar(@containers) == 0) {
print "No containers defined";
} else {

# Provide some basic responsive support across all themes
print '<style>
.panel-body tr td { padding: 5px 10px 7px 10px !important}
Expand Down Expand Up @@ -140,6 +146,7 @@ if ($fail) {

}
print ui_columns_end();
}
}

print ui_tabs_end_tab('mode', 'containers');
Expand Down
71 changes: 71 additions & 0 deletions docker/status_monitor.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/perl
use WebminCore;

do 'docker-lib.pl';

# status_monitor_list()
# Return a list of supported monitor types
sub status_monitor_list
{
return ( [ "docker_up", "Docker Up"], [ "docker_containerup", "Docker Container Up"], );
}

# status_monitor_status(type, &monitor, from-ui)
# Check the docker or container status
sub status_monitor_status
{
my ($type, $monitor, $fromui) = @_;

# Basic status check via running docker info and checking return
# This gets around the various ways docker can be run (supervisor, systemctl etc)
if ($type eq "docker_up") {
my ($status, $result) = &get_status();
return {
'up' => $status == 0 ? 1 : 0,
"desc" => $status != 0 ? $result : ''
};
} elsif ($type eq "docker_containerup") {
$container = $monitor->{'docker_container'};

my ($status, $result) = &get_container_attr($container, "State.Status");

my $ok = $status == 0 && $result == "running" ? 1 : 0;
return {
'up' => $ok,
'desc' => ucfirst($result)
};
}
return { 'up' => -1,
'desc' => $text{'monitor_notype'} };
}

# status_monitor_dialog(type, &monitor)
# Return form for configuring monitors
sub status_monitor_dialog
{
my ($type, $mon) = @_;

if ($type eq "docker_up") {
# Nada
} elsif ($type eq "docker_containerup") {
return &ui_table_row("Container", # $text{'monitor_container'},
&ui_textbox("docker_container", html_escape($mon->{'docker_container'}), 50)
);
} else {
return undef;
}
}

# status_monitor_parse(type, &monitor, &in)
# Parse form for selecting a rule
sub status_monitor_parse
{
my ($type, $mon, $in) = @_;
if ($type eq "docker_up") {
# Nada
} elsif ($type eq "docker_containerup") {
$mon->{'docker_container'} = $in->{'docker_container'};
}
}

1;
14 changes: 1 addition & 13 deletions tools/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,8 @@ ENV DEBIAN_FRONTEND=noninteractive TZ=Australia/Brisbane
RUN apt-get update -qq -y && \
apt-get upgrade -y && \
apt-get install -y \
# wget \
# curl \
# apt-transport-https \
# lsb-release \
# ca-certificates \
gnupg2 \
# software-properties-common \
# locales \
# cron \
net-tools
# vim \
# docker \
# docker-compose
# RUN dpkg-reconfigure locales

# Install Webmin
RUN echo root:password | chpasswd && \
Expand All @@ -34,7 +22,7 @@ RUN echo root:password | chpasswd && \
apt-get install -y webmin && \
# apt-get clean && \
echo "$(cat /etc/webmin/webmin.acl) docker" > /etc/webmin/webmin.acl && \
mkdir /etc/webmin/docker
mkdir /etc/webmin/docker && chmod 755 /etc/webmin/docker

# Last 2 line adds docker module to webmin's acl, for easier development and creates the config dir.
# Also requires the volume & config in the compose
Expand Down

0 comments on commit 73ae0ca

Please sign in to comment.