{"id":37132454,"url":"https://github.com/pavius/crane","last_synced_at":"2026-01-14T15:27:19.795Z","repository":{"id":57589059,"uuid":"55436802","full_name":"pavius/crane","owner":"pavius","description":"Crane - Lift containers with ease","archived":false,"fork":true,"pushed_at":"2016-04-01T08:20:16.000Z","size":1594,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-06-20T14:21:55.493Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"michaelsauter/crane","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pavius.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-04-04T18:55:53.000Z","updated_at":"2016-04-04T18:55:54.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pavius/crane","commit_stats":null,"previous_names":[],"tags_count":42,"template":false,"template_full_name":null,"purl":"pkg:github/pavius/crane","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavius%2Fcrane","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavius%2Fcrane/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavius%2Fcrane/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavius%2Fcrane/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pavius","download_url":"https://codeload.github.com/pavius/crane/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavius%2Fcrane/sbom","scorecard":{"id":724050,"data":{"date":"2025-08-11","repo":{"name":"github.com/pavius/crane","commit":"77a7ca7537c052b5b1ee6e481a1a2c3e55d2807c"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-22T12:13:51.073Z","repository_id":57589059,"created_at":"2025-08-22T12:13:51.073Z","updated_at":"2025-08-22T12:13:51.073Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28424374,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T13:30:50.153Z","status":"ssl_error","status_checked_at":"2026-01-14T13:29:08.907Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-14T15:27:19.170Z","updated_at":"2026-01-14T15:27:19.781Z","avatar_url":"https://github.com/pavius.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Crane\nLift containers with ease\n\n\n## Overview\nCrane is a tool to orchestrate Docker containers. It works by reading in some\nconfiguration (JSON or YAML) which describes how to obtain images and how to run\ncontainers. Crane is ideally suited for setting up a development environment or\ncontinuous integration.\n\n* [Installation](#installation)\n* [Usage](#usage)\n* [Configuration](#configuration)\n* [Example](#example)\n* [Advanced Usage](#advanced-usage)\n  * [Groups and Targeting](#groups-and-targeting)\n  * [Extending the target](#extending-the-target)\n  * [Excluding containers](#excluding-containers)\n  * [Ad hoc commands](#ad-hoc-commands)\n  * [Networking](#networking)\n  * [Volumes](#volumes)\n  * [Hooks](#hooks)\n  * [Parallism](#parallism)\n  * [Container Prefixes](#container-prefixes)\n  * [Override image tag](#override-image-tag)\n  * [Generate command](#generate-command)\n  * [YAML advanced usage](#yaml-advanced-usage)\n\n\n## Installation\nThe latest release (2.7.0) can be installed via:\n\n```\nbash -c \"`curl -sL https://raw.githubusercontent.com/michaelsauter/crane/v2.7.0/download.sh`\" \u0026\u0026 sudo mv crane /usr/local/bin/crane\n```\n\nOlder releases can be found on the\n[releases](https://github.com/michaelsauter/crane/releases) page. You can also\nbuild Crane yourself by using the standard Go toolchain.\n\nPlease have a look at the\n[changelog](https://github.com/michaelsauter/crane/blob/v2.7.0/CHANGELOG.md)\nwhen upgrading.\n\nOf course, you will need to have Docker (\u003e= 1.6) installed.\n\n\n## Usage\nCrane is a very light wrapper around the Docker CLI. This means that most\ncommands just call the corresponding Docker command, but for all targeted\ncontainers. The basic format is `crane \u003ccommand\u003e \u003ctarget\u003e`, where `\u003ccommand\u003e`\ncorresponds to a Docker command, and `\u003ctarget\u003e` either is a single container or\na [group](#groups-and-targeting).\n\nWhen executing commands, keep the following 2 rules in mind:\n\n1. Crane will apply the command ONLY to the target\n2. Crane will do with other containers in the configuration whatever it takes in\norder for (1) to succeed\n\nAs an example, imagine you have a container `web` depending on container\n`database`. When you execute `crane run web`, then Crane will start `database`\nfirst, then run `web` (recreating `web` if it already exists). There are ways to\n[dynamically extend the target](#extending-the-target) (so that `database` would\nbe recreated as well for example).\n\nFollowing are a list of supported commands and possible options:\n\n| Command | Maps to | Explanation and Options |\n| ------------- | ----------- | ---------|\n| create      | create           | Creates containers. Any existing containers are removed first. |\n| run         | run              | Runs containers. Any existing containers are removed first. |\n| rm          | rm               | Removes containers if they exist. Use `--force` to kill running containers first. |\n| start       | start            | Starts containers if not they are not running yet. Non-existing containers are created first. |\n| stop        | stop             | Stops containers if they are running. |\n| kill        | kill             | Kills containers if they are running. |\n| pause       | pause            |  |\n| unpause     | unpause          |  |\n| exec        | exec             | Starts container first if not running yet. |\n| logs        | logs             | Logs of containers are multiplexed. Use `--follow` to follow log output. |\n| stats       | stats            | |\n| push        | push             | |\n| pull        | pull             | |\n| provision   | pull/build       | Calls Docker's `pull` if no Dockerfile is specified. Otherwise it builds the image, optionally with disabled cache by passing `--no-cache`. |\n| lift        | pull/build + run | Provisions and runs containers in one go. Use `--no-cache` to disable build cache. |\n| status      | -                | Displays information similar to `docker ps` for the given target. |\n| generate    | -                | Passes the targeted portion of the config through given `--template` and outputs the result to STDOUT or given `--output` file. |\n\nYou can get more information about what's happening behind the scenes for all commands by using `--verbose`. Most options have a short version as well, e.g. `lift -n`. The CLI provides help for every command, e.g. `crane help run`.\n\n\n## Configuration\nThe configuration defines a map of containers in either JSON or YAML. By default, the configuration is expected in a file named `crane.json` or `crane.yaml`/`crane.yml`. The file can also be set via `--config` or `CRANE_CONFIG`. If the given path is relative, Crane searches for the configuration in the current directory, then recursively in the parent directory. Dependencies between containers are automatically detected and resolved.\nThe map of containers consists of the name of the container mapped to the container configuration, with the following keys:\n\n* `image` (string, required): Name of the image to build/pull\n* `requires` (array) Container dependencies (experimental)\n* `run` (object, optional): Parameters mapped to Docker's `run` \u0026 `create`.\n\t* `add-host` (array) Add custom host-to-IP mappings.\n\t* `blkio-weight` (integer) Need Docker \u003e= 1.7\n\t* `blkio-weight-device` (array) Need Docker \u003e= 1.10\n\t* `cap-add` (array) Add Linux capabilities.\n\t* `cap-drop` (array) Drop Linux capabilities.\n\t* `cgroup-parent` (string)\n\t* `cidfile` (string)\n\t* `cpu-period` (integer) Need Docker \u003e= 1.7\n\t* `cpu-quota` (integer) Need Docker \u003e= 1.7\n\t* `cpuset` (integer)\n\t* `cpu-shares` (integer)\n\t* `detach` (boolean) `sudo docker attach \u003ccontainer name\u003e` will work as normal.\n\t* `detach-keys` (string) Need Docker \u003e= 1.10\n\t* `device` (array) Add host devices.\n\t* `device-read-bps` (array) Need Docker \u003e= 1.10\n\t* `device-read-iops` (array) Need Docker \u003e= 1.10\n\t* `device-write-bp` (array) Need Docker \u003e= 1.10\n\t* `device-write-iops` (array) Need Docker \u003e= 1.10\n\t* `dns` (array)\n\t* `dns-opt` (array) Need Docker \u003e= 1.9\n\t* `dns-search` (array)\n\t* `entrypoint` (string)\n\t* `env` (array/mapping) Can be declared as a string array with `\"key[=value]\"` items or a string-to-string mapping where each `key: value` will be translated to the corresponding `\"key=value\"` string.\n\t* `env-file` (array)\n\t* `expose` (array) Ports to expose to linked containers.\n\t* `group-add` (array) Need Docker \u003e= 1.8\n\t* `hostname` (string)\n\t* `interactive` (boolean)\n\t* `ip` (string) ip address. Need Docker \u003e= 1.10\n\t* `ip6` (string) ipv6 address. Need Docker \u003e= 1.10\n\t* `ipc` (string) The `container:id` syntax is not supported, use `container:name` if you want to reuse another container IPC.\n\t* `isolation` (string) Need Docker \u003e= 1.10\n\t* `kernel-memory` (string) Need Docker \u003e= 1.9\n\t* `label` (array/mapping) Can be declared as a string array with `\"key[=value]\"` items or a string-to-string mapping where each `key: value` will be translated to the corresponding `\"key=value\"` string.\n\t* `label-file` (array)\n\t* `link` (array) Link containers.\n\t* `log-driver` (string)\n\t* `log-opt` (array) Need Docker \u003e= 1.7\n\t* `lxc-conf` (array)\n\t* `mac-address` (string)\n\t* `memory` (string)\n\t* `memory-reservation` (string) Need Docker \u003e= 1.9\n\t* `memory-swap` (string)\n\t* `memory-swappiness` (int) Need Docker \u003e= 1.8\n\t* `net` (string) The `container:id` syntax is not supported, use `container:name` if you want to reuse another container network stack.\n\t* `net-alias` (array) Need Docker \u003e= 1.10\n\t* `oom-kill-disable` (bool) Need Docker \u003e= 1.7\n\t* `oom-score-adj` (string) Need Docker \u003e= 1.10\n\t* `pid` (string)\n\t* `privileged` (boolean)\n\t* `publish` (array) Map network ports to the container.\n\t* `publish-all` (boolean)\n\t* `read-only` (boolean)\n\t* `restart` (string) Restart policy.\n\t* `security-opt` (array)\n\t* `shm-size` (string) Need Docker \u003e= 1.10\n\t* `stop-signal` (string)  Need Docker \u003e= 1.9\n\t* `sig-proxy` (boolean) `true` by default\n\t* `rm` (boolean)\n\t* `tmpfs` (array) Need Docker \u003e= 1.10\n\t* `tty` (boolean)\n\t* `ulimit` (array)\n\t* `user` (string)\n\t* `uts` (string) Need Docker \u003e= 1.7\n\t* `volume` (array) In contrast to plain Docker, the host path can be relative.\n\t* `volume-driver` (string) Need Docker \u003e= 1.10\n\t* `volumes-from` (array) Mount volumes from other containers\n\t* `workdir` (string)\n\t* `cmd` (array/string) Command to append to `docker run` (overwriting `CMD`).\n* `rm` (object, optional): Parameters mapped to Docker's `rm`.\n\t* `volumes` (boolean)\n* `start` (object, optional): Parameters mapped to Docker's `start`.\n\t* `attach` (boolean)\n\t* `detach-keys` (string) Need Docker \u003e= 1.10\n\t* `interactive` (boolean)\n* `build` (object, optional): Parameters mapped to Docker's `build`.\n\t* `context` (string)\n\t* `file` (string)\n  * `build-arg` (array/mapping) Provide build arguments. Need Docker \u003e= 1.9\n* `exec` (object, optional): Parameters mapped to Docker's `exec`.\n\t* `detach` (boolean)\n\t* `detach-keys` (string) Need Docker \u003e= 1.10\n\t* `interactive` (boolean)\n\t* `privileged` (boolean) Need Docker \u003e= 1.9\n\t* `tty` (boolean)\n\t* `user` (string) Need Docker \u003e= 1.7\n\nNote that basic environment variable expansion (`${FOO}`, `$FOO`) is supported throughout the configuration, but advanced shell features such as command substitution (`$(cat foo)`, `` `cat foo` ``) or advanced expansions (`sp{el,il,al}l`, `foo*`, `~/project`, `$((A * B))`, `${PARAMETER#PATTERN}`) are *not* as the Docker CLI is called directly. Use `$$` for escaping a raw `$`.\n\nSee the [Docker documentation](http://docs.docker.com/reference/commandline/cli/) for more details about the parameters.\n\n\n## Example\nTaken from a basic\n[Sinatra blog app](https://github.com/michaelsauter/sinatra-crane-env), a\ntypical `crane.yaml` looks like this:\n\n```\ncontainers:\n  blog:\n    build:\n      context: image\n    image: michaelsauter/sinatra-example\n    run:\n      publish: [\"9292:9292\"]\n      volume: [\"blog:/blog\"]\n      link: [\"postgres:db\"]\n      env:\n        - \"POSTGRESQL_DB=default\"\n        - \"POSTGRESQL_USER=default\"\n        - \"POSTGRESQL_PASS=default\"\n      tty: true\n      interactive: true\n      cmd: \"start-blog\"\n  postgres:\n    image: d11wtq/postgres\n    run:\n      detach: true\n```\n\nThe specified Docker containers can then be created and started in the correct\norder with:\n\n```\ncrane lift blog\n```\n\nIf you want to use JSON instead of YAML, here's what a simple configuration\nlooks like:\n\n```\n{\n\t\"containers\": {\n\t\t\"pry\": {\n\t\t\t\"image\": \"d11wtq/ruby\",\n\t\t\t\"run\": {\n\t\t\t\t\"interactive\": true,\n\t\t\t\t\"tty\": true,\n\t\t\t\t\"cmd\": \"pry\"\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n\n## Advanced Usage\n\n### Groups and Targeting\n\nNext to containers, you can also specify groups, and then execute Crane commands\nagainst those groups. If you do not specify any target, the command will apply\nto all containers. However, you can override this by specifying a `default`\ngroup. Also, every container can be targeted individually by using the name of\nthe container. Groups of containers can be specified like this (YAML shown):\n\n```\ncontainers:\n  database1:\n    ../..\n  database2:\n    ../..\n  service1:\n    ../..\n  service2:\n    ../..\ngroups:\n  default: [\"service1\", \"database1\"]\n  databases: [\"database1\", \"database2\"]\n  services: [\"service1\", \"service2\"]\n\n```\n\nThis could be used like so: `crane provision service1`, `crane run databases`\nor `crane lift services`. `crane status` is an alias for `crane status default`\nin this example. If `default` were not specified, then `crane lift` would start\n`database1`, `database2`, `service1` and `service2`.\n\n\n### Extending the target\n\nIt is also possible to extend the target to related containers. There are 2\ndifferent \"dynamic\" groups, `affected` and `dependencies` (both have a short\nversion `a` and `d`). In our example configuration above, when targeting the\n`postgres` container, if it had been started earlier, the `blog` container\nwould be considered to be \"affected\". When targeting the `blog` container,\nthe `postgres` container would be considered as a \"dependency\". Therefore\n`crane run postgres+affected` will recreate both `postgres` and `blog`.\nSimilarly, `crane run blog+dependencies` will recreate `blog` and `postgres`.\nIt is possible to combine `affected` and `dependencies`.\n\n\n### Excluding containers\n\nIf you want to exclude a container or a whole group from a Crane command, you\ncan specify this with `--exclude \u003creference\u003e` (or via `CRANE_EXCLUDE`). The\nflag can be repeated to exclude several containers or groups (use a multi-line\nenvironment variable value to pass several references via `CRANE_EXCLUDE`).\n\nExcluded containers' declaration _and_ references in the configuration file\nwill be completely ignored, so their dependencies will also be excluded\n(unless they are also required by other non-excluded containers).\n\nThis feature is experimental, which means it can be changed or even removed\nin every minor version update.\n\n\n### Ad hoc commands\nIf you pass a command on the CLI to `lift` or `run`, Crane will add a timestamp\nto the container name (e.g. `foo` will become `foo-1447155694523`), making it\npossible to have multiple containers based on the same Crane config. Those ad\nhoc containers will have `ip`, `ip6`, `publish`, `publish-all` and `detach`\ndisabled, and `rm` enabled. This feature is experimental, which means it can be\nchanged or even removed in every minor version update.\n\n\n### Networking\nDocker networks are supported via the top-level config `networks`, which does not take additional parameters at this stage. As links are not strict dependencies for containers attached to a user-defined network (but simply aliases), `requires` can be used instead to indicate that a container must be started for another one to be functional. Networks are automatically created by Crane when necessary, and never cleaned up. When a [prefix](#container-prefixes) is used, it is also applied to the network.\n\n```\ncontainers:\n  foo:\n    requires: [\"bar\"]\n    run:\n      net: qux\n  bar:\n    run:\n      net: qux\nnetworks:\n  qux:\n```\n\nThis feature is experimental, which means it can be changed or even removed in\nevery minor version update.\n\n\n### Volumes\nDocker volumes are supported via the top-level config `volumes`, which does not\ntake additional parameters at this stage. Volumes are automatically created by\nCrane when necessary, and never cleaned up. When a [prefix](#container-prefixes)\nis used, it is also applied to the volume.\n\n```\ncontainers:\n  foo:\n    run:\n      volume: [\"bar:/path\"]\nvolumes:\n  bar:\n```\n\nThis feature is experimental, which means it can be changed or even removed in\nevery minor version update.\n\n\n### Hooks\n\nIn order to run certain commands before or after key lifecycle events of containers, hooks can be declared in the configuration. They are run synchronously on the host where Crane is installed, outside containers, via an `exec` call. They may interrupt the flow by returning a non-zero status. If shell features more advanced than basic variable expansion is required, you should explicitly spawn a shell to run the command in (`sh -c 'ls *'`).\n\nHooks are declared at the top level of the configuration, under the `hooks` key. See YAML example below:\n\n```\ncontainers:\n  service1:\n    image: busybox\n    run:\n      detach: true\n      cmd: [\"sleep\", \"50\"]\n  service2:\n    image: busybox\n    run:\n      detach: true\n      cmd: [\"sleep\", \"50\"]\n  service3:\n    image: busybox\n    run:\n      detach: true\n      cmd: [\"sleep\", \"50\"]\ngroups:\n  foo:\n    - service1\n    - service2\n  bar:\n    - service2\n    - service3\nhooks:\n  foo:\n    post-start: echo container from foo started\n  bar:\n    post-stop: echo container from bar stopped\n  service3:\n    post-stop: echo container service3 stopped\n```\n\nHooks can be defined on a group level (`foo`, `bar`) so that they apply to all containers within that group, or directly on a container (`service3`). At most one hook can be registered per container and per event. When more than one hook is found for a given container and a given event, the following rules apply:\n\n* Container-defined hooks have priority over group-defined ones, so in the example above, only \"container service3 stopped\" will be echoed when stopping `service3`.\n* A fatal error will be raised at startup when 2 group-inherited hooks conflict. This is not the case in the previous example; even though `foo` and `bar` both contain `service2`, the hooks they declare are disjoint.\n\nThe following hooks are currently available:\n* `pre-build`: Executed before building an image\n* `post-build`: Executed after building an image\n* `pre-start`: Executed before starting or running a container\n* `post-start`: Executed after starting or running a container\n* `pre-stop`: Executed before stopping, killing or removing a running container\n* `post-stop`: Executed after stopping, killing or removing a running container\n\nEvery hook will have the name of the container for which this hook runs available as the environment variable `CRANE_HOOKED_CONTAINER`.\n\n\n### Parallism\nBy default, Crane executes all commands sequentially. However, you might want\nto increase the level of parallelism for network-heavy operations, in order to\ncut down the overall run time. The `--parallel`/`-l` flag allows you to\nspecify the level of parallelism for commands where network can be a\nbottleneck (namely `provision` and `lift`). Passing a value of 0 effectively\ndisable throttling, which means that all provisioning will be done in parallel.\n\n\n### Container Prefixes\nIt is possible to prefix containers with a global `--prefix` flag, which is just\nprepended to the container name. Remember that you will have to provide the same\nprefix for subsequent calls if you want to address the same set of containers. A\ncommon use case for this feature is to launch a set of containers\nin parallel, e.g. for CI builds. Container prefixes can also be supplied by the\n`CRANE_PREFIX` environment variable.\n\n\n### Override image tag\nBy using a the `--tag` flag, it is possible to globally overrides image tags. If\nyou specify `--tag 2.0-rc2`, an image name `repo/app:1.0` is treated as\n`repo/app:2.0-rc2`. The `CRANE_TAG` environment variable can also be used to\nset the global tag.\n\n\n### Generate command\nThe `generate` command can transform (part of) the configuration based on a\ngiven template, making it easy to re-use the configuation with other tools.\n`--template` is a required flag, which should point to a Go template. By\ndefault, the output is printed to STDOUT. It can also be written to a file using\nthe `--output` flag. If the given filename contains `%s`, then multiple files\nare written (one per container), substituting `%s` with the name of the\ncontainer. For each container, an object of type\n[ContainerInfo](https://godoc.org/github.com/michaelsauter/crane/crane#ContainerInfo)\nis passed to the template. If one file is generated for all targeted containers,\na list of containers is located under the key `Containers`.  This feature is\nexperimental, which means it can be changed or even removed in every minor\nversion update.\n\nExample templates can be found at\n[crane-templates](https://github.com/michaelsauter/crane-templates).\n\n\n### YAML advanced usage\nYAML gives you some advanced features like [alias](http://www.yaml.org/spec/1.2/spec.html#id2786196) and [merge](http://yaml.org/type/merge.html). They allow you to easily avoid duplicated code in your `crane.yml` file. As a example, imagine you need to define 2 different containers: `web` and `admin`. They share almost the same configuration but the `cmd` declaration. And imagine you also need 2 instances for each one for using with a node balancer. Then you can declare them as simply:\n\n```\ncontainers:\n  web1: \u0026web\n    image: my-web-app\n    run: \u0026web-run\n      link: [\"db:db\"]\n      ...\n      cmd: web\n  web2: *web\n\n  admin1: \u0026admin { \u003c\u003c: *web, run: { \u003c\u003c: *web-run , cmd: admin }}\n  admin2: *admin\n```\n\nAs a summary, `\u0026anchor` declares the anchor property, `*alias` is the alias indicator to simply copy the mapping it references, and `\u003c\u003c: *merge` includes all the mapping but let you override some keys.\n\n\n## Copyright \u0026 Licensing\nCopyright © 2013-2016 Michael Sauter. See the LICENSE file for details.\n\n---\n\n[![GoDoc](https://godoc.org/github.com/michaelsauter/crane?status.png)](https://godoc.org/github.com/michaelsauter/crane)\n[![Build Status](https://travis-ci.org/michaelsauter/crane.svg?branch=master)](https://travis-ci.org/michaelsauter/crane)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpavius%2Fcrane","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpavius%2Fcrane","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpavius%2Fcrane/lists"}