cloud

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 12, 2025 License: MIT Imports: 24 Imported by: 1

README

@Mogoly/cloud

This package provides a high-level API for Docker service management, enabling programmatic creation and deployment of database services with custom domain assignment and HTTPS support via Traefik integration.

Features

  • Docker Service Management: Create, list, and delete database service instances
  • Supported Databases: PostgreSQL, MySQL, MongoDB, Redis, MariaDB
  • Custom Domain Support: Assign custom domains to services with automatic SSL/TLS via Let's Encrypt
  • Traefik Integration: Automated reverse proxy setup with ACME support
  • Volume Management: Persistent storage configuration for database containers
  • Automatic Port Allocation: Smart port management for service exposure

Prerequisites

  • Docker must be installed and running
  • Docker daemon must be accessible
  • For custom domains: DNS records must point to your server

Installation

go get github.com/DoniLite/Mogoly/cloud

Quick Start

Basic Usage
package main

import (
    "log"
    "github.com/DoniLite/Mogoly/cloud"
)

func main() {
    // Create cloud manager
    manager, err := cloud.NewCloudManager()
    if err != nil {
        log.Fatal(err)
    }
    defer manager.Close()

    // Configure a PostgreSQL service
    config := cloud.ServiceConfig{
        Type:         cloud.PostgreSQL,
        Name:         "my-postgres-db",
        Username:     "admin",
        Password:     "securepassword",
        DatabaseName: "mydb",
        Version:      "14",
        Volumes: []cloud.VolumeMount{
            {
                Name:          "postgres-data",
                ContainerPath: "/var/lib/postgresql/data",
            },
        },
    }

    // Create the service instance
    instance, err := manager.CreateInstance(config)
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("Service created: %s on port %d", instance.Name, instance.ExternalPort)
}

API Reference

CloudManager

The main entry point for managing Docker services.

Creating the Manager
manager, err := cloud.NewCloudManager()
if err != nil {
    log.Fatal(err)
}
defer manager.Close()
Methods
CreateInstance

Create a new database service instance.

func (m *CloudManager) CreateInstance(config ServiceConfig) (*ServiceInstance, error)

Parameters:

  • config: Service configuration (type, name, credentials, volumes, domain, etc.)

Returns:

  • *ServiceInstance: The created service instance
  • error: Any error that occurred during creation

Example:

config := cloud.ServiceConfig{
    Type:     cloud.MySQL,
    Name:     "my-mysql",
    Username: "root",
    Password: "rootpass",
    Version:  "8.0",
}

instance, err := manager.CreateInstance(config)
GetInstance

Retrieve a service instance by ID.

func (m *CloudManager) GetInstance(id string) (*ServiceInstance, bool)
ListInstances

Get all service instances.

func (m *CloudManager) ListInstances() []*ServiceInstance
DeleteInstance

Delete a service instance (removes container and volumes).

func (m *CloudManager) DeleteInstance(id string) error

Warning: This will permanently delete the container and its data.

CreateTraefikBundle

Create and start the Traefik reverse proxy with ACME support.

func (m *CloudManager) CreateTraefikBundle(acmeEmail string) (string, error)

Parameters:

  • acmeEmail: Email address for Let's Encrypt certificate registration

Returns:

  • string: Container ID of the Traefik instance
  • error: Any error that occurred

Note: This must be called before creating services with custom domains.

RecreateWithDomain

Recreate an existing service with a custom domain.

func (m *CloudManager) RecreateWithDomain(id string, domain *DomainConfig) (*ServiceInstance, error)
Types
ServiceType
type ServiceType string

const (
    PostgreSQL ServiceType = "postgresql"
    MySQL      ServiceType = "mysql"
    MongoDB    ServiceType = "mongodb"
    Redis      ServiceType = "redis"
    MariaDB    ServiceType = "mariadb"
)
ServiceConfig
type ServiceConfig struct {
    Type            ServiceType       // Database type
    Name            string            // Service name (required)
    Username        string            // Database username
    Password        string            // Database password
    DatabaseName    string            // Database name
    Version         string            // Specific version tag (e.g., "14", "8.0")
    UseLatestVersion bool             // Use latest version instead
    Variables       map[string]string // Additional environment variables
    ExposedPorts    []string          // Additional ports to expose
    Volumes         []VolumeMount     // Volume configurations
    Domain          *DomainConfig     // Custom domain configuration
}
ServiceInstance
type ServiceInstance struct {
    ID           string      // Unique identifier
    Name         string      // Service name
    Type         ServiceType // Database type
    ContainerID  string      // Docker container ID
    Port         int         // Internal port
    Username     string      // Database username
    Password     string      // Database password
    DatabaseName string      // Database name
    Status       string      // Current status
    CreatedAt    time.Time   // Creation timestamp
    ExternalPort int         // Exposed external port
    Domain       string      // Custom domain
    VolumeNames  []string    // Attached volume names
}
DomainConfig
type DomainConfig struct {
    Domain       string   // e.g., "db.example.com"
    CertResolver string   // Default: "letsencrypt"
    EntryPoint   string   // Default: "websecure" (port 443)
    AllowedCIDRs []string // IP allowlist (optional)
}
VolumeMount
type VolumeMount struct {
    Name          string            // Docker volume name
    ContainerPath string            // Mount path in container
    ReadOnly      bool              // Read-only mount
    Driver        string            // Volume driver (e.g., "local")
    DriverOpts    map[string]string // Driver-specific options
}

Advanced Usage

Using Custom Domains with HTTPS

To use custom domains with automatic SSL/TLS certificates:

Step 1: Create Traefik Bundle

traefikID, err := manager.CreateTraefikBundle("[email protected]")
if err != nil {
    log.Fatal("Failed to create Traefik:", err)
}
log.Printf("Traefik started with ID: %s", traefikID)

Step 2: Create Service with Domain

config := cloud.ServiceConfig{
    Type:     cloud.PostgreSQL,
    Name:     "production-db",
    Username: "admin",
    Password: "securepass",
    Domain: &cloud.DomainConfig{
        Domain:       "db.example.com",
        CertResolver: "letsencrypt",
        EntryPoint:   "websecure",
    },
    Volumes: []cloud.VolumeMount{
        {
            Name:          "prod-db-data",
            ContainerPath: "/var/lib/postgresql/data",
        },
    },
}

instance, err := manager.CreateInstance(config)
if err != nil {
    log.Fatal(err)
}

log.Printf("Production database available at: https://%s", instance.Domain)
Custom Volume Configuration
config := cloud.ServiceConfig{
    Type: cloud.MongoDB,
    Name: "mongo-cluster",
    Volumes: []cloud.VolumeMount{
        {
            Name:          "mongo-data",
            ContainerPath: "/data/db",
            Driver:        "local",
            DriverOpts: map[string]string{
                "type":   "nfs",
                "o":      "addr=10.0.0.1,rw",
                "device": ":/path/to/dir",
            },
        },
        {
            Name:          "mongo-config",
            ContainerPath: "/data/configdb",
            ReadOnly:      false,
        },
    },
}

instance, err := manager.CreateInstance(config)
Environment Variables
config := cloud.ServiceConfig{
    Type: cloud.MySQL,
    Name: "configured-mysql",
    Variables: map[string]string{
        "MYSQL_MAX_CONNECTIONS":    "500",
        "MYSQL_INNODB_BUFFER_POOL": "2G",
    },
}

Best Practices

  1. Always use volumes: Configure persistent volumes to prevent data loss
  2. Secure credentials: Use strong passwords and consider using secrets management
  3. Close the manager: Always defer manager.Close() to clean up resources
  4. Create Traefik first: If using custom domains, create the Traefik bundle before services
  5. Use specific versions: Specify database versions instead of using "latest" for production
  6. Monitor logs: Check Docker logs if services fail to start
  7. DNS configuration: Ensure DNS records point to your server before creating domain-enabled services

Troubleshooting

Service creation fails
  • Ensure Docker daemon is running: docker ps
  • Check if the port is already in use
  • Verify Docker network exists: docker network ls
  • Check Docker logs: docker logs <container-id>
Custom domain SSL issues
  • Verify DNS records point to your server
  • Ensure ports 80 and 443 are accessible
  • Check Traefik logs: docker logs <traefik-container-id>
  • Verify email address is valid for ACME registration
Volume mount issues
  • Ensure the volume name is unique
  • Check volume driver is available: docker volume ls
  • Verify container path is valid for the database type

Examples

See the integration tests for more usage examples.

License

MIT License - see LICENSE for details.

Contributing

This package is part of the Mogoly project.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CloudManager

type CloudManager struct {
	// contains filtered or unexported fields
}

Managing the docker service instances

func NewCloudDBManager

func NewCloudDBManager() (*CloudManager, error)

func (*CloudManager) CreateInstance

func (m *CloudManager) CreateInstance(config ServiceConfig) (*ServiceInstance, error)

Creating a new service instance based on the provided configuration The service is created with default values if not provided After creating the instance, it will be started and exposed to a public port on your machine

func (*CloudManager) CreateTraefikBundle

func (m *CloudManager) CreateTraefikBundle(acmeEmail string) (string, error)

CreateTraefikBundle — programmatically run Traefik with ACME on your network Equivalent to the docker-compose in the docs; keeps ops inside Go if desired.

func (*CloudManager) DeleteInstance

func (m *CloudManager) DeleteInstance(id string) error

Deleting a service instance be careful when using this in production

func (*CloudManager) GetInstance

func (m *CloudManager) GetInstance(id string) (*ServiceInstance, bool)

Get an service instance from its ID

func (*CloudManager) GetInstanceLogs added in v0.2.0

func (m *CloudManager) GetInstanceLogs(id string, tailLines int) (string, error)

GetInstanceLogs fetches the last N lines of logs from a container

func (*CloudManager) ListInstances

func (m *CloudManager) ListInstances() []*ServiceInstance

This returns all service instances

func (*CloudManager) RecreateWithDomain

func (m *CloudManager) RecreateWithDomain(id string, domain *DomainConfig) (*ServiceInstance, error)

RecreateWithDomain — convenience to switch/add domain (labels are immutable)

func (*CloudManager) RefreshInstanceStatus added in v0.2.0

func (m *CloudManager) RefreshInstanceStatus(id string) error

RefreshInstanceStatus syncs instance status from Docker

func (*CloudManager) RestartInstance added in v0.2.0

func (m *CloudManager) RestartInstance(id string) error

RestartInstance restarts a running or stopped instance

func (*CloudManager) StartInstance added in v0.2.0

func (m *CloudManager) StartInstance(id string) error

StartInstance starts a stopped instance

func (*CloudManager) StopInstance added in v0.2.0

func (m *CloudManager) StopInstance(id string) error

StopInstance stops a running instance without deleting it

type DomainConfig

type DomainConfig struct {
	Domain       string   `json:"domain" yaml:"domain"`                                   // e.g. donidb.com
	CertResolver string   `json:"cert_resolver,omitempty" yaml:"cert_resolver,omitempty"` // default "letsencrypt"
	EntryPoint   string   `json:"entrypoint,omitempty" yaml:"entrypoint,omitempty"`       // default "websecure" (443)
	AllowedCIDRs []string `json:"allowed_cidrs,omitempty" yaml:"allowed_cidrs,omitempty"` // optional IP allow-list
}

type ServiceConfig

type ServiceConfig struct {
	Type            ServiceType       `json:"type,omitempty" yaml:"type,omitempty"`
	Name            string            `json:"name" yaml:"name"`
	Username        string            `json:"username,omitempty" yaml:"username,omitempty"`
	Password        string            `json:"password,omitempty" yaml:"password,omitempty"`
	DatabaseName    string            `json:"database_name,omitempty" yaml:"database_name,omitempty"`
	Version         string            `json:"version,omitempty" yaml:"version,omitempty"`
	UsLatestVersion bool              `json:"use_latest_version,omitempty" yaml:"use_latest_version,omitempty"`
	Variables       map[string]string `json:"variables,omitempty" yaml:"variables,omitempty"`
	ExposedPorts    []string          `json:"exposed_ports,omitempty" yaml:"exposed_ports,omitempty"`

	Volumes []VolumeMount `json:"volumes,omitempty" yaml:"volumes,omitempty"`
	Domain  *DomainConfig `json:"domain,omitempty" yaml:"domain,omitempty"`
}

The necessary config for a docker service creation

type ServiceInstance

type ServiceInstance struct {
	ID           string      `json:"id"`
	Name         string      `json:"name"`
	Type         ServiceType `json:"type"`
	ContainerID  string      `json:"container_id"`
	Port         int         `json:"port"`
	Username     string      `json:"username,omitempty"`
	Password     string      `json:"password,omitempty"`
	DatabaseName string      `json:"database_name,omitempty"`
	Status       string      `json:"status"`
	CreatedAt    time.Time   `json:"created_at"`
	ExternalPort int         `json:"external_port"`

	Domain      string   `json:"domain,omitempty"`
	VolumeNames []string `json:"volume_names,omitempty"`
}

Represents a docker service instance

type ServiceType

type ServiceType string

Represents a docker service name

const (
	PostgreSQL ServiceType = "postgresql"
	MySQL      ServiceType = "mysql"
	MongoDB    ServiceType = "mongodb"
	Redis      ServiceType = "redis"
	MariaDB    ServiceType = "mariadb"
)

type VolumeMount

type VolumeMount struct {
	Name          string            `json:"name" yaml:"name"`                     // docker volume name
	ContainerPath string            `json:"container_path" yaml:"container_path"` // e.g. /var/lib/postgresql/data
	ReadOnly      bool              `json:"read_only,omitempty" yaml:"read_only,omitempty"`
	Driver        string            `json:"driver,omitempty" yaml:"driver,omitempty"` // "local" etc.
	DriverOpts    map[string]string `json:"driver_opts,omitempty" yaml:"driver_opts,omitempty"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL