compose-exec

module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Sep 22, 2026 License: MIT

README

compose-exec

Go Reference Japanese README

compose-exec lets Go programs run containerized tools like external commands.

Keep each tool in its own Compose service instead of bundling it into the application image, and invoke it through an os/exec-like API.

cmd := compose.CommandContext(ctx, "pandoc", "input.md", "-t", "html")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr

if err := cmd.Run(); err != nil {
	log.Fatal(err)
}

Tool-specific settings such as the image, volumes, environment variables, and networks stay in compose.yaml.

compose-exec talks to the Docker Engine directly instead of invoking docker compose.

flowchart LR
    Go["Go program"]
    CE["compose-exec"]
    CLI["docker compose"]
    Docker["Docker Engine"]
    Service["Compose service"]

    Go --> CE --> Docker --> Service
    CLI -.-> Docker

Example

This repository includes a runnable Pandoc example with two services:

  • controller runs the Go program using compose-exec
  • pandoc provides Pandoc in a separate container

Compose services do not have to be long-running processes started with docker compose up. They can also be used as definitions for short-lived containers, as with docker compose run.

compose-exec uses the same idea: when the Go program invokes pandoc, it creates a container from the pandoc service definition and runs the requested command.

Run the example with:

git clone https://github.com/hnw/compose-exec.git
cd compose-exec
docker compose run --rm controller

Example output:

[Controller] Converting Markdown to HTML...
[Controller] Running Pandoc via the "pandoc" Compose service.

Input: example/input.md

<h1 id="hello-pandoc">Hello, Pandoc</h1>
<p>This Markdown file is converted to HTML by the
<strong>pandoc</strong> Compose service.</p>
...

[Controller] Done. Pandoc ran in a separate container,
[Controller] so it is not installed in the controller image.

The pandoc service is defined in compose.yaml:

services:
  pandoc:
    image: pandoc/core:3.11.0.0
    volumes:
      - ./example:/data
    working_dir: /data

Pandoc and its dependencies stay out of the controller image, and its version can be changed independently by updating the image tag.

If Go is installed locally, the same example can also be run directly:

go run ./example

In that case, the Go program runs on the host and only Pandoc runs in a container.

Why compose-exec?

compose-exec is useful when a Go program needs to run one or more tools in containers while keeping their runtime setup in Compose.

Typical use cases include:

  • keeping tools and their dependencies in separate container images
  • updating tool versions independently from the application
  • using stdin, stdout, stderr, and context.Context through an os/exec-like API

This works especially well for bots, agents, CI helpers, and automation services that call several containerized tools.

Usage

package main

import (
	"context"
	"log"
	"os"

	"github.com/hnw/compose-exec/compose"
)

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

	cmd := compose.CommandContext(ctx, "pandoc", "input.md", "-t", "html")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	if err := cmd.Run(); err != nil {
		log.Fatal(err)
	}
}

Command() and CommandContext() load the Compose project from the current working directory.

For repeated commands, load the project once and reuse it:

project, err := compose.LoadProject(ctx, ".")
if err != nil {
	log.Fatal(err)
}

cmd := project.CommandContext(ctx, "tool", "--version")

Docker-outside-of-Docker

The Go program can itself run inside a container while using the host Docker daemon.

In this setup, the controller uses the mounted Docker socket to start sibling containers from the service definitions in compose.yaml.

Mount the Docker socket and keep the project at the same absolute path on the host and inside the controller:

services:
  controller:
    image: golang:1.25
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - .:${PWD}
    working_dir: ${PWD}
    environment:
      - PWD=${PWD}

Using the same path allows bind mounts in compose.yaml to refer to the correct host paths.

Compose support

compose-exec supports the Compose settings commonly needed to run containerized tools and supporting services.

Notable limitations:

  • build is not supported; services must specify image
  • compose-exec is not a full Docker Compose implementation

Supported service fields include:

  • image, platform
  • command, entrypoint, working_dir
  • environment, env_file
  • volumes, tmpfs, read_only
  • ports
  • networks, network_mode, extra_hosts
  • healthcheck
  • user, init
  • stop_signal, stop_grace_period
  • privileged, cap_add, cap_drop, security_opt
  • shm_size, devices
  • mem_limit, mem_reservation, memswap_limit
  • cpus, cpu_shares, cpuset
  • ulimits, labels

Other Compose fields are outside the supported scope.

Installation

go get github.com/hnw/compose-exec

Requirements

  • Go 1.24 or later
  • Docker Engine API v1.40 or later

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 treating a Docker Compose service as an external command: Pandoc runs in its own container, invoked from Go.
Package main demonstrates treating a Docker Compose service as an external command: Pandoc runs in its own container, invoked from Go.

Jump to

Keyboard shortcuts

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