{"id":19956533,"url":"https://github.com/tbreuss/local-dev","last_synced_at":"2025-05-03T20:32:14.895Z","repository":{"id":104902444,"uuid":"184402107","full_name":"tbreuss/local-dev","owner":"tbreuss","description":"Lightweight web development environment for MacOS Monterey using dnsmasq, Docker, Docker-Compose and Traefik","archived":false,"fork":false,"pushed_at":"2024-05-11T11:59:41.000Z","size":36,"stargazers_count":27,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-07T21:11:28.847Z","etag":null,"topics":["dnsmasq","docker","docker-compose","hacktoberfest","homebrew","local-development","macos","traefik"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tbreuss.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-05-01T10:42:19.000Z","updated_at":"2024-11-07T21:20:59.000Z","dependencies_parsed_at":null,"dependency_job_id":"dc8683ab-f75d-4494-8b6d-65ba51c03821","html_url":"https://github.com/tbreuss/local-dev","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbreuss%2Flocal-dev","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbreuss%2Flocal-dev/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbreuss%2Flocal-dev/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbreuss%2Flocal-dev/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tbreuss","download_url":"https://codeload.github.com/tbreuss/local-dev/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252253116,"owners_count":21718770,"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":["dnsmasq","docker","docker-compose","hacktoberfest","homebrew","local-development","macos","traefik"],"created_at":"2024-11-13T01:34:38.959Z","updated_at":"2025-05-03T20:32:09.885Z","avatar_url":"https://github.com/tbreuss.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# LOCAL-DEV\n\n\u003e This is my lightweight local development environment using dnsmasq, Docker, and Traefik running on macOS Monterey.\n\n- [Goals](#goals)\n- [Prerequisites](#prerequisites)\n- [Solution](#solution)\n- [Included Docker Images](#included-docker-images)\n- [Links](#links)\n\n\n## Goals\n\n- Support for local development of multiple docker services with API interdependencies\n- Ability to use *.test domain names from Mac host\n- Ability to use same domain names inside Docker containers\n- Support for HTTP and TCP routes \n- Support for HTTPS (without self-signed certificate so far)\n- No more messing around in /etc/hosts\n\n\n## Prerequisites\n\nThis is my current set up:\n\n- macOS Monterey (12.7)\n- Homebrew (4.2)\n- dnsmasq (2.90)\n- Docker Desktop for Mac (4.28)\n\nThe instructions should also work with older versions.\n\n## Solution\n\n1. Create persistent loopback interface for IP 10.254.254.254\n2. Install dnsmasq using IP 10.254.254.254 for nameserver and address target\n3. Launch Traefik and other containers using Docker Compose\n\n\n### 1. Create persistent loopback interface in macOS\n\nCreate a \"launchd\" daemon that configures an additional IPv4 address.\n\n~~~bash\ncat \u003c\u003c EOF | sudo tee -a /Library/LaunchDaemons/ch.tebe.loopback1.plist\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003c!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"\u003e\n\u003cplist version=\"1.0\"\u003e\n  \u003cdict\u003e\n    \u003ckey\u003eLabel\u003c/key\u003e\n    \u003cstring\u003ech.tebe.loopback1\u003c/string\u003e\n    \u003ckey\u003eProgramArguments\u003c/key\u003e\n    \u003carray\u003e\n        \u003cstring\u003e/sbin/ifconfig\u003c/string\u003e\n        \u003cstring\u003elo0\u003c/string\u003e\n        \u003cstring\u003ealias\u003c/string\u003e\n        \u003cstring\u003e10.254.254.254\u003c/string\u003e\n    \u003c/array\u003e\n    \u003ckey\u003eRunAtLoad\u003c/key\u003e\n    \u003ctrue/\u003e\n  \u003c/dict\u003e\n\u003c/plist\u003e\nEOF\n~~~\n\nLaunch service:\n\n~~~bash\nsudo launchctl load /Library/LaunchDaemons/ch.tebe.loopback1.plist\n~~~\n\nMake sure it works:\n\n~~~bash\nLaunchDaemons % sudo launchctl list | grep ch.tebe\n-\t0\tch.tebe.loopback1\n~~~\n\nRestart Mac and check ifconfig:\n\n~~~bash\nifconfig lo0\nlo0: flags=8049\u003cUP,LOOPBACK,RUNNING,MULTICAST\u003e mtu 16384\n\toptions=1203\u003cRXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP\u003e\n\tinet 127.0.0.1 netmask 0xff000000\n\tinet6 ::1 prefixlen 128\n\tinet6 fe80::1%lo0 prefixlen 64 scopeid 0x1\n\tinet 10.254.254.254 netmask 0xff000000\n\tnd6 options=201\u003cPERFORMNUD,DAD\u003e\n~~~\n\n\n### 2. Install and configure dnsmasq\n\nInstall dnsmasq using Homebrew:\n\n~~~bash\nbrew update # Always update Homebrew and the formulae first\nbrew install dnsmasq\n~~~\n\nStart dnsmasq service:\n\n~~~bash\nsudo brew services start dnsmasq\n~~~\n\nOpen `/usr/local/etc/dnsmasq.conf` and add/uncomment the following line:\n\n~~~bash\nconf-dir=/usr/local/etc/dnsmasq.d,*.conf\n~~~\n\nCreate custom conf file:\n\n~~~bash\nmkdir -p /usr/local/etc/dnsmasq.d\ntouch /usr/local/etc/dnsmasq.d/development.conf\n~~~\n\nAdd routing rule for *.test domain names:\n\n~~~bash\naddress=/.test/10.254.254.254 \n~~~\n\nAdd custom resolver:\n\n~~~bash\nsudo mkdir /etc/resolver\n~~~\n\nCreate a file `/etc/resolver/test` for the *.test domain names and add this line:\n\n~~~bash\nnameserver 10.254.254.254\n~~~\n\nCheck that the resolver is registered.\n\n~~~bash\nscutil --dns\n...\nresolver #8\n  domain   : test\n  nameserver[0] : 10.254.254.254\n  flags    : Request A records\n  reach    : 0x00030002 (Reachable,Local Address,Directly Reachable Address)\n...  \n~~~\n\nCheck the dnsmasq setup:\n\n~~~bash\nping -c 1 google.com # Make sure you can still access the outside world! \nping -c 1 mysite.test\nping -c 1 my.other.site.test\n~~~\n\n\n### 3. Launch Traefik and other containers using Docker Compose\n\nInstall Docker Desktop:\n\n\u003chttps://www.docker.com/products/docker-desktop\u003e\n\nClone project from Github:\n\n~~~\ngit clone https://github.com/tbreuss/local-dev.git\n~~~\n\nStart services using Docker Compose:\n\n~~~\ncd local-dev\ndocker-compose up\n~~~\n\nCheck that everything works as expected.\n\nOpen `http://whoami.test` with your favorite browser. \nYou should see something like:\n\n~~~text\nHostname: eb7f1da188d7\nIP: 127.0.0.1\nIP: 172.18.0.5\nRemoteAddr: 172.18.0.2:45232\nGET / HTTP/1.1\nHost: whoami.test\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\nAccept-Encoding: gzip, deflate\nAccept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7\nDnt: 1\nUpgrade-Insecure-Requests: 1\nX-Forwarded-For: 172.18.0.1\nX-Forwarded-Host: whoami.test\nX-Forwarded-Port: 80\nX-Forwarded-Proto: http\nX-Forwarded-Server: 73db93d4c8e8\nX-Real-Ip: 172.18.0.1\n~~~\n\nNow, open `https://whoami.test` with your favorite browser.\nThe browser displays a NET::ERR_CERT_AUTHORITY_INVALID warning or similar, but lets you proceed to the website if you choose to.\nYou should see a similar output like above.\n\nMake a cURL call from one docker container to another:\n\n~~~bash\ndocker-compose exec adminer curl http://whoami.test\nHostname: eb7f1da188d7\nIP: 127.0.0.1\nIP: 172.18.0.5\nRemoteAddr: 172.18.0.2:45238\nGET / HTTP/1.1\nHost: whoami.test\nUser-Agent: curl/7.80.0\nAccept: */*\nAccept-Encoding: gzip\nX-Forwarded-For: 172.18.0.1\nX-Forwarded-Host: whoami.test\nX-Forwarded-Port: 80\nX-Forwarded-Proto: http\nX-Forwarded-Server: 73db93d4c8e8\nX-Real-Ip: 172.18.0.1\n~~~\n\nTry the same using https:\n\n~~~bash\ndocker-compose exec adminer curl --insecure https://whoami.test\n~~~\n\nYou should see a similar output like above.\n\nDon't forget to check the same after rebooting your Mac.\n\n\n## Included Docker Images\n\nAt the time of writing this repo includes configs for the following Docker images:\n\n- [adminer:4.8](https://hub.docker.com/_/adminer)\n- [containous/whoami:v1.5](https://hub.docker.com/r/containous/whoami)\n- [mailhog/mailhog:v1.0](https://hub.docker.com/r/mailhog/mailhog)\n- [mysql:5.7](https://hub.docker.com/_/mysql)\n- [traefik:v3.0](https://hub.docker.com/_/traefik)\n\n\n## Links\n\nThanks to the authors of these helpful blog posts: \n\n- [Local Dev on Docker - Fun with DNS](https://medium.com/@williamhayes/local-dev-on-docker-fun-with-dns-85ca7d701f0a)\n- [Use dnsmasq instead of /etc/hosts](https://www.stevenrombauts.be/2018/01/use-dnsmasq-instead-of-etc-hosts/)\n- [Persistent loopback interfaces in Mac OS X](https://felipealfaro.wordpress.com/2017/03/22/persistent-loopback-interfaces-in-mac-os-x/)\n- [Traefik Proxy 2.x and TLS 101](https://traefik.io/blog/traefik-2-tls-101-23b4fbee81f1/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftbreuss%2Flocal-dev","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftbreuss%2Flocal-dev","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftbreuss%2Flocal-dev/lists"}