Managing Docker containers through the command line works, but it does not scale. When you are running multiple services across multiple servers, you need a visual dashboard that gives you instant insight into container health, resource usage, and deployment status. With usulnet, you can go from a bare Docker installation to a fully operational management dashboard in under 60 seconds.

This tutorial walks you through every step: deploying usulnet, initial configuration, adding remote nodes, launching your first container through the UI, and hardening the setup for production.

Prerequisites

Before starting, make sure you have the following:

  • A Linux server (Ubuntu 22.04+, Debian 12+, CentOS 9+, or any distribution with Docker support)
  • Docker Engine 24.0 or later installed
  • Docker Compose v2 (bundled with modern Docker installations)
  • At least 1 GB of free RAM and 5 GB of disk space
  • Port 443 (or your chosen port) accessible if you want remote access

If Docker is not installed yet, here is the fastest way to get it:

# Install Docker using the official convenience script
curl -fsSL https://get.docker.com | sh

# Add your user to the docker group (log out and back in after)
sudo usermod -aG docker $USER

# Verify the installation
docker --version
docker compose version

Step 1: Deploy usulnet (The 60-Second Part)

Create a directory for your usulnet deployment and set up the Docker Compose configuration:

# Create and enter the deployment directory
mkdir -p /opt/usulnet && cd /opt/usulnet

# Create the docker-compose.yml file
cat <<'EOF' > docker-compose.yml
version: "3.8"

services:
  usulnet:
    image: usulnet/usulnet:latest
    container_name: usulnet
    restart: unless-stopped
    ports:
      - "9443:9443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - usulnet_data:/data
    environment:
      - TZ=UTC

volumes:
  usulnet_data:
EOF

# Launch usulnet
docker compose up -d

That is it. Three commands, and your Docker management dashboard is running. Open your browser and navigate to https://your-server-ip:9443.

Tip: The first time you access usulnet, it will use a self-signed SSL certificate. Your browser will show a security warning. This is expected for initial setup; we will configure proper TLS later.

Step 2: Initial Configuration

When you first access the usulnet UI, you will go through a quick setup wizard:

Create Your Admin Account

The first screen prompts you to create an administrator account. Choose a strong password since this account has full control over your Docker infrastructure:

  • Use a password with at least 12 characters
  • Include uppercase, lowercase, numbers, and symbols
  • Do not reuse passwords from other services

Connect the Local Docker Environment

After creating your account, usulnet automatically detects the local Docker environment through the mounted socket. You will see your local Docker node appear in the dashboard, showing:

  • Docker version and API version
  • Number of running, stopped, and total containers
  • Images, volumes, and networks on the host
  • CPU, memory, and disk utilization

Explore the Dashboard

The main dashboard provides a bird's-eye view of your Docker infrastructure. Take a moment to explore the key sections:

  • Containers — List all containers, view logs, start/stop/restart, and access the shell
  • Images — Browse pulled images, remove unused ones, and pull new images
  • Volumes — Inspect data volumes, see which containers use them, and manage storage
  • Networks — View Docker networks, inspect connected containers, and create new networks
  • Stacks — Deploy and manage Docker Compose stacks directly from the UI

Step 3: Adding Remote Nodes

The real power of usulnet comes from managing multiple Docker hosts from a single dashboard. There are several ways to add remote nodes.

Method A: Agent-Based Connection

The agent approach is the simplest and works even when remote nodes are behind firewalls or NAT. On the remote server, deploy the usulnet agent:

# On the remote server
docker run -d \
  --name usulnet-agent \
  --restart always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -p 9001:9001 \
  usulnet/agent:latest

Then in the usulnet UI:

  1. Navigate to Environments > Add Environment
  2. Select Agent as the connection method
  3. Enter the remote server's IP and port (e.g., 192.168.1.101:9001)
  4. Give the environment a descriptive name (e.g., "Production DB Server")
  5. Click Connect

Method B: Docker API Over TLS

For direct API connections, you need to configure Docker's remote API with TLS authentication on the remote host:

# Generate TLS certificates (on the remote host)
mkdir -p /etc/docker/tls

# Generate CA key and certificate
openssl genrsa -out /etc/docker/tls/ca-key.pem 4096
openssl req -new -x509 -days 365 \
  -key /etc/docker/tls/ca-key.pem \
  -out /etc/docker/tls/ca.pem \
  -subj "/CN=Docker CA"

# Generate server key and certificate
openssl genrsa -out /etc/docker/tls/server-key.pem 4096
openssl req -new \
  -key /etc/docker/tls/server-key.pem \
  -out /etc/docker/tls/server.csr \
  -subj "/CN=$(hostname)"

# Sign the server certificate
echo "subjectAltName = IP:$(hostname -I | awk '{print $1}'),IP:127.0.0.1" \
  > /etc/docker/tls/extfile.cnf
openssl x509 -req -days 365 \
  -in /etc/docker/tls/server.csr \
  -CA /etc/docker/tls/ca.pem \
  -CAkey /etc/docker/tls/ca-key.pem \
  -CAcreateserial \
  -out /etc/docker/tls/server-cert.pem \
  -extfile /etc/docker/tls/extfile.cnf

# Configure Docker daemon for TLS
cat <<EOF > /etc/docker/daemon.json
{
  "tls": true,
  "tlsverify": true,
  "tlscacert": "/etc/docker/tls/ca.pem",
  "tlscert": "/etc/docker/tls/server-cert.pem",
  "tlskey": "/etc/docker/tls/server-key.pem",
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"]
}
EOF

sudo systemctl restart docker

Generate client certificates and upload them in the usulnet UI when adding the remote environment.

Method C: SSH Connection

If you have SSH access to the remote server, usulnet can connect through an SSH tunnel without requiring any additional setup on the remote host:

  1. Navigate to Environments > Add Environment
  2. Select Docker > API
  3. Enter the SSH connection string: ssh://[email protected]
  4. Upload your SSH private key or use password authentication

Step 4: Deploy Your First Container

Now that usulnet is running and your nodes are connected, let us deploy a container through the UI.

Deploying a Single Container

  1. Click Containers in the sidebar
  2. Click Add Container
  3. Fill in the configuration:
    • Name: my-nginx
    • Image: nginx:alpine
    • Port mapping: Host 8080 -> Container 80
    • Restart policy: Unless stopped
  4. Click Deploy the container

Within seconds, you will see the container running in the dashboard. Click on it to view logs, inspect settings, or open a console session.

Deploying a Full Stack with Compose

For multi-service applications, use the Stacks feature to deploy Docker Compose files directly:

  1. Click Stacks in the sidebar
  2. Click Add Stack
  3. Give it a name (e.g., "wordpress")
  4. Paste your Docker Compose content:
version: "3.8"

services:
  wordpress:
    image: wordpress:latest
    restart: unless-stopped
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - wp_data:/var/www/html
    depends_on:
      - db

  db:
    image: mariadb:11
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql

volumes:
  wp_data:
  db_data:
  1. Add environment variables in the Environment Variables section
  2. Click Deploy the stack

usulnet will pull the images, create the volumes and network, and start both services. You can monitor the deployment progress in real time.

Step 5: Security Hardening

Before exposing usulnet to the internet or using it in production, apply these security measures:

Set Up a Reverse Proxy with TLS

Place usulnet behind a reverse proxy with a real SSL certificate. Here is a minimal Nginx + Let's Encrypt setup:

# /etc/nginx/sites-available/usulnet
server {
    listen 80;
    server_name docker.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name docker.example.com;

    ssl_certificate /etc/letsencrypt/live/docker.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/docker.example.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass https://127.0.0.1:9443;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket support for container console
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
# Obtain a Let's Encrypt certificate
sudo certbot --nginx -d docker.example.com

Restrict Network Access

# Only allow access from specific IPs using iptables
sudo iptables -A INPUT -p tcp --dport 9443 -s 10.0.0.0/8 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 9443 -s 192.168.0.0/16 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 9443 -j DROP

# Or use UFW (simpler)
sudo ufw allow from 10.0.0.0/8 to any port 9443
sudo ufw allow from 192.168.0.0/16 to any port 9443
sudo ufw deny 9443

Enable Authentication Features

  • Disable public registration — In Settings, ensure that only administrators can create new user accounts
  • Set session timeouts — Configure automatic logout after a period of inactivity
  • Use RBAC — Create teams with role-based access control, limiting what each user can do on each environment
  • Enable LDAP/OAuth — Integrate with your existing identity provider for centralized authentication

Secure the Docker Socket

The Docker socket (/var/run/docker.sock) provides root-equivalent access to the host. Protect it:

# Run usulnet with read-only socket access where possible
volumes:
  - /var/run/docker.sock:/var/run/docker.sock:ro

# Consider using a Docker socket proxy for fine-grained control
services:
  socket-proxy:
    image: tecnativa/docker-socket-proxy
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      CONTAINERS: 1
      IMAGES: 1
      NETWORKS: 1
      VOLUMES: 1
      SERVICES: 1
      TASKS: 1
      INFO: 1
      POST: 1
      # Disable dangerous operations
      BUILD: 0
      COMMIT: 0
      EXEC: 0  # Set to 1 if you need console access

  usulnet:
    image: usulnet/usulnet:latest
    # Connect through the proxy instead of direct socket
    environment:
      - DOCKER_HOST=tcp://socket-proxy:2375

Step 6: Regular Maintenance

Keep your usulnet deployment healthy with these maintenance tasks:

Update usulnet

# Pull the latest version and recreate the container
cd /opt/usulnet
docker compose pull
docker compose up -d

# Verify the update
docker compose logs usulnet | tail -20

Backup usulnet Data

# Backup the usulnet data volume
docker run --rm \
  -v usulnet_data:/source:ro \
  -v $(pwd):/backup \
  alpine tar czf /backup/usulnet_backup_$(date +%Y%m%d).tar.gz \
  -C /source .

Monitor Disk Usage

# Check Docker disk usage
docker system df

# Clean up unused resources (careful in production!)
docker system prune --volumes  # Removes unused volumes too
docker image prune -a          # Removes all unused images
Tip: Set up a weekly cron job to clean dangling images and stopped containers. This prevents disk usage from growing unbounded over time. Use docker image prune (without -a) to safely remove only dangling images without affecting any images that are in use.

Conclusion

You now have a fully operational Docker management stack. From a single dashboard, you can monitor containers across multiple servers, deploy new services, view logs, manage volumes and networks, and control access with role-based permissions.

The 60-second deployment is just the beginning. As your infrastructure grows, usulnet scales with you: add more nodes, create teams with granular permissions, deploy complex stacks, and maintain visibility across your entire container fleet. The goal is to make Docker management feel as natural as managing files on your desktop, without sacrificing the power and flexibility that makes Docker great.