Yann Autissier ed3c5a0c7c add the engine benchmark: make, sh, just and a Go prototype
Same work on each, median of five. The numbers separate three costs that the
earlier measurements mixed up: the engine itself (go 23 ms flat, sh 177 ms
plus 63 per stack, just 204 plus 32, make 792 plus 700), the shell hooks
(about 40 ms per computed setting whatever the engine, since Go runs the same
sh), and bin/myos loading a directory's hooks once per stack reference rather
than once per directory, which doubles the hook cost for a group.

Memoising the lazy defaults changes nothing: the cost is the command
substitutions inside each tag helper, not repeated lookups.
2026-09-05 15:07:53 +02:00
2025-12-18 00:47:53 +01:00
wip
2021-07-14 20:38:30 +01:00

myos - Make Your Own Stack

myos runs docker compose stacks: on a server, in a project directory, for a user. It is a thin layer over docker compose that resolves which compose files to load, under which project name, with which environment variables.

The framework itself ships no stack. Ready-to-use stacks (consul, fabio, registrator, postgres, supabase, drone, …) live in a separate catalogue, myos-stacks.

Disclaimer

This is beta software, use it at your own risks.

Requirements

docker (with the docker compose plugin >= 2.24.4, or a docker-compose binary), git and make.

Install

As a command

sudo git clone https://github.com/aya/myos /usr/local/lib/myos
sudo ln -s /usr/local/lib/myos/myos /usr/local/bin/myos

Optionally pin per-machine settings in /etc/conf.d/myos (or /etc/default/myos), one VAR=value per line, no comments:

DOMAIN=example.org
ENV=master

myos runs from the current directory: it passes it as WORKDIR, so stacks and .env are looked up there. A WORKDIR set in the config file wins over the current directory, which pins a machine to its deployment directory.

As a make include

Add to your project Makefile:

MYOS ?= /usr/local/lib/myos
-include $(MYOS)/make/include.mk

Then make help lists the available targets.

Stack catalogue

myos looks for stacks in ./stack, ../stack, ~/.local/share/myos/stack, /usr/local/share/myos/stack and /usr/share/myos/stack:

sudo git clone https://github.com/aya/myos-stacks /usr/local/share/myos

Usage

myos doctor                      # check the installation first
myos ls                          # what stacks are reachable
myos -n up host                  # print what it would run
myos up                          # the stack of the current directory
myos up STACK=host               # a group of stacks, see stack/host/host.mk
myos up STACK=host/fabio         # a single stack
myos up STACK=postgres:9.6       # a versioned stack
myos ps
myos logs
myos config                      # rendered compose file
myos down
myos shutdown                    # every stack: app, host and user

How a stack is resolved

A stack is a directory of compose files. For STACK=<name> in environment ENV, myos loads, in order, whichever of these exist:

<name>.yml   <name>.<ENV>.yml   <ENV>/<name>.yml
<name>.<suffix>.yml   <name>.<suffix>.<ENV>.yml   <name>.<version>.yml

<suffix> comes from the COMPOSE_FILE_* variables that are not false (app, labels, networks, ssh, volumes by default; add e.g. COMPOSE_FILE_WWW=true to also load <name>.www.yml). The framework always appends its own share/compose/networks.yml.

Project names and networks

stack compose project meaning
host/* $(HOSTNAME) one instance per machine: ports 80/443, consul, certbot
User/* user identity one instance per user
anything else <user>-<app>-<env> many instances per machine

Networks: default = _<project> (private to the project), private = <user>-<env> and public = <hostname>, both external and created on demand.

Variables

variable effect
DEBUG=true show executed commands
DRYRUN=true print commands instead of running them
VERBOSE=true show called functions
ENV=<env> environment: selects .env.<env> and the <name>.<env>.yml overlays
STACK=<refs> stacks to act on
SERVICE=<name> target one compose service (exec, run, logs, scale)
MYOS_PROJECT_FORMAT user-env-app (default) or user-app-env for deployments made before myos 2.0
myos env COMPOSE_FILE             # show a variable
myos env COMPOSE_PROJECT_NAME
myos config <stack>               # the rendered compose file

The make targets keep working: print-VAR, stack-<stack>-<command>, <command>@<env>, and a project Makefile that includes make/include.mk.

SETUP_UFW=true enables the ufw/ufw-docker integration (myos setup-ufw).

With make

A project that would rather drive make can include the shim, which turns every myos command into a make target while leaving its own targets alone:

MYOS ?= /usr/local/lib/myos
include $(MYOS)/share/make/shim.mk

make up STACK=host then runs exactly what myos up host runs: the shim only forwards. make is not needed otherwise, and the CLI never calls it.

For agents

skills/myos/SKILL.md is a skill describing how to drive myos, with references on the conventions, the commands and the failure modes. AGENTS.md covers changing myos itself.

Tests

make test           # shellspec: unit + golden (a mocked docker, no daemon needed)
make test-golden    # golden only
make golden-record  # re-record the golden expectations
make lint           # shellcheck

License

GPL-3.0, see LICENSE.

S
Description
common make targets to build and run docker projects
Readme AGPL-3.0
1.2 MiB
Languages
Makefile 85.6%
Shell 10.5%
Dockerfile 3.9%