{"id":13551421,"url":"https://github.com/crosbymichael/skydock","last_synced_at":"2025-04-12T22:37:12.525Z","repository":{"id":13371716,"uuid":"16059467","full_name":"crosbymichael/skydock","owner":"crosbymichael","description":"Service discovery via DNS for docker","archived":false,"fork":false,"pushed_at":"2017-02-06T21:34:13.000Z","size":81,"stargazers_count":1051,"open_issues_count":39,"forks_count":86,"subscribers_count":61,"default_branch":"master","last_synced_at":"2025-04-04T02:08:07.316Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/crosbymichael.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}},"created_at":"2014-01-20T02:48:28.000Z","updated_at":"2025-02-19T19:03:01.000Z","dependencies_parsed_at":"2022-08-25T18:20:15.379Z","dependency_job_id":null,"html_url":"https://github.com/crosbymichael/skydock","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crosbymichael%2Fskydock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crosbymichael%2Fskydock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crosbymichael%2Fskydock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crosbymichael%2Fskydock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/crosbymichael","download_url":"https://codeload.github.com/crosbymichael/skydock/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248643006,"owners_count":21138353,"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":[],"created_at":"2024-08-01T12:01:48.014Z","updated_at":"2025-04-12T22:37:12.499Z","avatar_url":"https://github.com/crosbymichael.png","language":"Go","funding_links":[],"categories":["Go","others"],"sub_categories":[],"readme":"### Skydock - Automagic Service Discovery for [Docker](https://github.com/dotcloud/docker)\n[![Build Status](https://travis-ci.org/crosbymichael/skydock.png)](https://travis-ci.org/crosbymichael/skydock)\n\n\n## NOTICE\n\nDocker supports DNS based service discovery now.  You should use the Docker implementation instead of this project.\nSkydock was built at a time when Docker did not support DNS discovery or auto registration.  I'll keep the repo\nup for past years and as reference for others but don't use it if you have a recent version of Docker. \n\n\nSkydock monitors docker events when containers start, stop, die, kill, etc and inserts records into a dynamic\nDNS server [skydns](https://github.com/skynetservices/skydns1).  This allows standard DNS queries for services\nrunning inside docker containers.  Because lets face it, if you have to modify your application code to work\nwith other service discovery solutions you might as well just give up.  DNS just works and it works well.  \nAlso you cannot be expected to modify application code that you don't own.  Passing service urls via the\ncli or in static config files (nginx) will not be possible if your service discovery solution requires\na client library just to fetch an IP.  \n\n\n[Skydns](https://github.com/skynetservices/skydns1) is a very small and simple server that does DNS for \ndiscovery very well.  The authors and contributors to skydns helped a lot to make this project possible.\nSkydns exposes a very simple REST API to add, update, and remove services.\n\n\n#### The Details\n\nWhen you start a container with docker an event is sent to skydock via the events endpoint.  Skydock will\nthen inspect the container's information and add an entry to skydns.  We setup skydns to bind it's nameserver\nto the **docker0** bridge so that it is available to containers.  For DNS queries that are not part of the \ndomain registered with skydns for service discovery, skydns will forward the query to an authoritative nameserver.\nSkydns will return A, AAAA, and SRV records for registered services.\n\n\n\nWhen designing skydock I made the assumption that when in the context of service discovery a client does\nnot care about a specific instance of a service running inside a container.  The client cares about the \nservice and in the context of docker a service is defined by an image.  We have many images; redis, postgres,\nour frontend applications, queues, and workers.  The URL scheme is designed using this assumption.\n\n\n**Parts of the URL**\n* Domain (domain name to resolve DNS requests for)\n* Environment (context of what type of service is running dev, production, qa, uat)\n* Service (the actual service name derived from the image name minus the repository crosbymichael/redis -\u003e redis)\n* Instance (container's name representing the actual instance of a service)\n* Region (currently not used but will be your docker host, digitalocean, ec2; this will be used for multihost)\n\n\nA typical query will look like this if your domain is `crosbymichael.com` and environment is `production`:\n\n```bash\ncurl webapp.production.crosbymichael.com\n```\n\nThe query above will return the IP for a container running the image webapp.  If we want a specific instance\nwe can prepend the container name to the query.  If our webapp container's name was webapp1 we could do this \nto get the specific container.\n\n```bash\ncurl webapp1.webapp.production.crosbymichael.com\n```\n\nVery simple and easy and no client code was harmed in this demonstration.  Wildcard queries are also supported.  \n\n```bash\ndig @172.17.42.1 \"webapp.*.crosbymichael.com\"\n```\n\n\n#### Setup\n\nSo what type of hacks do you have to do to get this running?  Nothing, everything runs inside docker containers.\nYou are just two `docker run` s away from bliss.\n\n\nOk, I lied.  You have to make one change to your docker daemon.  You need to run the daemon with the `-dns` flag so\nthat docker injects a specific nameserver into the `/etc/resolv.conf` of each container that is run.  First get the \nIP address of the `docker0` bridge.  We will need to know the IP of the bridge so that we can tell skydns to bind it's \nnameserver to that IP.  For this example we will use the ip `172.17.42.1` as the `docker0` bridge.\n\n\n```bash\n# start your daemon with the -dns flag, figure it out...\ndocker -d --bip=172.17.42.1/16 --dns=172.17.42.1 # + what other settings you use\n```\n\n**Note:**\nYou can also pass the `-dns` flag to individual containers so that the DNS options only apply to specific \ncontainers and not everything started by the daemon.  But what fun is that?\n\nNow we need to start skydns before our other containers are run or else they will not be able to resolve DNS queries.\n\n```bash\ndocker pull crosbymichael/skydns\ndocker run -d -p 172.17.42.1:53:53/udp --name skydns crosbymichael/skydns -nameserver 8.8.8.8:53 -domain docker\n```\n\nWe add the name skydns to the container and we use `-p` and tell docker to bind skydns port 53/udp to the docker0 bridge's IP.\nWe give skydns a nameserver of `8.8.8.8:53`.  This nameserver is used to forward queries that are not for service discovery to a \nreal nameserver.  If you don't know `8.8.8.8` is google's public DNS address.\n\n\nNext is the `-domain` flag.  This is the domain that you want skydns to resolve DNS queries for.  In this example I am running \ndocker on my local development machine so I am using the domain name `docker`.  Any requests for services `*.docker` will be \nresolved by skydns for service discovery, all other requests will be forwarded to `8.8.8.8`.\n\n\nNow that skydns is running we can start skydock to bridge the gap between docker and skydns.\n\n\n```bash\ndocker pull crosbymichael/skydock\ndocker run -d -v /var/run/docker.sock:/docker.sock --name skydock crosbymichael/skydock -ttl 30 -environment dev -s /docker.sock -domain docker -name skydns\n```\n\n\nThis one is as little more involved but the parts are still simple.  First we give it the name of skydock and we bind docker's unix socket into the container.\nI'm guessing for most, you do not want to service the docker API on a tcp port for containers to reach.  If we bind the unix socket into this container we don't \nhave to worry about other containers accessing the API, only skydock.  We also add a link for skydns so that skydock knows where to make requests to insert \nnew records.  We are pre DNS discovery at this point.\n\n\nNow we have a few settings to assign to skydock.  First is the TTL value that you want all services to have when skydock adds them to DNS.  I'm using a\nTTL value 30 seconds but you can set it higher or lower if needed.  Skydock will also start a heartbeat for the service after it is added.  You can use \nthe `-beat` flag to set this default interval in seconds for the heartbeat or skydock will set the heartbeat interval to `TTL -(TTL/4)`.  I know, too \ncomplicated.\n\n\nNext is the `-environment` flag which is the second part of your DNS queries.  I set this to `dev` because it is running on my local machine.  `-s` is \nthe final option and it just tells skydock where to find docker's unix socket so that it can make requests to docker's API.\n\n\nNow you're done.  Just start containers and use intuitive urls to discover your services.  Here is an small example starting a redis server and connecting \nthe redis-cli to that instance of the service.  Because it's DNS you can specific the urls on `docker run`.  \n\n\n```bash\n# run an instance of redis\ndocker run -d --name redis1 crosbymichael/redis\n03582c0de0ebb10665678d6ed530ae98bebd7d63dad5e7fb1cd53ffb1f85d91d\n\n# run the cli and connect to our new instance\ndocker run -t -i crosbymichael/redis-cli -h redis1.redis.dev.docker\n\nredis.dev.docker:6379\u003e set name koye\nOK\nredis.dev.docker:6379\u003e get name\n\"koye\"\nredis.dev.docker:6379\u003e\n\n```\n\nThat is, the `redis1` named `crosbymichael/redis` container was available under the hostname `redis1.redis.dev.docker`.\n\n```\ndig @172.17.42.1 +short redis1.redis.dev.docker\n172.17.0.4\n```\n\nIf you were to run additional `crosbymichael/redis` containers, they would all be available under the `redis.dev.docker` hostname.\n\n```\ndocker run -d --name redis2 crosbymichael/redis\ndocker run -d --name redis3 crosbymichael/redis\n\ndig @172.17.42.1 +short redis.dev.docker\n172.17.0.4\n172.17.0.5\n172.17.0.6\n```\n\n#### Plugin support\nI just added plugin support via [otto](https://github.com/robertkrimen/otto) to allow users to write plugins in javascript.  Currently only one function uses plugins and that is `createService(container)`.  This function takes a container's configuration and converts it into a DNS service  The current functionality is implementing in this javascript function:\n\n```javascript\nfunction createService(container) {\n    return {\n        Port: 80,\n        Environment: defaultEnvironment,\n        TTL: defaultTTL,\n        Service: cleanImageName(container.Image),\n        Instance: removeSlash(container.Name),\n        Host: container.NetworkSettings.IpAddress\n    }; \n}\n```\n\nYour function must be called `createservice` which takes one object, the container, and must return a service with the fields shown above.  In your plugin you have access to the following global variables and functions.\n\n\n```javascript\nvar defaultEnvironment = \"string - the environment from the -environment flag\";\nvar defaultTTL = 30; // int - the ttl value from the -ttl flag\n\nfunction cleanImageName(string) string // cleans the repo and tags of the passed parameter returning the result\nfunction removeSlash(string) string  // removes all / from the passed parameter returning the result\n```\n\nAnd that is it.  Just add a `createservice` function to a .js file then use the `-plugins` flag to enable your new plugin.  Plugins are loaded at start so changes made to the functions during the life of skydock are not reflected, you have to restart ( done for performance ).  \n\n```bash\ndocker run -d -v /var/run/docker.sock:/docker.sock -v /myplugins.js:/myplugins.js --name skydock --link skydns:skydns crosbymichael/skydock -s /docker.sock -domain docker -plugins /myplugins.js\n```\n\nFeel free to submit your plugins to this repo under the `plugins/` directory.  \n\n\n#### TODO/ROADMAP\n* Multihost support\n* Handle multiple ports via SRV records\n\n#### Bugs\n* Please report all skydock bugs on this repository\n* Report all skydns bugs [here](https://github.com/skynetservices/skydns1/issues?state=open)\n\n#### License - MIT\n\nCopyright (c) 2014 Michael Crosby. michael@crosbymichael.com\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation \nfiles (the \"Software\"), to deal in the Software without \nrestriction, including without limitation the rights to use, copy, \nmodify, merge, publish, distribute, sublicense, and/or sell copies \nof the Software, and to permit persons to whom the Software is \nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be \nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED,\nINCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. \nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \nHOLDERS BE LIABLE FOR ANY CLAIM, \nDAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, \nTORT OR OTHERWISE, \nARISING FROM, OUT OF OR IN CONNECTION WITH \nTHE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrosbymichael%2Fskydock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrosbymichael%2Fskydock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrosbymichael%2Fskydock/lists"}