{"id":20210619,"url":"https://github.com/luisaveiro/docker-reverse-proxy","last_synced_at":"2025-07-08T18:03:51.308Z","repository":{"id":176325707,"uuid":"433537400","full_name":"luisaveiro/docker-reverse-proxy","owner":"luisaveiro","description":"Local reverse proxy for Docker containers powered by Caddy.","archived":false,"fork":false,"pushed_at":"2025-03-13T22:43:31.000Z","size":1780,"stargazers_count":64,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-24T12:05:31.612Z","etag":null,"topics":["caddy","developer-experience","developer-productivity","developer-tool","docker","docker-compose","local-development","local-domain","reverse-proxy"],"latest_commit_sha":null,"homepage":"","language":null,"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/luisaveiro.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null},"funding":{"github":["luisaveiro"],"custom":["https://www.buymeacoffee.com/luisaveiro"]}},"created_at":"2021-11-30T18:13:13.000Z","updated_at":"2025-03-13T22:43:04.000Z","dependencies_parsed_at":"2023-12-31T01:50:20.389Z","dependency_job_id":"4ccbb352-7c43-4f45-bba0-987c8d1265a9","html_url":"https://github.com/luisaveiro/docker-reverse-proxy","commit_stats":null,"previous_names":["luisaveiro/docker-reverse-proxy"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luisaveiro%2Fdocker-reverse-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luisaveiro%2Fdocker-reverse-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luisaveiro%2Fdocker-reverse-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luisaveiro%2Fdocker-reverse-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/luisaveiro","download_url":"https://codeload.github.com/luisaveiro/docker-reverse-proxy/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248225661,"owners_count":21068078,"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":["caddy","developer-experience","developer-productivity","developer-tool","docker","docker-compose","local-development","local-domain","reverse-proxy"],"created_at":"2024-11-14T05:48:41.971Z","updated_at":"2025-04-10T13:21:40.012Z","avatar_url":"https://github.com/luisaveiro.png","language":null,"readme":"\u003cp align=\"center\"\u003e\n    \u003ca href=\"http://github.com/luisaveiro/docker-reverse-proxy\"\u003e\n        \u003cimg \n            src=\"./images/programming.svg\" \n            alt=\"programming\" \n            width=\"50%\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n\u003ch4 align=\"center\"\u003e\n    Local reverse proxy for Docker containers powered by Caddy.\n\u003c/h4\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"#about\"\u003eAbout\u003c/a\u003e •\n    \u003ca href=\"#disclaimer\"\u003eDisclaimer\u003c/a\u003e •\n    \u003ca href=\"#getting-started\"\u003eGetting Started\u003c/a\u003e •\n    \u003ca href=\"#download\"\u003eDownload\u003c/a\u003e •\n    \u003ca href=\"#how-to-use\"\u003eHow To Use\u003c/a\u003e •\n    \u003ca href=\"#faq\"\u003eFAQ\u003c/a\u003e •\n    \u003ca href=\"#useful-tips\"\u003eUseful Tips\u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"#changelog\"\u003eChangelog\u003c/a\u003e •\n    \u003ca href=\"#contributing\"\u003eContributing\u003c/a\u003e •\n    \u003ca href=\"#security-vulnerabilities\"\u003eSecurity Vulnerabilities\u003c/a\u003e •\n    \u003ca href=\"#credits\"\u003eCredits\u003c/a\u003e •\n    \u003ca href=\"#Sponsor\"\u003eSponsor\u003c/a\u003e •\n    \u003ca href=\"#license\"\u003eLicense\u003c/a\u003e\n\u003c/p\u003e\n\n## About\n\nThis repository offers a simple approach to having [Caddy Server](https://caddyserver.com/) \nas a local reverse proxy for your [Docker](https://www.docker.com/) containers. \nCaddy Server is the first and only web server to use HTTPS automatically with \nno extra configuration or separate tooling required.\n\n**Why would you need a local reverse proxy?**  \nWith a hosts file, you can only map hostnames to IP addresses. Hosts file does \nnot support mapping ports with IP addresses. You are unable to map multiple \ncontainers to hostnames.\n\nAs a developer, you might be working on multiple Docker-based projects. We have \nall experienced the Docker container port binding failure message - \n*Bind for 0.0.0.0:80 failed: port is already allocated.*\n\nOr you are working on a multi-tenant application that requires tenants to log \nin on their subdomain. Developing locally can be challenging with this \nrequirement.\n\nHaving a reverse proxy you can assign domains or subdomains to your Docker \ncontainers without the need to worry about port binding failures or develop \nlocally with a multi-tenant subdomain application.\n\n## Disclaimer\n\n\u003e [!IMPORTANT]  \n\u003e ***Docker Reverse Proxy*** is not affiliated with Stack Holdings \nGmbH or Docker, Inc and is not an official product from either company. \n\n\"Caddy\" is a registered trademark of Stack Holdings GmbH.\n\"Docker\" is a registered trademark of Docker, Inc.\n\n***Docker Reverse Proxy*** has been developed to run Caddy in a local Docker \nenvironment. If you wish to use Caddy on your system, you can follow the follow \nthe [Installation Guide](https://caddyserver.com/docs/install).\n\n## Getting Started\n\nYou will need to make sure your system meets the following prerequisites:\n\n- Docker Engine \u003e= 20.10.00\n\nThis repository utilizes [Docker](https://www.docker.com/) to run Caddy. So, \nbefore using ***Docker Reverse Proxy***, make sure you have Docker installed \non your system.\n\n## Download\n\nYou can clone the latest version of ***Docker Reverse Proxy*** repository for \nmacOS, Linux and Windows.\n\n```bash\n# Clone this repository.\n$ git clone git@github.com:luisaveiro/docker-reverse-proxy.git --branch main --single-branch\n```\n\n## How To Use\n\nBelow is the current directory structure for the ***Docker Reverse Proxy*** repository.\n\n```\n.\n+-- config\n|   +-- Caddyfile.example\n+-- .env.example\n+-- compose.yaml\n```\n\nThere are a few steps you need to follow before you can have Caddy set up and \nrunning as a reverse proxy for your Docker containers. I have outline the steps \nyou would need to take to get started.\n\n#### 1. \u003cins\u003eUpdate your hosts file\u003c/ins\u003e\n\nYou will need to modify your `/etc/hosts` file to include the hostnames entries.\nThe hostname is the domain or subdomain you wish to direct traffic for a Docker \ncontainer. \n\nThe structure of the hostname entry must be your loopback IP Address \n(`127.0.0.1`) and domain/subdomain. For example:\n\n```\n127.0.0.1 domain.local\n```\n\n\u003e [!NOTE]  \n\u003e The hosts file **does not support wildcard** (`*`) for domains \nor subdomains. You will need to have an entry for each domain and subdomain you \nwish to use for the reverse proxy in your hosts file.\n\n#### 2. \u003cins\u003eCreate a Caddyfile\u003c/ins\u003e\n\nOnce you have added your domain/subdomain entry to your hosts file, you will \nneed to create a `Caddyfile`. The Caddyfile is a convenient Caddy configuration \nformat for humans. \n\n***Docker Reverse Proxy*** includes a `Caddyfile.example` file in the config \ndirectory to help you get started. You can run the following command in the \nterminal to create your Caddyfile file.\n\n```bash\n# Create Caddyfile from Caddyfile.example.\n$ cp config/Caddyfile.example config/Caddyfile\n```\n\n#### 3. \u003cins\u003eAdd your site blocks to your Caddyfile\u003c/ins\u003e\n\nCaddy supports various configurations, you can follow the \n[Caddy Documentation](https://caddyserver.com/docs/caddyfile) to learn more \nabout the various configurations supported by Caddyfile.\n\nThis readme will focus on the Caddyfile reverse proxy configuration \n(*with minimum configuration*). You will need to create a site block in the \nCaddyfile to match the domain entry of your hosts file. \n\nThe `Caddyfile.example` file has an example of the structure of the site block.\n\n```ini\n# HTTP site block\n\u003chostname\u003e:80 {\n  reverse_proxy \u003ccontainer-name\u003e:\u003cport\u003e\n}\n\n# HTTPS site block\n\u003chostname\u003e:443 {\n  tls internal\n  reverse_proxy \u003ccontainer-name\u003e:\u003cport\u003e\n}\n```\n\nLet's cover the the Caddyfile's structure:\n\n- **Site block**  \nThe site block defines the Caddy configuration for a given site address. You \ncan identify a site block by the curly braces.\n\n- **Site address**  \nThe site address is the domain/subdomain entry which matches your hostname in \nyour hosts file. Unlike your hosts file, Caddyfile supports port mapping.\n\n- **Directive**  \nA directive is the Caddy instruction. Caddy has a variety of \n[directives](https://caddyserver.com/docs/caddyfile/directives). This is readme \nwill focus on the [reverse_proxy](https://caddyserver.com/docs/caddyfile/directives/reverse_proxy) \ndirective.\n\n- **Argument**  \nThe reverse_proxy argument is the upstream which Caddy will proxy. In our use \ncase the upstream will be the Docker container name and the exposed port. \n\n- **TLS (HTTPS only)**  \nThe TLS directive is to configure HTTPS for the site block. By using the \ninternal option, we are using Caddy's internal, locally-trusted CA to produce \ncertificates for the site.\n\nBelow is an example of a configured site block:\n\n```ini\n# Personal website\nwebsite.local:80 {\n  reverse_proxy website_app:8080\n}\n\n# Personal website using HTTPS\nwebsite.local:443 {\n  tls internal\n  reverse_proxy website_app:8080\n}\n```\n\n#### 4. \u003cins\u003eStart Caddy Docker container\u003c/ins\u003e\n\nAfter you have configured your Caddyfile, you can start Caddy Docker container.\n***Docker Reverse Proxy*** includes a `compose.yaml` file with Caddy \npre-configured. You can run the following command:\n\n```bash\n# Start Caddy Docker container\n$ docker compose up\n\n# Or start Caddy Docker container detached mode\n$ docker compose up -d\n```\n\nDocker will create the Caddy container which is called `docker-reverse-proxy`. \nThe container will be attached to a network called `reverse_proxy`. \n\nIf you want to change the container name, network name or volume names, you can \ncreate a DotEnv file and override the Docker Compose variables. Below is an \nexample of the DotEnv variables.\n\n```ini\n#--------------------------------------------------------------------------\n# Docker env\n#--------------------------------------------------------------------------\n\n# The project name. | default: reverse_proxy\nAPP_NAME=\"reverse_proxy\"\n\n#--------------------------------------------------------------------------\n# Container env\n#--------------------------------------------------------------------------\n\n# The Caddy Server Docker container name. | default: reverse_proxy\nCONTAINER_NAME=\"${APP_NAME}\"\n\n#--------------------------------------------------------------------------\n# Network env\n#--------------------------------------------------------------------------\n\n# Map the Admin API port to the host port. | default: 2019\nADMIN_API_PORT=2019\n\n# The Docker network for the containers. | default: reverse_proxy\nNETWORK_NAME=\"reverse_proxy\"\n\n#--------------------------------------------------------------------------\n# Volume env\n#--------------------------------------------------------------------------\n\n# The app container data volume. | default: reverse_proxy_data\nCONTAINER_VOLUME_DATA_NAME=\"${CONTAINER_NAME}_data\"\n\n# The app container config volume. | default: reverse_proxy_config\nCONTAINER_VOLUME_CONFIG_NAME=\"${CONTAINER_NAME}_config\"\n\n```\n\n***Docker Reverse Proxy*** includes a `.env.example` file to get you started. \nYou can run the following command in the terminal to create your DotEnv file.\n\n```bash\n# Create .env from .env.example.\n$ cp .env.example .env\n```\n\n#### 5. \u003cins\u003eTrusting Caddy certificate authority (CA)\u003c/ins\u003e\n\nIf you are not planning to use HTTPS for local development, you can skip this \nstep.\n\nCaddy generates its own certificate authority (CA) and uses it to sign \ncertificates. After Caddy's root CA is created, you will need to add the \ncertificate to your local trust store. I have outline the steps you would need \nto take.\n\n\u003e [!IMPORTANT]  \n\u003e Please ensure you have the latest update of the Caddy Docker image.\n\nCaddy container will create and mount a folder called `certificate-authority`. \nIn this folder you will see certificate and key files. You will be installing \nthe `root.crt` in your local trust store.\n\nOpen the \"Keychain Access\" app and drag and drop the certificate into the \n\"login\" keychain. Open the certificate (it should be called something like \n\"Caddy Local Authority\") and configure it to \"Always Trust\", as shown below.\n\n\u003cp align=\"center\"\u003e\n    \u003ca\u003e\n    \u003cimg \n        src=\"./images/mac-keychain-access.png\" \n        alt=\"Trust Caddy Local Authority certificate\"\n        width=\"50%\"\u003e\n    \u003c/a\u003e\n    \u003cbr\u003e\n    \u003csub\u003e\u003csup\u003eTrust Caddy Local Authority certificate.\u003c/sup\u003e\u003c/sub\u003e\n\u003c/p\u003e\n\n\u003e [!TIP] \n\u003e Firefox has its own local trust store. You will be required to complete \none additional step.\n\nIn Firefox, type 'about:config' in the address bar. If prompted, accept any \nwarnings. Set \"security.enterprise_roots.enabled\" as true.\n\n\u003cp align=\"center\"\u003e\n    \u003ca\u003e\n    \u003cimg \n        src=\"./images/firefox-settings.png\" \n        alt=\"Firefox settings\"\n        width=\"50%\"\u003e\n    \u003c/a\u003e\n    \u003cbr\u003e\n    \u003csub\u003e\u003csup\u003eFirefox settings for local trust store.\u003c/sup\u003e\u003c/sub\u003e\n\u003c/p\u003e\n\n#### 6. \u003cins\u003eAttach Docker containers to Caddy network\u003c/ins\u003e\n\nOnce Caddy container is up and running, you will need to configure your Docker \ncontainers by attaching the **reverse_proxy** network to your container(s), \nassign a name to the container and expose the port that Caddy will proxy.\n\nI have outlined the necessary configuration below both for Docker Compose and \nDocker CLI approach.\n\n**Docker Compose**\n\nIn your Docker Compose file you need to define **reverse_proxy** as an external \nnetwork. For each services you want to access via Caddy reverse proxy, you will \nneed to add **reverse_proxy** as an attached network and define your exposed \nport.\n\nBelow I have provided an example of a Docker Compose file configured to match \nthe example site block in the Caddyfile.\n\n##### **Caddyfile**\n\n```ini\n# Personal website\nwebsite.local:80 {\n  reverse_proxy website_app:8080\n}\n```\n\n##### **Docker Compose**\n\n```yaml\nversion: '3.9'\n\nservices:\n  website:\n    # Container name should be the same as in the Caddyfile.\n    container_name: website_app\n    image: nginx:alpine\n    restart: unless-stopped\n    # Expose the mapped port that Caddy will proxy.\n    expose:\n      - 8080\n    # Add reverse_proxy as attached network.\n    networks:\n      - reverse_proxy\n    volumes:\n      - ./src:/usr/share/nginx/html\n\nnetworks:\n  # Add reverse_proxy as an external network.\n  reverse_proxy:\n    external: true\n```\n\n**Docker CLI**\n\nIf you don't use Docker Compose, I have included an example of Docker CLI to \nstart a container with the necessary configurations.\n\n```bash\n$ docker run --rm --name=website_app --expose 8080 --network=reverse_proxy nginx:alpine\n```\n\n## FAQ\n\n**Q:** Can I configure Caddy via the REST API?  \n**A:** Yes, You can access Caddy administration endpoints via HTTP by connect to \nhttp://localhost:2019. You can change the the API port in the DotEnv file.\n\n```ini\n#--------------------------------------------------------------------------\n# Network env\n#--------------------------------------------------------------------------\n\n# Map the Admin API port to the host port. | default: 2019\nADMIN_API_PORT=2019\n```\n\n**Q:** If I change the Caddyfile, do I need to restart the Docker container?  \n**A:** Yes, You will need to restart Caddy to allow the reverse proxy to reload \nchanges in your configuration. There are two commands you can use to restart \nCaddy.\n\nAccording to the Caddy Docker Hub page, Caddy comes with a `caddy reload` \ncommand. You can run the following command to reload Caddy configuration:\n\n```bash\n$ docker exec -w /etc/caddy docker-reverse-proxy caddy reload\n```\n\nThe working directory is set to `/etc/caddy` so Caddy can find your Caddyfile \nwithout additional arguments.\n\nAlternatively, you can restart the Docker container by using the following command.\n\n```bash\n$ docker-compose restart\n```\n\n## Useful Tips\n\n[VSCode Caddyfile Syntax](https://marketplace.visualstudio.com/items?itemName=zamerick.vscode-caddyfile-syntax) \nis an extension for VSCode that adds syntax highlighting for Caddyfiles.\n\n## Changelog\n\nPlease see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.\n\n## Contributing\n\nI encourage you to contribute to ***Docker Reverse Proxy***! Contributions are \nwhat make the open source community such an amazing place to be learn, inspire, \nand create. Any contributions you make are **greatly appreciated**.\n\nPlease check out the [contributing to Docker Reverse Proxy guide](.github/CONTRIBUTING.md) \nfor guidelines about how to \nproceed.\n\n## Security Vulnerabilities\n\nTrying to report a possible security vulnerability in ***Docker Reverse Proxy***? \nPlease check out our [security policy](.github/SECURITY.md) for guidelines \nabout how to proceed.\n\n## Credits\n\nThe illustration used in the project is from [unDraw (created by Katerina Limpitsouni)](https://undraw.co/). \nAll product names, logos, brands, trademarks and registered trademarks are \nproperty of their respective owners.\n\n## Sponsor\n\nDo you like this project? Support it by donating.\n\n\u003ca href=\"https://www.buymeacoffee.com/luisaveiro\"\u003e\n  \u003cimg src=\"./images/bmc-button.svg\" alt=\"Code Review\" width=\"144\"\u003e\n\u003c/a\u003e\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE) for more information.\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"http://github.com/luisaveiro\" target=\"_blank\"\u003eGitHub\u003c/a\u003e •\n  \u003ca href=\"https://uk.linkedin.com/in/luisaveiro\" target=\"_blank\"\u003eLinkedIn\u003c/a\u003e •\n  \u003ca href=\"https://twitter.com/luisdeaveiro\" target=\"_blank\"\u003eTwitter\u003c/a\u003e\n\u003c/p\u003e\n","funding_links":["https://github.com/sponsors/luisaveiro","https://www.buymeacoffee.com/luisaveiro"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluisaveiro%2Fdocker-reverse-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fluisaveiro%2Fdocker-reverse-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluisaveiro%2Fdocker-reverse-proxy/lists"}