253 líneas
6.2 KiB
Go
253 líneas
6.2 KiB
Go
package proxy
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/manalejandro/buque/internal/docker"
|
|
"github.com/manalejandro/buque/internal/models"
|
|
)
|
|
|
|
const (
|
|
nginxProxyImage = "nginxproxy/nginx-proxy:latest"
|
|
nginxProxyCompanionImage = "nginxproxy/acme-companion:latest"
|
|
)
|
|
|
|
// NginxManager manages nginx-proxy deployment and configuration
|
|
type NginxManager struct {
|
|
config models.NginxProxyConfig
|
|
dockerClient *docker.Client
|
|
composeManager *docker.ComposeManager
|
|
}
|
|
|
|
// NewNginxManager creates a new nginx-proxy manager
|
|
func NewNginxManager(config models.NginxProxyConfig) (*NginxManager, error) {
|
|
dockerClient, err := docker.NewClient()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
composeManager, err := docker.NewComposeManager()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &NginxManager{
|
|
config: config,
|
|
dockerClient: dockerClient,
|
|
composeManager: composeManager,
|
|
}, nil
|
|
}
|
|
|
|
// Close closes the nginx manager
|
|
func (nm *NginxManager) Close() error {
|
|
return nm.dockerClient.Close()
|
|
}
|
|
|
|
// Deploy deploys the nginx-proxy environment
|
|
func (nm *NginxManager) Deploy(ctx context.Context) error {
|
|
// Create nginx-proxy directory if it doesn't exist
|
|
if err := os.MkdirAll(nm.config.Path, 0755); err != nil {
|
|
return fmt.Errorf("failed to create nginx-proxy directory: %w", err)
|
|
}
|
|
|
|
// Create docker-compose.yml
|
|
composeContent := nm.generateComposeFile()
|
|
composePath := filepath.Join(nm.config.Path, "docker-compose.yml")
|
|
if err := os.WriteFile(composePath, []byte(composeContent), 0644); err != nil {
|
|
return fmt.Errorf("failed to write compose file: %w", err)
|
|
}
|
|
|
|
// Create network if it doesn't exist
|
|
exists, err := nm.dockerClient.NetworkExists(ctx, nm.config.NetworkName)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to check network: %w", err)
|
|
}
|
|
|
|
if !exists {
|
|
if err := nm.dockerClient.CreateNetwork(ctx, nm.config.NetworkName); err != nil {
|
|
return fmt.Errorf("failed to create network: %w", err)
|
|
}
|
|
fmt.Printf("Created network: %s\n", nm.config.NetworkName)
|
|
}
|
|
|
|
// Deploy using docker-compose
|
|
env := models.Environment{
|
|
Name: "nginx-proxy",
|
|
Path: nm.config.Path,
|
|
ComposeFile: "docker-compose.yml",
|
|
Enabled: true,
|
|
}
|
|
|
|
fmt.Println("Deploying nginx-proxy...")
|
|
if err := nm.composeManager.Up(ctx, env, true); err != nil {
|
|
return fmt.Errorf("failed to deploy nginx-proxy: %w", err)
|
|
}
|
|
|
|
fmt.Println("Nginx-proxy deployed successfully!")
|
|
return nil
|
|
}
|
|
|
|
// Remove removes the nginx-proxy environment
|
|
func (nm *NginxManager) Remove(ctx context.Context) error {
|
|
env := models.Environment{
|
|
Name: "nginx-proxy",
|
|
Path: nm.config.Path,
|
|
ComposeFile: "docker-compose.yml",
|
|
Enabled: true,
|
|
}
|
|
|
|
fmt.Println("Removing nginx-proxy...")
|
|
if err := nm.composeManager.Down(ctx, env, true); err != nil {
|
|
return fmt.Errorf("failed to remove nginx-proxy: %w", err)
|
|
}
|
|
|
|
fmt.Println("Nginx-proxy removed successfully!")
|
|
return nil
|
|
}
|
|
|
|
// Status returns the status of nginx-proxy
|
|
func (nm *NginxManager) Status(ctx context.Context) (string, error) {
|
|
env := models.Environment{
|
|
Name: "nginx-proxy",
|
|
Path: nm.config.Path,
|
|
ComposeFile: "docker-compose.yml",
|
|
Enabled: true,
|
|
}
|
|
|
|
return nm.composeManager.PS(ctx, env)
|
|
}
|
|
|
|
// generateComposeFile generates the docker-compose.yml content for nginx-proxy
|
|
func (nm *NginxManager) generateComposeFile() string {
|
|
content := fmt.Sprintf(`version: '3.8'
|
|
|
|
services:
|
|
nginx-proxy:
|
|
image: %s
|
|
container_name: %s
|
|
restart: unless-stopped
|
|
ports:
|
|
- "%d:80"`, nginxProxyImage, nm.config.ContainerName, nm.config.HTTPPort)
|
|
|
|
if nm.config.SSLEnabled {
|
|
content += fmt.Sprintf(`
|
|
- "%d:443"`, nm.config.HTTPSPort)
|
|
}
|
|
|
|
content += `
|
|
volumes:
|
|
- /var/run/docker.sock:/tmp/docker.sock:ro`
|
|
|
|
if nm.config.SSLEnabled {
|
|
content += `
|
|
- certs:/etc/nginx/certs:ro
|
|
- vhost:/etc/nginx/vhost.d
|
|
- html:/usr/share/nginx/html`
|
|
}
|
|
|
|
content += `
|
|
environment:
|
|
- DEFAULT_HOST=localhost
|
|
networks:
|
|
- ` + nm.config.NetworkName
|
|
|
|
content += `
|
|
labels:
|
|
- "buque.managed=true"
|
|
- "buque.service=nginx-proxy"`
|
|
|
|
if nm.config.SSLEnabled {
|
|
content += fmt.Sprintf(`
|
|
|
|
acme-companion:
|
|
image: %s
|
|
container_name: nginx-proxy-acme
|
|
restart: unless-stopped
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
- certs:/etc/nginx/certs
|
|
- vhost:/etc/nginx/vhost.d
|
|
- html:/usr/share/nginx/html
|
|
- acme:/etc/acme.sh
|
|
environment:
|
|
- DEFAULT_EMAIL=admin@localhost
|
|
- NGINX_PROXY_CONTAINER=%s
|
|
networks:
|
|
- %s
|
|
depends_on:
|
|
- nginx-proxy
|
|
labels:
|
|
- "buque.managed=true"
|
|
- "buque.service=nginx-proxy-acme"`, nginxProxyCompanionImage, nm.config.ContainerName, nm.config.NetworkName)
|
|
}
|
|
|
|
content += `
|
|
|
|
networks:
|
|
` + nm.config.NetworkName + `:
|
|
external: true`
|
|
|
|
if nm.config.SSLEnabled {
|
|
content += `
|
|
|
|
volumes:
|
|
certs:
|
|
vhost:
|
|
html:
|
|
acme:`
|
|
}
|
|
|
|
return content
|
|
}
|
|
|
|
// GenerateServiceLabels generates labels for a service to work with nginx-proxy
|
|
func (nm *NginxManager) GenerateServiceLabels(virtualHost string, virtualPort int, letsencryptHost string, letsencryptEmail string) map[string]string {
|
|
labels := map[string]string{
|
|
"VIRTUAL_HOST": virtualHost,
|
|
}
|
|
|
|
if virtualPort > 0 {
|
|
labels["VIRTUAL_PORT"] = fmt.Sprintf("%d", virtualPort)
|
|
}
|
|
|
|
if nm.config.SSLEnabled && letsencryptHost != "" {
|
|
labels["LETSENCRYPT_HOST"] = letsencryptHost
|
|
if letsencryptEmail != "" {
|
|
labels["LETSENCRYPT_EMAIL"] = letsencryptEmail
|
|
}
|
|
}
|
|
|
|
return labels
|
|
}
|
|
|
|
// GetExampleServiceCompose returns an example docker-compose.yml for a service behind nginx-proxy
|
|
func (nm *NginxManager) GetExampleServiceCompose(serviceName, virtualHost string) string {
|
|
return fmt.Sprintf(`version: '3.8'
|
|
|
|
services:
|
|
%s:
|
|
image: your-image:latest
|
|
container_name: %s
|
|
restart: unless-stopped
|
|
expose:
|
|
- "80"
|
|
environment:
|
|
- VIRTUAL_HOST=%s
|
|
- VIRTUAL_PORT=80
|
|
- LETSENCRYPT_HOST=%s
|
|
- LETSENCRYPT_EMAIL=admin@%s
|
|
networks:
|
|
- %s
|
|
labels:
|
|
- "buque.environment=%s"
|
|
- "buque.managed=true"
|
|
|
|
networks:
|
|
%s:
|
|
external: true
|
|
`, serviceName, serviceName, virtualHost, virtualHost, virtualHost, nm.config.NetworkName, serviceName, nm.config.NetworkName)
|
|
}
|