compose-exec

module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jan 10, 2026 License: MIT

README

compose-exec

Go Reference

Japanese README (日本語ドキュメント)

The Missing Link for Secure, Portable DevOps in Go.

compose-exec is a dependency-free Go library for executing commands inside Docker Compose services. It provides an interface identical to os/exec and implements the Sibling Container Pattern in the most secure and robust way possible.

⚡ Why compose-exec?

The traditional approach of installing the Docker CLI inside a container is broken in terms of security and portability. This library is the logical answer to modern DevOps challenges.

1. Zero-Trust & Distroless Ready

Minimizes the attack surface to the absolute limit.

  • No Docker CLI Required: No need to install docker binaries or Python-based Compose inside your container.
  • No Shell Required: Does not require /bin/sh.
  • This enables usage with Distroless (static) or scratch images. Orchestrate containers from an environment with zero tools available to an attacker.
2. Pipeline as Code (No More YAML Hell)

Liberate your CI/CD logic from vendor-specific YAML (GitHub Actions, GitLab CI).

  • Portable Logic: Define build, test, and deploy steps as Go code.
  • Reproducibility: Eliminates "Works on my machine, fails on CI". As long as you have Go and Docker, your pipeline runs exactly the same way on a MacBook as it does on a CI Runner.
3. Native Go Experience
  • Zero Learning Curve: The API mirrors os/exec.
  • Robustness: Automatically handles signal forwarding (SIGINT/SIGTERM), zombie process prevention (PID 1 issues), and exit code propagation.

🚀 Quick Start

Installation
go get [github.com/hnw/compose-exec](https://github.com/hnw/compose-exec)
Usage

The code feels exactly like os/exec.

package main

import (
	"context"
	"os"
	"[github.com/hnw/compose-exec/compose](https://github.com/hnw/compose-exec/compose)"
)

func main() {
	ctx := context.Background()

	// 1. Target a service defined in docker-compose.yml
	// Image pulling, container creation, and networking are handled automatically.
	cmd := compose.From("sibling-target").Command("ls", "-la", "/app")

	// 2. Connect pipes
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	// 3. Run
	// The container is automatically cleaned up after execution.
	if err := cmd.Run(ctx); err != nil {
		// Exit codes are correctly propagated
		panic(err)
	}
}

💡 Real-World Use Cases

The true value lies not just in running commands, but in "Infrastructure as Code" for tasks.

Scenario A: Self-Contained Integration Tests

Your test code manages the lifecycle of its required infrastructure (DB, Cache, etc.). No need to define services in your CI YAML.

func TestWithDatabase(t *testing.T) {
    // Launch DB on demand within the test
    // Portable across any CI environment
    dbCmd := compose.From("postgres").Command("docker-entrypoint.sh", "postgres")
    dbCmd.Start(context.Background())
    defer dbCmd.Wait() // Teardown on test completion

    // ... run tests ...
}
Scenario B: Portable CI/CD Runner

Write complex build flows (Frontend build -> Static Asset -> Go Embed) in Go and run them as a custom runner.

  • No need to install Node.js/npm on the developer's machine.
  • compose-exec spins up a Node.js container, builds the assets, and exits.

⚙️ Configuration

To use compose-exec from within a container (Sibling Container Pattern), your docker-compose.yml requires specific setup.

1. Mirror Mount (.:${PWD})

Docker Bind Mounts always reference host OS paths. To resolve relative paths correctly, you must mount the host's current directory to the exact same path inside the container.

2. Manual Profile

Use profiles to prevent the target (Sibling) container from starting automatically with docker compose up.

services:
  # 1. Controller (Your Go App / CI Runner)
  #    Can be a Distroless image
  controller:
    image: gcr.io/distroless/static-debian12:latest
    volumes:
      # Required: Access to Docker API
      - /var/run/docker.sock:/var/run/docker.sock
      # Required: Mirror Mount
      # Maps host's current dir to the SAME path inside the container
      - .:${PWD}
    working_dir: ${PWD}
    # Optional: Inject host UID/GID to avoid permission issues
    user: "${UID}:${GID}"
    command: ["/path/to/your-go-binary"]

  # 2. Target Sibling
  sibling-target:
    image: alpine:latest
    profiles:
      - manual # Only starts when called by compose-exec

⚠️ Requirements & Compatibility

  • Go: 1.22+
  • Docker Engine: API version 1.40+
  • OS: Linux, macOS (Docker Desktop), Windows (WSL2 recommended)
Note on Image Size

This library includes the Docker SDK, which increases binary size. However, because it removes the need to bundle the docker CLI binary (~50MB) and a base OS shell, the total container image size is significantly reduced.


License

MIT

Directories

Path Synopsis
Package compose provides a small API to execute commands in Compose services via Docker Engine.
Package compose provides a small API to execute commands in Compose services via Docker Engine.
Package main demonstrates executing a command in a Compose service.
Package main demonstrates executing a command in a Compose service.

Jump to

Keyboard shortcuts

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