{"id":24306541,"url":"https://github.com/exteon/docker-recipes","last_synced_at":"2026-05-05T01:33:54.021Z","repository":{"id":56980658,"uuid":"418605092","full_name":"exteon/docker-recipes","owner":"exteon","description":"A library to aggregate a multistage Dockerfile from multiple Dockerfiles and add reusable templates","archived":false,"fork":false,"pushed_at":"2022-08-15T21:51:47.000Z","size":44,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-17T03:20:43.235Z","etag":null,"topics":["docker","docker-compose","docker-compose-template","dockerfile","php"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/exteon.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":"2021-10-18T17:36:56.000Z","updated_at":"2023-09-26T14:53:58.000Z","dependencies_parsed_at":"2022-08-21T08:40:42.108Z","dependency_job_id":null,"html_url":"https://github.com/exteon/docker-recipes","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exteon%2Fdocker-recipes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exteon%2Fdocker-recipes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exteon%2Fdocker-recipes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exteon%2Fdocker-recipes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/exteon","download_url":"https://codeload.github.com/exteon/docker-recipes/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242257698,"owners_count":20098199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["docker","docker-compose","docker-compose-template","dockerfile","php"],"created_at":"2025-01-17T03:20:04.029Z","updated_at":"2026-05-05T01:33:53.969Z","avatar_url":"https://github.com/exteon.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# exteon/docker-recipes\n\nLibrary that allows merging `Dockerfile` and `docker-compose.yml` recipes, \nadding modularity and reusability to docker recipes\n\n## Concepts\n\n### Templates\n\nIn the context of `docker-recipes`, a template is a fragment of `Dockerfile`, \nusing the same syntax, that is used to piece together a final `Dockerfile`.\n\nA template can require multiple other templates.\n\n### Dockerfile\n\nWith `docker-recipes`, a source dockerfile is a regular `Dockerfile`, with added\nsyntax to include any number of templates.\n\n### `docker-compose.yml`\n\n`docker-recipes` provides a mechanism for merging multiple `docker-compose.yml`s\ninto a destination `docker-compose.yml`. At the same time, referenced templated\n`Dockerfile`s in `docker-compose.yml`s are managed to point to the generated \n`Dockerfile`s in the generated merged `docker-compose.yml`\n\n### AppEnv's\n\nMany times, an app has multiple build environments it can run in. For example, it can have a `live` environment, with \nminimal footprint, and a `dev` environment where a number of debugging tools are added to containers (such as xdebug).\n\nSince v3.0, `docker-recipes` provides a mechanism for specifying app-env's for Dockerfile templates as well as for \ndocker-compose files. Each Dockerfile and docker-compose file has one app-env associated with it, determined based on \nthe directory structure (for more details see [Locators](#locators)). \n\nWhen compiling Dockerfiles and docker-compose files, an app-env stack can be provided as an array:\n* Dockerfiles are then looked up using the order of the provided app-envs, (with index 0 having top priority).\n* docker-compose files are stacked and merged in the reverse order of the provided app-envs (with index 0 on top).\n\n## Dockerfile composition and syntax\n\nIn both `Dockerfile`s and templates, the syntax to require another template is:\n\n```\n#TEMPLATE[ template-name ]\n```\n\n-or-\n\n```\n#TEMPLATE[ app-env/template-name ]\n```\n\nThat is, a comment starting at the beginning of the line, with a single comment\nhash and followed, with no spaces, by `TEMPLATE[`. Between the square brackets,\nthe template name is provided, possibly preceded by the app-env and a slash. The \nmechanism of locating templates is described in [Locators](#locators).\n\nThe purpose of the library is, for every source `Dockerfile`, to generate a \ntarget `Dockerfile` with all templates compiled in.\n\nWhen a template is required multiple times, (presumably by multiple \ndifferent other templates), it will be deduplicated and included only once in \nthe compiled Dockerfile; the concept of functional (invokable/parameterisable) \ntemplates is not implemented but is considered for future versions.\n\nIn the `Dockerfile` templates/images, when you have for instance a `COPY`\ninstruction, you need the path to the template dir. For this, you need to use \nthe `$TEMPLATE_DIR` variable which will be compiled into the proper path, i.e.:\n\n```dockerfile\nCOPY $TEMPLATE_DIR/supervisord/supervisord.conf /etc/supervisord.conf\n```\n(see this [Example template](example/sources/default/templates/centos8/Dockerfile))\n\n## `docker-compose.yml` composition and syntax\n\nA final `docker-compose.yml` will be generated by merging the \n`docker-compose.yml` file returned by each locator. There is no special syntax, \nexcept when you need to reference the path to the final context the compose will \nrun in. This is also known as \"the project path\" and is sent as `$projectRoot`\nto the `DockerComposeCompiler` constructor (see \n[docker-compose compiling](#docker-compose-compiling)).\n\nTo reference that directory, use the `${PROJECT_DIR}` environment variable in \nthe source `docker-compose.yml` files.\n\n(see this [example](example/sources/default/docker-compose.yml))\n\n# \u003ca name=\"locators\"\u003e\u003c/a\u003e Locators\n\nImages and templates are referenced by name. In order to locate and map them to \na source file, one or more locators are used. A standard locator implementation \nis provided, with classes `StdDockerfileLocator` and `StdDockerComposeLocator` \nthat receives a root directory as constructor parameter; every root \ndirectory contains a set of templates and a set of images, and, in case of \n`StdDockerComposeLocator`, zero or one `docker-compose.yml` file. \n\nThe file structure is as follows:\n\n```\n\u003croot_dir\u003e\n  ├ templates\n  │  ├ template_name_1\n  │  │  └ Dockerfile\n  │  └ some_other_template\n  │     └ Dockerfile\n  ├ image_name_1\n  │  └ Dockerfile\n  ├ some_other_image\n  │  └ Dockerfile\n  └ docker-compose.yml\n```\n\nThe difference between the two locators is that:\n\n* `StdDockerfileLocator` is used by `DockerfileCompiler` and will only process\n  images and templates\n* `StdDockerComposeLocator` is used by `DockerComposeCompiler` and will process,\n  in addition to images and templates, also the `docker-compose.yml` file.\n\nIf you need a different directory structure, you can create custom locators \nimplementing `DockerComposeLocator` and `DockerfileLocator` interfaces.\n\n## AppEnv's directory structure\n\nThe directory structure described above is valid for the default `''` (blank) app-env. For using multiple app-envs, the\ndirectory structure changes as such:\n\n```\n\u003croot_dir\u003e\n  ├ common\n  │  ├ templates\n  │  │  ├ template_name_1\n  │  │  │  └ Dockerfile\n  │  │  └ some_other_template\n  │  │     └ Dockerfile\n  │  ├ image_name_1\n  │  │ └ Dockerfile\n  │  ├ some_other_image\n  │  │  └ Dockerfile\n  │  └ docker-compose.yml\n  ├ live\n  │  ├ templates\n  │  │  └ template_name_1\n  │  │     └ Dockerfile\n  │  └ docker-compose.yml\n  └ dev\n     └ docker-compose.yml\n```\n\nThen when a `DockerComposeCompiler` is instanced with `['live', 'common']` as app-env chain for instance, then:\n* When referenced in a `#TEMPALTE[  ]` tag without an app-env specified, or when referenced in a docker-compose file, \n  templates and images will be looked up first in the `live` then in the `common` dir\n* Both `common/docker-compose.yml`, `live/docker-compose.yml` will be merged, in this order.\n\n# \u003ca name=\"dockerfile-compiling\"\u003e\u003c/a\u003e Dockerfile compiling\n\nCompilation of images from templates is done by `DockerfileCompiler`, which is\ninstantiated as follows:\n\n```php\n/**\n * @param DockerfileLocator[] $locators\n * @param string $targetDir\n * @param string[] $appEnv\n */\npublic function __construct(\n   array $locators,\n   string $targetDir,\n   array $appEnv = ['']\n)\n```\n\nThe `$targetDir` is a target directory where compiled image files will be \nwritten. \n\nTo compile the images, you use:\n\n```php\n/** @var \\Exteon\\DockerRecipes\\DockerfileCompiler $compiler */\n$compiler-\u003ecompile();\n```\n\nThis will produce a target directory that for the example source directory \nabove, will produce:\n\n```\n\u003ctarget_dir\u003e\n  ├ image_name_1\n  │  └ Dockerfile\n  └ some_other_image\n     └ Dockerfile\n```\n\nSo for every source image, there will be a target image compiled from the \ntemplates.\n\n# \u003ca name=\"docker-compose-compiling\"\u003e\u003c/a\u003e docker-compose compiling\n\nCompiling recipes for `docker-compose` is done using `DockerComposeCompiler`,\nwhich compiles both images (the same as `DockerfileCompiler`, and a \n`docker-compose.yml`) file from the locators' `docker-compose.yml` files. It is\ninstanced as:\n\n```php\n/**\n * @param DockerComposeLocator[] $locators\n * @param string $dockerfilesTargetDir\n * @param string $composeFileTargetPath\n * @param string $projectRoot\n * @param string[] $appEnv\n */\npublic function __construct(\n    array $locators,\n    string $dockerfilesTargetDir,\n    string $composeFileTargetPath,\n    string $projectRoot,\n    array $appEnv = ['']\n)\n```\n\nThe `$dockerfilesTargetDir` is the target directory for the compiled images. For\nmore info, see [Dockerfile compiling](#dockerfile-compiling).\n\nThe `$composeFileTargetPath` is the target path for the `docker-compose.yml`\nfile to be compiled.\n\nThe `$projectRoot` is the path to a directory that will be used as `${PROJECT_DIR}` substitution in `docker-compose.yml` \nfiles. \n\nThe `$appEnv` is the app-env stack order used to compose the files.\n\nTo compile the images / compose files, you use:\n\n```php\n/** @var \\Exteon\\DockerRecipes\\DockerComposeCompiler $compiler */\n$compiler-\u003ecompile();\n```\n\nWhen compiling `docker-compose.yml` from multiple sources (multiple locators \nthat provide a `docker-compose.yml`), the target file is merged from all the \nsource files using the following algorithm: recursively, for all string keys in \nthe yml file, values are merged (or overridden if scalar). For all sequential\narrays, the contents are appended.\n\n# Example\n\nSince an example is worth a thousand words, you can take a look at \nthe [example](example) dir to see an example of compiling a CentOS8 image with\na webserver, using templates that can be reused for building different other \nimages (such as the `supervisor-rhel8` template).\n\nTo run the example, just run `php example.php`. The `centos8-web` image recipe\nwill be generated in `example/target` and the compose file at \n`example/docker-compose.yml`. To build and run the container, run \n`composer up -d` in `example`","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexteon%2Fdocker-recipes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexteon%2Fdocker-recipes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexteon%2Fdocker-recipes/lists"}