Deploy a Full Docker Management Stack in 60 Seconds
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.
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:
- Navigate to Environments > Add Environment
- Select Agent as the connection method
- Enter the remote server's IP and port (e.g.,
192.168.1.101:9001) - Give the environment a descriptive name (e.g., "Production DB Server")
- 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:
- Navigate to Environments > Add Environment
- Select Docker > API
- Enter the SSH connection string:
ssh://[email protected] - 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
- Click Containers in the sidebar
- Click Add Container
- Fill in the configuration:
- Name: my-nginx
- Image: nginx:alpine
- Port mapping: Host 8080 -> Container 80
- Restart policy: Unless stopped
- 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:
- Click Stacks in the sidebar
- Click Add Stack
- Give it a name (e.g., "wordpress")
- 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:
- Add environment variables in the Environment Variables section
- 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
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.