{"id":13582458,"url":"https://github.com/zekiunal/swarm-template","last_synced_at":"2026-01-28T20:41:44.316Z","repository":{"id":79633284,"uuid":"76790319","full_name":"zekiunal/swarm-template","owner":"zekiunal","description":"Generic template rendering for Docker Swarm Mode","archived":false,"fork":false,"pushed_at":"2017-07-23T08:35:41.000Z","size":23,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"v2","last_synced_at":"2024-11-05T22:41:25.236Z","etag":null,"topics":["devops","docker","service-discovery","swarm-mode","swarm-template","templating"],"latest_commit_sha":null,"homepage":"","language":"Go","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/zekiunal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-12-18T15:18:01.000Z","updated_at":"2020-08-18T15:32:48.000Z","dependencies_parsed_at":"2023-06-19T06:26:48.541Z","dependency_job_id":null,"html_url":"https://github.com/zekiunal/swarm-template","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zekiunal%2Fswarm-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zekiunal%2Fswarm-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zekiunal%2Fswarm-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zekiunal%2Fswarm-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zekiunal","download_url":"https://codeload.github.com/zekiunal/swarm-template/tar.gz/refs/heads/v2","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247495739,"owners_count":20948102,"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":["devops","docker","service-discovery","swarm-mode","swarm-template","templating"],"created_at":"2024-08-01T15:02:44.118Z","updated_at":"2026-01-28T20:41:44.310Z","avatar_url":"https://github.com/zekiunal.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"Swarm Template\n===============\n\nThe daemon swarm-template queries a Docker Swarm API and updates any number of specified templates on the file system.\nswarm-template can optionally run arbitrary commands when the update process completes.\n\nInstallation\n------------\n\nYou can download a released `swarm-template` artifact from\n [the Swarm Template release page](https://github.com/zekiunal/swarm-template/releases/). If you wish to compile from source,\nplease see the instructions in the [Contributing](#contributing) section.\n\nUsage\n-----\n\n### Command Line\nThe CLI interface supports all of the options detailed above.\n\n#### Help\n\n```shell\n# ./swarm-template -h\n\nUsage: swarm-template [options]\n\nGenerate files from docker swarm api\n\nOptions:\n  -cmd restart xyz\n        run command after template is regenerated (e.g restart xyz) (default \"true\")\n  -host string\n        swarm manager address. (default \"unix:///var/run/docker.sock\")\n  -interval int\n        notify command interval (secs) (default 1)\n  -target_file string\n        path to a write the template. (default \"example/template.cfg\")\n  -template_file string\n        path to a template to generate (default \"example/template.tmpl\")\n  -version\n        show version\nFor more information, see https://github.com/zekiunal/swarm-template\n\n```\n\n#### Run \n\n```shell\n$ ./swarm-template \\\n    -host=\"tcp://0.0.0.0:2375\"\n    -template_file=\"example/template.tmpl\" \\\n    -target_file=\"example/target_file\" \\\n    -cmd=\"/usr/sbin/nginx -s reload\" \\\n```\n\n### Example\n\n#### 1 - Create example services\n\n```shell\ndocker service rm api-example-com_v1-000 api-example-com_v1-001 anotherapi-example-com_v1-0000 anotherapi-example-com_v1-0001 anotherapi-example-com_v1-0002 logs-example-com static-example-com www-example-com\n\ndocker service create --name www-example-com --label st.tags=\"backend,development,public\" --label st.version=\"1.000\" --label st.group=www.example.com alpine ping docker.com\n\ndocker service create --name static-example-com --label st.tags=\"static,development,public\" --label st.version=\"1.000\" --label st.group=static.example.com alpine ping docker.com   \n \ndocker service create --name logs-example-com --label st.tags=\"backend,development,internal\" --label st.version=\"1.000\" --label st.group=logs.example.com alpine ping docker.com\n\ndocker service create --name api-example-com_v1-000 --label st.tags=\"backend,development,public,internal,api\" --label st.version=\"1.000\" --label st.group=api.example.com  alpine ping docker.com\n                        \ndocker service create --name api-example-com_v1-001 --label st.tags=\"backend,development,public,internal,api\" --label st.version=\"1.001\" --label st.group=api.example.com alpine ping docker.com\n \ndocker service create --name anotherapi-example-com_v1-0000 --label st.tags=\"backend,development,public,internal,api\" --label st.version=\"1.000\" --label st.group=anotherapi.example.com alpine ping docker.com\n                        \ndocker service create --name anotherapi-example-com_v1-0001 --label st.tags=\"backend,development,public,internal,api\" --label st.version=\"1.001\" --label st.group=anotherapi.example.com alpine ping docker.com\n\ndocker service create --name anotherapi-example-com_v1-0002 --label st.tags=\"backend,development,public,internal,api\" --label st.version=\"1.002\" --label st.group=anotherapi.example.com alpine ping docker.com\n```\n\n#### 2 - Run swarm-template\n\n```shell\ngo get -d -v -t \u0026\u0026 go build -v  \u0026\u0026 ./swarm-template -template_file=\"example/template.tmpl\" -target_file=\"example/nginx.conf\"\n```\n\n#### Results\n\n```shell\n# ./swarm-template -template_file=\"example/template.tmpl\" -target_file=\"example/nginx.conf\"\n_/zeki/swarm-template\n2016/12/20 12:20:47 Starting Swarm Template\n2016/12/20 12:20:47 Added   : api-example-com_v1-001\n2016/12/20 12:20:47 Added   : www-example-com\n2016/12/20 12:20:47 Added   : anotherapi-example-com_v1-0000\n2016/12/20 12:20:47 Added   : anotherapi-example-com_v1-0001\n2016/12/20 12:20:47 Added   : anotherapi-example-com_v1-0002\n2016/12/20 12:20:47 Added   : logs-example-com\n2016/12/20 12:20:47 Added   : api-example-com_v1-000\n2016/12/20 12:20:47 Added   : static-example-com\n\n```\n\n##### template file\n\n```\n{{ define \"main\" }}\n########################################################################################################################\n# List Backend UpStreams\n########################################################################################################################\n{{ range $service := . }}{{$service_name:=.Name}}{{ range $label := .Labels }}{{ if and ( . | contains \"backend\") ( . | contains \"development\") }}\nupstream {{$service_name}} {\n    server {{$service_name}}:9000 weight=100 max_fails=5000 fail_timeout=5;\n}{{ end }}{{ end }}{{ end }}\n\n########################################################################################################################\n# List External Services\n########################################################################################################################\n{{$services := .}}{{ range group . }}{{$service_name:=.Name}}{{$domain := index .Labels \"st.group\"}}{{ range $label := .Labels }}{{ if and ( . | contains \"backend\") ( . | contains \"development\") }}\nserver {\n    listen 80;\n    server_name {{$domain}};\n    ..\n    ...\n\n    location @rewrite3 {\n        rewrite ^({{ range keyBy $services $domain}}/v{{index .Labels \"st.version\"}}|{{end}})/(.*)$ $1/index.php?_url=/$2;\n    }\n    {{ range keyBy $services $domain}}{{$version := index .Labels \"st.version\"}}\n    location /v{{$version}} {\n        root /www/http/public/;\n        try_files $uri $uri/ @rewrite3;\n        location ~ ^/v{{$version}}(.+\\.php)$ {\n            fastcgi_pass {{$service_name}};\n            ..\n            ...\n            fastcgi_param VERSION v{{$version}};\n        }\n    }{{end}}\n}{{ end }}{{end}}{{end}}\n########################################################################################################################\n# List Internal Setup\n########################################################################################################################\nserver {\n    listen       80  default_server;\n    server_name  _;\n    ..\n    ...\n\n    location @rewrite2 {\n        rewrite ^({{ range $service := . }}{{$service_name:=.Name}}{{ range $label := .Labels }}{{ if and ( . | contains \"development\") ( . | contains \"backend\") ( . | contains \"internal\") }}{{$service_parse := $service_name | split \"_\"}}{{range $key, $value := $service_parse}}{{if eq $key 1}}{{$value_v := $value | replaceAll \"-\" \".\"}}/{{$value_v}}{{else}}/{{$value}}{{end}}{{end}}|{{end}}{{end}}{{end}})/(.*)$ $1/index.php?_url=/$2;\n    }\n    {{ range $service := . }}{{$service_name:=.Name}}{{ range $label := .Labels }}{{ if and ( . | contains \"development\") ( . | contains \"backend\") ( . | contains \"internal\") }}{{$service_parse := $service_name | split \"_\"}}\n    location {{range $key, $value := $service_parse}}{{if eq $key 1}}{{$value_v := $value | replaceAll \"-\" \".\"}}/{{$value_v}}{{else}}/{{$value}}{{end}}{{end}} {\n        root /www/http/public/;\n        try_files $uri $uri/ @rewrite2;\n        location ~ ^{{$service_parse := $service_name | split \"_\"}}{{range $key, $value := $service_parse}}{{if eq $key 1}}{{$value_v := $value | replaceAll \"-\" \".\"}}/{{$value_v}}{{else}}/{{$value}}{{end}}{{end}}(.+\\.php)$ {\n            fastcgi_pass {{$service_name}};\n            ..\n            ...\n            fastcgi_param VERSION {{$service_parse := $service_name | split \"_\"}}{{range $key, $value := $service_parse}}{{if eq $key 1}}{{$value_v := $value | replaceAll \"-\" \".\"}}{{$value_v}}{{end}}{{end}};\n        }\n    }{{end}}{{end}}{{end}}\n}\n{{end}}\n```\n\n##### generated target file\n\n```\n########################################################################################################################\n# List Backend UpStreams\n########################################################################################################################\nupstream anotherapi-example-com_v1-0000 {\n    server anotherapi-example-com_v1-0000:9000 weight=100 max_fails=5000 fail_timeout=5;\n}\nupstream api-example-com_v1-001 {\n    server api-example-com_v1-001:9000 weight=100 max_fails=5000 fail_timeout=5;\n}\nupstream www-example-com {\n    server www-example-com:9000 weight=100 max_fails=5000 fail_timeout=5;\n}\nupstream api-example-com_v1-000 {\n    server api-example-com_v1-000:9000 weight=100 max_fails=5000 fail_timeout=5;\n}\nupstream logs-example-com {\n    server logs-example-com:9000 weight=100 max_fails=5000 fail_timeout=5;\n}\nupstream anotherapi-example-com_v1-0001 {\n    server anotherapi-example-com_v1-0001:9000 weight=100 max_fails=5000 fail_timeout=5;\n}\nupstream anotherapi-example-com_v1-0002 {\n    server anotherapi-example-com_v1-0002:9000 weight=100 max_fails=5000 fail_timeout=5;\n}\n\n########################################################################################################################\n# List External Services\n########################################################################################################################\nserver {\n    listen 80;\n    server_name anotherapi.example.com;\n    ..\n    ...\n\n    location @rewrite3 {\n        rewrite ^(/v1.000|/v1.001|/v1.002|)/(.*)$ $1/index.php?_url=/$2;\n    }\n    \n    location /v1.000 {\n        root /www/http/public/;\n        try_files $uri $uri/ @rewrite3;\n        location ~ ^/v1.000(.+\\.php)$ {\n            fastcgi_pass anotherapi-example-com_v1-0000;\n            ..\n            ...\n            fastcgi_param VERSION v1.000;\n        }\n    }\n    location /v1.001 {\n        root /www/http/public/;\n        try_files $uri $uri/ @rewrite3;\n        location ~ ^/v1.001(.+\\.php)$ {\n            fastcgi_pass anotherapi-example-com_v1-0000;\n            ..\n            ...\n            fastcgi_param VERSION v1.001;\n        }\n    }\n    location /v1.002 {\n        root /www/http/public/;\n        try_files $uri $uri/ @rewrite3;\n        location ~ ^/v1.002(.+\\.php)$ {\n            fastcgi_pass anotherapi-example-com_v1-0000;\n            ..\n            ...\n            fastcgi_param VERSION v1.002;\n        }\n    }\n}\n\nserver {\n    listen 80;\n    server_name api.example.com;\n    ..\n    ...\n\n    location @rewrite3 {\n        rewrite ^(/v1.001|/v1.000|)/(.*)$ $1/index.php?_url=/$2;\n    }\n    \n    location /v1.001 {\n        root /www/http/public/;\n        try_files $uri $uri/ @rewrite3;\n        location ~ ^/v1.001(.+\\.php)$ {\n            fastcgi_pass api-example-com_v1-001;\n            ..\n            ...\n            fastcgi_param VERSION v1.001;\n        }\n    }\n    location /v1.000 {\n        root /www/http/public/;\n        try_files $uri $uri/ @rewrite3;\n        location ~ ^/v1.000(.+\\.php)$ {\n            fastcgi_pass api-example-com_v1-001;\n            ..\n            ...\n            fastcgi_param VERSION v1.000;\n        }\n    }\n}\n\nserver {\n    listen 80;\n    server_name www.example.com;\n    ..\n    ...\n\n    location @rewrite3 {\n        rewrite ^(/v1.000|)/(.*)$ $1/index.php?_url=/$2;\n    }\n    \n    location /v1.000 {\n        root /www/http/public/;\n        try_files $uri $uri/ @rewrite3;\n        location ~ ^/v1.000(.+\\.php)$ {\n            fastcgi_pass www-example-com;\n            ..\n            ...\n            fastcgi_param VERSION v1.000;\n        }\n    }\n}\n\nserver {\n    listen 80;\n    server_name logs.example.com;\n    ..\n    ...\n\n    location @rewrite3 {\n        rewrite ^(/v1.000|)/(.*)$ $1/index.php?_url=/$2;\n    }\n    \n    location /v1.000 {\n        root /www/http/public/;\n        try_files $uri $uri/ @rewrite3;\n        location ~ ^/v1.000(.+\\.php)$ {\n            fastcgi_pass logs-example-com;\n            ..\n            ...\n            fastcgi_param VERSION v1.000;\n        }\n    }\n}\n########################################################################################################################\n# List Internal Setup\n########################################################################################################################\nserver {\n    listen       80  default_server;\n    server_name  _;\n    ..\n    ...\n\n    location @rewrite2 {\n        rewrite ^(/anotherapi-example-com/v1.0000|/api-example-com/v1.001|/api-example-com/v1.000|/logs-example-com|/anotherapi-example-com/v1.0001|/anotherapi-example-com/v1.0002|)/(.*)$ $1/index.php?_url=/$2;\n    }\n    \n    location /anotherapi-example-com/v1.0000 {\n        root /www/http/public/;\n        try_files $uri $uri/ @rewrite2;\n        location ~ ^/anotherapi-example-com/v1.0000(.+\\.php)$ {\n            fastcgi_pass anotherapi-example-com_v1-0000;\n            ..\n            ...\n            fastcgi_param VERSION v1.0000;\n        }\n    }\n    location /api-example-com/v1.001 {\n        root /www/http/public/;\n        try_files $uri $uri/ @rewrite2;\n        location ~ ^/api-example-com/v1.001(.+\\.php)$ {\n            fastcgi_pass api-example-com_v1-001;\n            ..\n            ...\n            fastcgi_param VERSION v1.001;\n        }\n    }\n    location /api-example-com/v1.000 {\n        root /www/http/public/;\n        try_files $uri $uri/ @rewrite2;\n        location ~ ^/api-example-com/v1.000(.+\\.php)$ {\n            fastcgi_pass api-example-com_v1-000;\n            ..\n            ...\n            fastcgi_param VERSION v1.000;\n        }\n    }\n    location /logs-example-com {\n        root /www/http/public/;\n        try_files $uri $uri/ @rewrite2;\n        location ~ ^/logs-example-com(.+\\.php)$ {\n            fastcgi_pass logs-example-com;\n            ..\n            ...\n            fastcgi_param VERSION ;\n        }\n    }\n    location /anotherapi-example-com/v1.0001 {\n        root /www/http/public/;\n        try_files $uri $uri/ @rewrite2;\n        location ~ ^/anotherapi-example-com/v1.0001(.+\\.php)$ {\n            fastcgi_pass anotherapi-example-com_v1-0001;\n            ..\n            ...\n            fastcgi_param VERSION v1.0001;\n        }\n    }\n    location /anotherapi-example-com/v1.0002 {\n        root /www/http/public/;\n        try_files $uri $uri/ @rewrite2;\n        location ~ ^/anotherapi-example-com/v1.0002(.+\\.php)$ {\n            fastcgi_pass anotherapi-example-com_v1-0002;\n            ..\n            ...\n            fastcgi_param VERSION v1.0002;\n        }\n    }\n}\n\n```\n\n### Templating Language\n\nSwarm Template consumes template files in the [Go Template][] format.\n\n#### Additional Functions\n\n##### `env`\n\nWrapper for os.Getenv. Retrieves the value of the environment variable named by the key. It returns the value, which will be empty if the variable is not present. Optionally, you can give a default value that will be returned if the key is not present.\n\n```liquid\n{{env \"HOSTNAME\" \"127.0.0.1\"}}\n```\n\n##### `group`\nQuery Swarm API for all services in the group by \"st.group\" label. Services are queried using the following syntax:\n\n```liquid\n{{ range group . }}\n    # ...\n{{ end}}\n```\n\n##### `KeyBy`\n\nCreates a map that groups services by tag\n\n```liquid\n{{$services := . }}\n\n{{ range keyBy $services \"example_value\"}}\n    # ...\n{{end}}\n```\n\n##### `contains`\nDetermines if a needle is within an iterable element.\n\n```liquid\n{{ range .Labels }}\n    {{ if and ( . | contains \"backend\") ( . | contains \"production\") }}\n        # ...\n    {{ end }}\n{{ end }}\n```\n\n##### `replaceAll`\nTakes the argument as a string and replaces all occurrences of the given string with the given string.\n\n```liquid\n{{\"foo.bar\" | replaceAll \".\" \"_\"}}\n```\n\nThis function can be chained with other functions as well:\n\n```liquid\n{{$variable := .Example | replaceAll \"-\" \".\"}}\n```\n\n##### `split`\nSplits the given string on the provided separator:\n\n```liquid\n{{\"application_version\" | split \"_\"}}\n```\n\nContributing\n------------\n\n### Build \n\n```\ndocker run --rm --name go-build -v \"$PWD\":\"/go/src/swarm-template\" -w \"/go/src/swarm-template\"  golang sh -c \" go get; go build -v\"\n```\n\n#### Alpine\n```\ndocker run --rm -v \"$PWD\":\"/go/src/swarm-template\" -w \"/go/src/swarm-template\" golang:alpine sh -c \"apk add --update git \u0026\u0026 go get -v; go build -v\" \u0026\u0026 tar -zcvf swarm-template.tar.gz $PWD/swarm-template\n```\n\nIf you want to contribute to our project, please follow these guidelines:\n\n1. Fork the repo\n2. Choose the correct branch to base your contribution (see details bellow)\n3. Implement and test your code\n4. Submit a pull request\n\nToDo\n------------\n * -cmd options multi command support\n \nThank You\n------------\n \n * [AzMesai](http://azmesai.net/) Group Members\n \n \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzekiunal%2Fswarm-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzekiunal%2Fswarm-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzekiunal%2Fswarm-template/lists"}