### Start with Docker Compose Source: https://github.com/qdm12/deunhealth/blob/main/README.md Use this command to start the service using a docker-compose.yml file. ```sh docker-compose up -d ``` -------------------------------- ### Install Go dependencies Source: https://github.com/qdm12/deunhealth/blob/main/README.md Run this command to download the necessary Go modules for the project. ```sh go mod download ``` -------------------------------- ### Start Unhealthy Loop Monitoring Source: https://context7.com/qdm12/deunhealth/llms.txt Starts the container health monitoring loop. Returns a channel for run errors and an initial error if setup fails. ```go // Start begins monitoring for unhealthy containers func (l *Unhealthy) Start(ctx context.Context) (runError <-chan error, err error) { ready := make(chan struct{}) done := make(chan struct{}) runErrorCh := make(chan error) runCtx, cancel := context.WithCancel(context.Background()) l.cancel = cancel go l.run(runCtx, ready, done, runErrorCh) <-ready return runErrorCh, nil } ``` -------------------------------- ### Build DeUnhealth from Source Source: https://context7.com/qdm12/deunhealth/llms.txt Provides command-line instructions for building the DeUnhealth application from source using Go and Docker. Includes steps for cloning, dependency installation, binary building, testing, linting, and Docker image creation. ```bash # Clone the repository git clone https://github.com/qdm12/deunhealth.git cd deunhealth # Install dependencies go mod download # Build the binary go build -o deunhealth cmd/app/main.go # Run tests go test ./... # Run linter golangci-lint run # Build Docker image docker build -t qmcgaw/deunhealth . ``` -------------------------------- ### Docker Compose Configuration for DeUnhealth and Monitored Services Source: https://context7.com/qdm12/deunhealth/llms.txt Example Docker Compose file demonstrating how to set up DeUnhealth alongside other services, including health checks and labels for monitoring. ```yaml # docker-compose.yml - Complete setup with monitored services version: "3.7" services: # Deunhealth monitoring service deunhealth: image: qmcgaw/deunhealth container_name: deunhealth network_mode: "none" environment: - LOG_LEVEL=info - TZ=UTC restart: always volumes: - /var/run/docker.sock:/var/run/docker.sock # Web application with health monitoring webapp: image: nginx:alpine container_name: webapp labels: - deunhealth.restart.on.unhealthy=true healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost"] interval: 30s timeout: 10s retries: 3 start_period: 10s restart: unless-stopped # API service with health monitoring api: image: my-api:latest container_name: api labels: - deunhealth.restart.on.unhealthy=true healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 15s timeout: 5s retries: 3 environment: - DATABASE_URL=postgres://db:5432/myapp restart: unless-stopped # Database without restart-on-unhealthy (managed differently) db: image: postgres:15 container_name: db # No deunhealth label - will not be auto-restarted healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 volumes: - pgdata:/var/lib/postgresql/data restart: unless-stopped volumes: pgdata: ``` -------------------------------- ### Run DeUnhealth Container Source: https://github.com/qdm12/deunhealth/blob/main/README.md Use this command to start the DeUnhealth container with the necessary Docker socket volume mount and network isolation. ```sh docker run -d --network none -v /var/run/docker.sock:/var/run/docker.sock qmcgaw/deunhealth ``` -------------------------------- ### Development and build commands Source: https://github.com/qdm12/deunhealth/blob/main/README.md Common commands for building the binary, running tests, linting, and creating the Docker image. ```sh # Build the binary go build cmd/app/main.go # Test the code go test ./... # Lint the code golangci-lint run # Build the Docker image docker build -t qmcgaw/deunhealth . ``` -------------------------------- ### Create New Docker Client Source: https://context7.com/qdm12/deunhealth/llms.txt Initializes a new Docker client instance. Requires the Docker host address and negotiates the API version with the Docker daemon. ```go package docker import ( "context" "github.com/moby/moby/client" ) // Create a new Docker client func New(dockerHost string) (*Docker, error) { client, err := client.NewClientWithOpts( client.WithHost(dockerHost), client.WithAPIVersionNegotiation(), ) if err != nil { return nil, err } return &Docker{client: client}, nil } // Container represents a Docker container type Container struct { ID string Name string Image string } // Usage example func main() { ctx := context.Background() // Initialize Docker client docker, err := New("unix:///var/run/docker.sock") if err != nil { panic(err) } // Negotiate API version with Docker daemon docker.NegotiateVersion(ctx) // Get currently unhealthy containers with the monitoring label unhealthyContainers, err := docker.GetUnhealthy(ctx) if err != nil { panic(err) } // Restart each unhealthy container for _, container := range unhealthyContainers { err := docker.RestartContainer(ctx, container.ID) if err != nil { log.Printf("Failed to restart %s: %v", container.Name, err) } } } ``` -------------------------------- ### Build DeUnhealth with Version Information Source: https://context7.com/qdm12/deunhealth/llms.txt Build the DeUnhealth Docker image, embedding version, commit hash, and creation timestamp. ```bash docker build \ --build-arg VERSION=v1.0.0 \ --build-arg COMMIT=$(git rev-parse HEAD) \ --build-arg CREATED=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \ -t qmcgaw/deunhealth:v1.0.0 . ``` -------------------------------- ### Configure Container Labels for Monitoring Source: https://context7.com/qdm12/deunhealth/llms.txt Enable health monitoring for specific containers using labels and health check definitions. ```bash # Run a container with health monitoring enabled docker run -d \ --name my-app \ --label deunhealth.restart.on.unhealthy=true \ --health-cmd "curl -f http://localhost:8080/health || exit 1" \ --health-interval 30s \ --health-timeout 10s \ --health-retries 3 \ my-app-image ``` ```yaml # Add label to existing container in docker-compose # docker-compose.yml version: "3.7" services: webapp: image: nginx labels: - deunhealth.restart.on.unhealthy=true healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 30s timeout: 10s retries: 3 ``` -------------------------------- ### Run DeUnhealth with Docker Source: https://context7.com/qdm12/deunhealth/llms.txt Deploy the DeUnhealth container with minimal or custom configuration settings. ```bash # Run DeUnhealth with minimal configuration docker run -d \ --name deunhealth \ --network none \ -v /var/run/docker.sock:/var/run/docker.sock \ qmcgaw/deunhealth # Run with custom configuration docker run -d \ --name deunhealth \ --network none \ -e LOG_LEVEL=debug \ -e HEALTH_SERVER_ADDRESS=127.0.0.1:9999 \ -e TZ=Europe/London \ -v /var/run/docker.sock:/var/run/docker.sock \ qmcgaw/deunhealth ``` -------------------------------- ### Initialize Unhealthy Loop Service Source: https://context7.com/qdm12/deunhealth/llms.txt Creates a new instance of the Unhealthy loop service, requiring a Docker client and a logger. ```go package loop import ( "context" "github.com/qdm12/deunhealth/internal/docker" "github.com/qdm12/log" ) // Create the unhealthy monitoring loop func NewUnhealthyLoop(docker Docker, logger log.LeveledLogger) *Unhealthy { return &Unhealthy{ docker: docker, logger: logger, } } ``` -------------------------------- ### Create Health Check Server Source: https://context7.com/qdm12/deunhealth/llms.txt Sets up an internal HTTP server for the application's health checks. It uses a provided health check function to determine the application's status. ```go package health import ( "context" "net/http" ) // Create health check server func NewServer(address string, logger Logger, healthcheck func() error) (*Server, error) { handler := newHandler(healthcheck) return httpserver.New(httpserver.Settings{ Handler: handler, Name: ptrTo("health"), Address: ptrTo(address), Logger: logger, }) } // Health check client for querying the server func NewClient() *Client { return &Client{ Client: &http.Client{Timeout: 5 * time.Second}, } } // Query the health server func (c *Client) Query(ctx context.Context, address string) error { _, port, _ := net.SplitHostPort(address) req, _ := http.NewRequestWithContext(ctx, http.MethodGet, "http://127.0.0.1:"+port, nil) resp, err := c.Do(req) if err != nil { return fmt.Errorf("querying health server: %w", err) } if resp.StatusCode == http.StatusOK { return nil } return ErrUnhealthy } // Health endpoint responds to GET / requests // Returns 200 OK if healthy, 500 Internal Server Error if unhealthy ``` -------------------------------- ### Deploy and Monitor DeUnhealth Stack Source: https://context7.com/qdm12/deunhealth/llms.txt Commands to deploy the Docker Compose stack and monitor the DeUnhealth service logs for container restart events. ```bash # Deploy the stack docker-compose up -d # Monitor DeUnhealth logs docker logs -f deunhealth # Expected output when container becomes unhealthy: # INFO container /webapp (image nginx:alpine) is unhealthy, restarting it... # INFO container /webapp restarted successfully ``` -------------------------------- ### Check Health from Container Source: https://context7.com/qdm12/deunhealth/llms.txt Demonstrates how to check the DeUnhealth application's health status from within its Docker container using the `docker exec` command. ```bash # Check health from within the container docker exec deunhealth /app healthcheck # The container's built-in healthcheck runs automatically: # HEALTHCHECK --interval=10s --timeout=5s --start-period=5s --retries=2 # CMD ["/app","healthcheck"] ``` -------------------------------- ### Configure Docker Host Connection Source: https://context7.com/qdm12/deunhealth/llms.txt Specify the Docker host connection string using the DOCKER_HOST environment variable. ```bash # Connect to remote Docker host via TCP docker run -d \ --name deunhealth \ -e DOCKER_HOST=tcp://docker-proxy:2375 \ -e LOG_LEVEL=debug \ qmcgaw/deunhealth # Using Unix socket (default) docker run -d \ --name deunhealth \ -e DOCKER_HOST=unix:///var/run/docker.sock \ -v /var/run/docker.sock:/var/run/docker.sock \ qmcgaw/deunhealth ``` -------------------------------- ### Deploy DeUnhealth with Docker Compose Source: https://context7.com/qdm12/deunhealth/llms.txt Use Docker Compose for managing the DeUnhealth service and its lifecycle. ```yaml # docker-compose.yml version: "3.7" services: deunhealth: image: qmcgaw/deunhealth container_name: deunhealth network_mode: "none" environment: - LOG_LEVEL=info - HEALTH_SERVER_ADDRESS=127.0.0.1:9999 - TZ=America/Montreal restart: always volumes: - /var/run/docker.sock:/var/run/docker.sock ``` ```bash # Deploy using docker-compose docker-compose up -d # View logs docker-compose logs -f deunhealth ``` -------------------------------- ### Internal Restart Logic for Unhealthy Container Source: https://context7.com/qdm12/deunhealth/llms.txt Handles the logic for restarting a container identified as unhealthy. Logs the attempt and outcome. ```go // Internal restart logic func (l *Unhealthy) restartUnhealthy(ctx context.Context, unhealthy docker.Container) { l.logger.Info("container " + unhealthy.Name + " (image " + unhealthy.Image + ") is unhealthy, restarting it...") err := l.docker.RestartContainer(ctx, unhealthy.ID) if err != nil { l.logger.Error("failed restarting container: " + err.Error()) } else { l.logger.Info("container " + unhealthy.Name + " restarted successfully") } } ``` -------------------------------- ### Update DeUnhealth Image Source: https://github.com/qdm12/deunhealth/blob/main/README.md Use this command to pull the latest version of the DeUnhealth image. ```sh docker pull qmcgaw/deunhealth:latest ``` -------------------------------- ### Stop Unhealthy Loop Service Source: https://context7.com/qdm12/deunhealth/llms.txt Gracefully shuts down the monitoring loop by canceling the context and waiting for completion. ```go // Stop gracefully shuts down the monitoring loop func (l *Unhealthy) Stop() error { l.cancel() <-l.done return nil } ``` -------------------------------- ### Stream Unhealthy Container Events Source: https://context7.com/qdm12/deunhealth/llms.txt Monitors Docker events in real-time to detect unhealthy containers. It specifically targets containers with the label 'deunhealth.restart.on.unhealthy=true' and avoids polling overhead. ```go package main import ( "context" "fmt" "github.com/qdm12/deunhealth/internal/docker" ) func monitorUnhealthyContainers(ctx context.Context, d *docker.Docker) { ready := make(chan struct{}) unhealthies := make(chan docker.Container) crashed := make(chan error) // Start streaming unhealthy container events // Only monitors containers with label: deunhealth.restart.on.unhealthy=true go d.StreamUnhealthy(ctx, ready, unhealthies, crashed) // Wait for stream to be ready <-ready fmt.Println("Stream ready, monitoring for unhealthy containers...") for { select { case err := <-crashed: fmt.Printf("Stream crashed: %v\n", err) return case container := <-unhealthies: fmt.Printf("Container %s (image: %s) became unhealthy\n", container.Name, container.Image) // Restart the unhealthy container if err := d.RestartContainer(ctx, container.ID); err != nil { fmt.Printf("Failed to restart: %v\n", err) } else { fmt.Printf("Successfully restarted %s\n", container.Name) } case <-ctx.Done(): return } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.