#!/usr/bin/env python3 """ Create Docker-Ready LXC Template Creates a fully configured LXC template with Docker pre-installed and optimized """ import sys import os import time sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from proxmox_client import ProxmoxClient def create_docker_lxc_template( template_id: int = 9001, template_name: str = "docker-lxc-template", os_template: str = "local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst", memory: int = 2048, cores: int = 2, disk_size: int = 20, storage: str = "local-lvm" ): """ Create a Docker-ready LXC template Args: template_id: Container ID for the template template_name: Hostname for the template os_template: Base OS template to use memory: Memory allocation in MB cores: CPU cores disk_size: Root disk size in GB storage: Storage pool to use """ client = ProxmoxClient() print(f"πŸš€ Creating Docker-Ready LXC Template (ID: {template_id})") print("=" * 60) # Step 1: Check if template ID is available print("\nπŸ“‹ Step 1: Checking template ID availability...") try: existing = client.get_container(template_id) print(f"❌ Container ID {template_id} already exists!") print(f" Name: {existing.get('hostname', 'unknown')}") response = input(" Delete existing container? (yes/no): ") if response.lower() == 'yes': print(f" Stopping container {template_id}...") try: client.stop_container(template_id) time.sleep(5) except: pass print(f" Deleting container {template_id}...") upid = client.delete_container(template_id) client.wait_for_task(upid, timeout=60) print(" βœ… Container deleted") else: print(" Aborting...") return False except: print(f"βœ… Container ID {template_id} is available") # Step 2: List available OS templates print("\nπŸ“¦ Step 2: Checking available OS templates...") templates = client.list_container_templates() template_found = False for tmpl in templates: if os_template in tmpl.get('volid', ''): template_found = True print(f"βœ… Found OS template: {tmpl['volid']}") break if not template_found: print(f"⚠️ OS template not found: {os_template}") print(" Available templates:") for tmpl in templates[:5]: print(f" - {tmpl['volid']}") print("\n Please download Ubuntu 22.04 template from Proxmox web UI:") print(" Datacenter β†’ β†’ local β†’ CT Templates β†’ Download from template") return False # Step 3: Create the container print(f"\nπŸ”¨ Step 3: Creating LXC container...") print(f" Hostname: {template_name}") print(f" Memory: {memory}MB") print(f" Cores: {cores}") print(f" Disk: {disk_size}GB") try: upid = client.create_container( vmid=template_id, ostemplate=os_template, hostname=template_name, storage=storage, memory=memory, cores=cores, rootfs=f"{storage}:{disk_size}", net0="name=eth0,bridge=vmbr0,ip=dhcp", nameserver="8.8.8.8", searchdomain="localdomain", password="temporary123", # Will be removed later onboot=0, unprivileged=0, # Privileged for Docker features="nesting=1,keyctl=1" # Docker support ) print(f" Task ID: {upid}") print(" Waiting for container creation...") if client.wait_for_task(upid, timeout=120): print("βœ… Container created successfully!") else: print("❌ Container creation failed or timed out") return False except Exception as e: print(f"❌ Error creating container: {e}") return False # Step 4: Start the container print("\n▢️ Step 4: Starting container...") try: upid = client.start_container(template_id) if client.wait_for_task(upid, timeout=60): print("βœ… Container started") time.sleep(10) # Wait for boot else: print("❌ Failed to start container") return False except Exception as e: print(f"❌ Error starting container: {e}") return False # Step 5: Install Docker (via SSH or pct exec) print("\n🐳 Step 5: Installing Docker...") print(" You need to run these commands manually via:") print(f" pct enter {template_id}") print("\n Then run:") print(""" # Update system apt update && apt upgrade -y # Install Docker apt install -y docker.io docker-compose-plugin curl wget git vim htop # Enable Docker service systemctl enable docker systemctl start docker # Verify Docker docker --version docker run hello-world # Clean up apt clean history -c # Exit container exit """) print("\n⏸️ Pausing for manual Docker installation...") print(" Press ENTER after you've completed the Docker installation...") input() # Step 6: Stop the container print("\n⏹️ Step 6: Stopping container...") try: upid = client.shutdown_container(template_id, timeout=60) if client.wait_for_task(upid, timeout=90): print("βœ… Container stopped") else: print("⚠️ Graceful shutdown timed out, forcing stop...") client.stop_container(template_id) time.sleep(5) except Exception as e: print(f"⚠️ Error stopping container: {e}") print(" Forcing stop...") client.stop_container(template_id) time.sleep(5) # Step 7: Convert to template print("\nπŸ“ Step 7: Converting to template...") print(" Run this command manually:") print(f" pct template {template_id}") print("\n Or via Proxmox web UI:") print(f" Right-click container {template_id} β†’ Convert to template") print("\n" + "=" * 60) print("πŸŽ‰ Docker-Ready LXC Template Creation Guide Complete!") print("\nπŸ“‹ Summary:") print(f" Template ID: {template_id}") print(f" Hostname: {template_name}") print(f" Resources: {memory}MB RAM, {cores} cores, {disk_size}GB disk") print(f" Features: Docker pre-installed, nesting enabled, privileged") print("\nπŸ”„ Next Steps:") print(" 1. Convert container to template (see above)") print(" 2. Clone template for new Docker hosts:") print(f" pct clone {template_id} --hostname --full") print(" 3. Configure network/storage for cloned containers") print(" 4. Start and use!") return True def main(): """Main entry point""" import argparse parser = argparse.ArgumentParser(description="Create Docker-ready LXC template") parser.add_argument("--id", type=int, default=9001, help="Template container ID (default: 9001)") parser.add_argument("--name", default="docker-lxc-template", help="Template hostname") parser.add_argument("--memory", type=int, default=2048, help="Memory in MB (default: 2048)") parser.add_argument("--cores", type=int, default=2, help="CPU cores (default: 2)") parser.add_argument("--disk", type=int, default=20, help="Disk size in GB (default: 20)") parser.add_argument("--storage", default="local-lvm", help="Storage pool (default: local-lvm)") parser.add_argument("--template", default="local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst", help="OS template path") args = parser.parse_args() try: success = create_docker_lxc_template( template_id=args.id, template_name=args.name, os_template=args.template, memory=args.memory, cores=args.cores, disk_size=args.disk, storage=args.storage ) if success: print("\nβœ… Template creation process completed!") sys.exit(0) else: print("\n❌ Template creation failed") sys.exit(1) except Exception as e: print(f"\n❌ Error: {e}") import traceback traceback.print_exc() sys.exit(1) if __name__ == "__main__": main()