{"id":13435800,"url":"https://github.com/lucaslorentz/caddy-docker-proxy","last_synced_at":"2025-05-12T15:24:14.418Z","repository":{"id":38802156,"uuid":"94173282","full_name":"lucaslorentz/caddy-docker-proxy","owner":"lucaslorentz","description":"Caddy as a reverse proxy for Docker","archived":false,"fork":false,"pushed_at":"2025-05-03T11:01:01.000Z","size":713,"stargazers_count":3552,"open_issues_count":76,"forks_count":188,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-05-12T15:24:13.930Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/lucaslorentz.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,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-06-13T05:37:13.000Z","updated_at":"2025-05-12T12:45:48.000Z","dependencies_parsed_at":"2023-12-27T11:24:34.715Z","dependency_job_id":"775aba49-3965-456f-90bb-4c928e262513","html_url":"https://github.com/lucaslorentz/caddy-docker-proxy","commit_stats":{"total_commits":316,"total_committers":35,"mean_commits":9.028571428571428,"dds":0.310126582278481,"last_synced_commit":"737c10db9bcd9d53e59f92a9362a5f32d511ebd3"},"previous_names":[],"tags_count":44,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucaslorentz%2Fcaddy-docker-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucaslorentz%2Fcaddy-docker-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucaslorentz%2Fcaddy-docker-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucaslorentz%2Fcaddy-docker-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lucaslorentz","download_url":"https://codeload.github.com/lucaslorentz/caddy-docker-proxy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253764179,"owners_count":21960528,"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-07-31T03:00:39.363Z","updated_at":"2025-05-12T15:24:14.401Z","avatar_url":"https://github.com/lucaslorentz.png","language":"Go","readme":"# Caddy-Docker-Proxy \n[![Build Status](https://dev.azure.com/lucaslorentzlara/lucaslorentzlara/_apis/build/status/lucaslorentz.caddy-docker-proxy?branchName=master)](https://dev.azure.com/lucaslorentzlara/lucaslorentzlara/_build/latest?definitionId=1) [![Go Report Card](https://goreportcard.com/badge/github.com/lucaslorentz/caddy-docker-proxy)](https://goreportcard.com/report/github.com/lucaslorentz/caddy-docker-proxy)\n\n## Introduction\nThis plugin enables Caddy to be used as a reverse proxy for Docker containers via labels.\n\n## How does it work?\nThe plugin scans Docker metadata, looking for labels indicating that the service or container should be served by Caddy.\n\nThen, it generates an in-memory Caddyfile with site entries and proxies pointing to each Docker service by their DNS name or container IP.\n\nEvery time a Docker object changes, the plugin updates the Caddyfile and triggers Caddy to gracefully reload, with zero-downtime.\n\n## Table of contents\n\n  * [Basic usage example, using docker-compose](#basic-usage-example-using-docker-compose)\n  * [Labels to Caddyfile conversion](#labels-to-caddyfile-conversion)\n    + [Tokens and arguments](#tokens-and-arguments)\n    + [Ordering and isolation](#ordering-and-isolation)\n    + [Sites, snippets and global options](#sites-snippets-and-global-options)\n    + [Go templates](#go-templates)\n  * [Template functions](#template-functions)\n    + [upstreams](#upstreams)\n  * [Examples](#examples)\n  * [Docker configs](#docker-configs)\n  * [Proxying services vs containers](#proxying-services-vs-containers)\n    + [Services](#services)\n    + [Containers](#containers)\n  * [Execution modes](#execution-modes)\n    + [Server](#server)\n    + [Controller](#controller)\n    + [Standalone (default)](#standalone-default)\n  * [Caddy CLI](#caddy-cli)\n  * [Docker images](#docker-images)\n    + [Choosing the version numbers](#choosing-the-version-numbers)\n    + [Chosing between default or alpine images](#chosing-between-default-or-alpine-images)\n    + [CI images](#ci-images)\n    + [ARM architecture images](#arm-architecture-images)\n    + [Windows images](#windows-images)\n    + [Custom images](#custom-images)\n  * [Connecting to Docker Host](#connecting-to-docker-host)\n  * [Volumes](#volumes)\n  * [Trying it](#trying-it)\n    + [With docker-compose file](#with-docker-compose-file)\n    + [With run commands](#with-run-commands)\n  * [Building it](#building-it)\n\n## Basic usage example, using docker-compose\n```shell\n$ docker network create caddy\n```\n\n`caddy/docker-compose.yml`\n```yml\nversion: \"3.7\"\nservices:\n  caddy:\n    image: lucaslorentz/caddy-docker-proxy:ci-alpine\n    ports:\n      - 80:80\n      - 443:443\n    environment:\n      - CADDY_INGRESS_NETWORKS=caddy\n    networks:\n      - caddy\n    volumes:\n      - /var/run/docker.sock:/var/run/docker.sock\n      - caddy_data:/data\n    restart: unless-stopped\n\nnetworks:\n  caddy:\n    external: true\n\nvolumes:\n  caddy_data: {}\n```\n```shell\n$ docker-compose up -d\n```\n\n`whoami/docker-compose.yml`\n```yml\nversion: '3.7'\nservices:\n  whoami:\n    image: traefik/whoami\n    networks:\n      - caddy\n    labels:\n      caddy: whoami.example.com\n      caddy.reverse_proxy: \"{{upstreams 80}}\"\n\nnetworks:\n  caddy:\n    external: true\n```\n```shell\n$ docker-compose up -d\n```\nNow, visit `https://whoami.example.com`. The site will be served [automatically over HTTPS](https://caddyserver.com/docs/automatic-https) with a certificate issued by Let's Encrypt or ZeroSSL.\n\t\t\n## Labels to Caddyfile conversion\nPlease first read the [Caddyfile Concepts](https://caddyserver.com/docs/caddyfile/concepts) documentation to understand the structure of a Caddyfile.\n\nAny label prefixed with `caddy` will be converted into a Caddyfile config, following these rules:\n\n### Tokens and arguments\n\nKeys are the directive name, and values are whitespace separated arguments:\n```\ncaddy.directive: arg1 arg2\n↓\n{\n\tdirective arg1 arg2\n}\n```\n\nIf you need whitespace or line-breaks inside one of the arguments, use double-quotes or backticks around it:\n```\ncaddy.respond: / \"Hello World\" 200\n↓\n{\n\trespond / \"Hello World\" 200\n}\n```\n```\ncaddy.respond: / `Hello\\nWorld` 200\n↓\n{\n\trespond / `Hello\nWorld` 200\n}\n```\n```\ncaddy.respond: |\n\t/ `Hello\n\tWorld` 200\n↓\n{\n\trespond / `Hello\nWorld` 200\n}\n```\n\nDots represent nesting, and grouping is done automatically:\n```\ncaddy.directive: argA  \ncaddy.directive.subdirA: valueA  \ncaddy.directive.subdirB: valueB1 valueB2\n↓\n{\n\tdirective argA {  \n\t\tsubdirA valueA  \n\t\tsubdirB valueB1 valueB2  \n\t}\n}\n```\n\nArguments for the parent directive are optional (e.g. no arguments to `directive`, setting subdirective `subdirA` directly):\n```\ncaddy.directive.subdirA: valueA\n↓\n{\n\tdirective {\n\t\tsubdirA valueA\n\t}\n}\n```\n\nLabels with empty values generate a directive without any arguments:\n```\ncaddy.directive:\n↓\n{\n\tdirective\n}\n```\n\n### Ordering and isolation\n\nBe aware that directives are subject to be sorted according to the default [directive order](https://caddyserver.com/docs/caddyfile/directives#directive-order) defined by Caddy, when the Caddyfile is parsed (after the Caddyfile is generated from labels).\n\n[Directives](https://caddyserver.com/docs/caddyfile/directives) from labels are ordered alphabetically by default:\n```\ncaddy.bbb: value\ncaddy.aaa: value\n↓\n{\n\taaa value \n\tbbb value\n}\n```\n\nSuffix _\u0026lt;number\u0026gt; isolates directives that otherwise would be grouped:\n```\ncaddy.route_0.a: value\ncaddy.route_1.b: value\n↓\n{\n\troute {\n\t\ta value\n\t}\n\troute {\n\t\tb value\n\t}\n}\n```\n\nPrefix \u0026lt;number\u0026gt;_ isolates directives but also defines a custom ordering for directives (mainly relevant within [`route`](https://caddyserver.com/docs/caddyfile/directives/route) blocks), and directives without order prefix will go last:\n```\ncaddy.1_bbb: value\ncaddy.2_aaa: value\ncaddy.3_aaa: value\n↓\n{\n\tbbb value\n\taaa value\n\taaa value\n}\n```\n\n### Sites, snippets and global options\n\nA label `caddy` creates a [site block](https://caddyserver.com/docs/caddyfile/concepts):\n```\ncaddy: example.com\ncaddy.respond: \"Hello World\" 200\n↓\nexample.com {\n\trespond \"Hello World\" 200\n}\n```\n\nOr a [snippet](https://caddyserver.com/docs/caddyfile/concepts#snippets):\n```\ncaddy: (encode)\ncaddy.encode: zstd gzip\n↓\n(encode) {\n\tencode zstd gzip\n}\n```\n\nIt's also possible to isolate Caddy configurations using suffix _\u0026lt;number\u0026gt;:\n```\ncaddy_0: (snippet)\ncaddy_0.tls: internal\ncaddy_1: site-a.com\ncaddy_1.import: snippet\ncaddy_2: site-b.com\ncaddy_2.import: snippet\n↓\n(snippet) {\n\ttls internal\n}\nsite_a {\n\timport snippet\n}\nsite_b {\n\timport snippet\n}\n```\n\n[Global options](https://caddyserver.com/docs/caddyfile/options) can be defined by not setting any value for `caddy`. They can be set in any container/service, including caddy-docker-proxy itself. [Here is an example](examples/standalone.yaml#L19)\n```\ncaddy.email: you@example.com\n↓\n{\n\temail you@example.com\n}\n```\n\n[Named matchers](https://caddyserver.com/docs/caddyfile/matchers#named-matchers) can be created using `@` inside labels:\n```\ncaddy: localhost\ncaddy.@match.path: /sourcepath /sourcepath/*\ncaddy.reverse_proxy: @match localhost:6001\n↓\nlocalhost {\n\t@match {\n\t\tpath /sourcepath /sourcepath/*\n\t}\n\treverse_proxy @match localhost:6001\n}\n```\n\n### Go templates\n\n[Golang templates](https://golang.org/pkg/text/template/) can be used inside label values to increase flexibility. From templates, you have access to current Docker resource information. But, keep in mind that the structure that describes a Docker container is different from a service.\n\nWhile you can access a service name like this:\n```\ncaddy.respond: /info \"{{.Spec.Name}}\"\n↓\nrespond /info \"myservice\"\n```\n\nThe equivalent to access a container name would be:\n```\ncaddy.respond: /info \"{{index .Names 0}}\"\n↓\nrespond /info \"mycontainer\"\n```\n\nSometimes it's not possile to have labels with empty values, like when using some UI to manage Docker. If that's the case, you can also use our support for go lang templates to generate empty labels.\n```\ncaddy.directive: {{\"\"}}\n↓\ndirective\n```\n\n## Template functions\n\nThe following functions are available for use inside templates:\n\n### upstreams\n\nReturns all addresses for the current Docker resource separated by whitespace.\n\nFor services, that would be the service DNS name when **proxy-service-tasks** is **false**, or all running tasks IPs when **proxy-service-tasks** is **true**.\n\nFor containers, that would be the container IPs.\n\nOnly containers/services that are connected to Caddy ingress networks are used.\n\n:warning: caddy docker proxy does a best effort to automatically detect what are the ingress networks. But that logic fails on some scenarios: [#207](https://github.com/lucaslorentz/caddy-docker-proxy/issues/207). To have a more resilient solution, you can manually configure Caddy ingress network using CLI option `ingress-networks`, environment variable `CADDY_INGRESS_NETWORKS`. You can also specify the ingress network per container/service by adding to it a label `caddy_ingress_network` with the network name.\n\nUsage: `upstreams [http|https] [port]`  \n\nExamples:\n```\ncaddy.reverse_proxy: {{upstreams}}\n↓\nreverse_proxy 192.168.0.1 192.168.0.2\n```\n```\ncaddy.reverse_proxy: {{upstreams https}}\n↓\nreverse_proxy https://192.168.0.1 https://192.168.0.2\n```\n```\ncaddy.reverse_proxy: {{upstreams 8080}}\n↓\nreverse_proxy 192.168.0.1:8080 192.168.0.2:8080\n```\n```\ncaddy.reverse_proxy: {{upstreams http 8080}}\n↓\nreverse_proxy http://192.168.0.1:8080 http://192.168.0.2:8080\n```\n\n:warning: Be carefull with quotes around upstreams. Quotes should only be added when using yaml. \n```\ncaddy.reverse_proxy: \"{{upstreams}}\"\n↓\nreverse_proxy \"192.168.0.1 192.168.0.2\"\n```\n\n## Examples\nProxying all requests to a domain to the container\n```yml\ncaddy: example.com\ncaddy.reverse_proxy: {{upstreams}}\n```\n\nProxying all requests to a domain to a subpath in the container\n```yml\ncaddy: example.com\ncaddy.rewrite: * /target{path}\ncaddy.reverse_proxy: {{upstreams}}\n```\n\nProxying requests matching a path, while stripping that path prefix\n```yml\ncaddy: example.com\ncaddy.handle_path: /source/*\ncaddy.handle_path.0_reverse_proxy: {{upstreams}}\n```\n\nProxying requests matching a path, rewriting to different path prefix\n```yml\ncaddy: example.com\ncaddy.handle_path: /source/*\ncaddy.handle_path.0_rewrite: * /target{uri}\ncaddy.handle_path.1_reverse_proxy: {{upstreams}}\n```\n\nProxying all websocket requests, and all requests to `/api*`, to the container\n```yml\ncaddy: example.com\ncaddy.@ws.0_header: Connection *Upgrade*\ncaddy.@ws.1_header: Upgrade websocket\ncaddy.0_reverse_proxy: @ws {{upstreams}}\ncaddy.1_reverse_proxy: /api* {{upstreams}}\n```\n\nProxying multiple domains, with certificates for each\n```yml\ncaddy: example.com, example.org, www.example.com, www.example.org\ncaddy.reverse_proxy: {{upstreams}}\n```\n\n**More community-maintained examples are available in the [Wiki](https://github.com/lucaslorentz/caddy-docker-proxy/wiki).**\n\n## Docker configs\n\n\u003e Note: This is for Docker Swarm only. Alternatively, use `CADDY_DOCKER_CADDYFILE_PATH` or `-caddyfile-path`\n\nYou can also add raw text to your Caddyfile using Docker configs. Just add Caddy label prefix to your configs and the whole config content will be inserted at the beginning of the generated Caddyfile, outside any server blocks.\n\n[Here is an example](examples/standalone.yaml#L4)\n\n## Proxying services vs containers\nCaddy docker proxy is able to proxy to swarm services or raw containers. Both features are always enabled, and what will differentiate the proxy target is where you define your labels.\n\n### Services\nTo proxy swarm services, labels should be defined at service level. In a docker-compose file, labels should be _inside_ `deploy`, like:\n```yml\nservices:\n  foo:\n    deploy:\n      labels:\n        caddy: service.example.com\n        caddy.reverse_proxy: {{upstreams}}\n```\n\nCaddy will use service DNS name as target or all service tasks IPs, depending on configuration **proxy-service-tasks**.\n\n### Containers\nTo proxy containers, labels should be defined at container level. In a docker-compose file, labels should be _outside_ `deploy`, like:\n```yml\nservices:\n  foo:\n    labels:\n      caddy: service.example.com\n      caddy.reverse_proxy: {{upstreams}}\n```\n\n## Execution modes\n\nEach caddy docker proxy instance can be executed in one of the following modes.\n\n### Server\n\nActs as a proxy to your Docker resources. The server starts without any configuration, and will not serve anything until it is configured by a \"controller\".\n\nIn order to make a server discoverable and configurable by controllers, you need to mark it with label `caddy_controlled_server` and define the controller network via CLI option `controller-network` or environment variable `CADDY_CONTROLLER_NETWORK`.\n\nServer instances doesn't need access to Docker host socket and you can run it in manager or worker nodes.\n\n[Configuration example](examples/distributed.yaml#L5)\n\n### Controller\n\nController monitors your Docker cluster, generates Caddy configuration, and pushes it to all servers it finds in your Docker cluster.\n\nWhen controller instances are connected to more than one network, it is also necessary to define the controller network via CLI option `controller-network` or environment variable `CADDY_CONTROLLER_NETWORK`.\n\nController instances require access to Docker host socket.\n\nA single controller instance can configure all server instances in your cluster.\n\n**:warning: Controller mode requires server nodes to serve traffic.**\n\n[Configuration example](examples/distributed.yaml#L21)\n\n### Standalone (default)\n\nThis mode executes a controller and a server in the same instance and doesn't require additional configuration.\n\n[Configuration example](examples/standalone.yaml#L11)\n\n## Caddy CLI\n\nThis plugin extends caddy's CLI with the command `caddy docker-proxy`.\n\nRun `caddy help docker-proxy` to see all available flags.\n\n```\nUsage of docker-proxy:\n  --caddyfile-path string\n        Path to a base Caddyfile that will be extended with Docker sites\n  --envfile\n        Path to an environment file with environment variables in the KEY=VALUE format to load into the Caddy process\n  --controller-network string\n        Network allowed to configure Caddy server in CIDR notation. Ex: 10.200.200.0/24\n  --ingress-networks string\n        Comma separated name of ingress networks connecting Caddy servers to containers.\n        When not defined, networks attached to controller container are considered ingress networks\n  --docker-sockets\n        Comma separated docker sockets\n        When not defined, DOCKER_HOST (or default docker socket if DOCKER_HOST not defined)\n  --docker-certs-path\n        Comma separated cert path, you could use empty value when no cert path for the concern index docker socket like cert_path0,,cert_path2\n  --docker-apis-version\n        Comma separated apis version, you could use empty value when no api version for the concern index docker socket like cert_path0,,cert_path2\n  --label-prefix string\n        Prefix for Docker labels (default \"caddy\")\n  --mode\n        Which mode this instance should run: standalone | controller | server\n  --polling-interval duration\n        Interval Caddy should manually check Docker for a new Caddyfile (default 30s)\n  --event-throttle-interval duration\n        Interval to throttle caddyfile updates triggered by docker events (default 100ms)\n  --process-caddyfile\n        Process Caddyfile before loading it, removing invalid servers (default true)\n  --proxy-service-tasks\n        Proxy to service tasks instead of service load balancer (default true)\n  --scan-stopped-containers\n        Scan stopped containers and use their labels for Caddyfile generation (default false)\n```\n\nThose flags can also be set via environment variables:\n\n```\nCADDY_DOCKER_CADDYFILE_PATH=\u003cstring\u003e\nCADDY_DOCKER_ENVFILE=\u003cstring\u003e\nCADDY_CONTROLLER_NETWORK=\u003cstring\u003e\nCADDY_INGRESS_NETWORKS=\u003cstring\u003e\nCADDY_DOCKER_SOCKETS=\u003cstring\u003e\nCADDY_DOCKER_CERTS_PATH=\u003cstring\u003e\nCADDY_DOCKER_APIS_VERSION=\u003cstring\u003e\nCADDY_DOCKER_LABEL_PREFIX=\u003cstring\u003e\nCADDY_DOCKER_MODE=\u003cstring\u003e\nCADDY_DOCKER_POLLING_INTERVAL=\u003cduration\u003e\nCADDY_DOCKER_PROCESS_CADDYFILE=\u003cbool\u003e\nCADDY_DOCKER_PROXY_SERVICE_TASKS=\u003cbool\u003e\nCADDY_DOCKER_SCAN_STOPPED_CONTAINERS=\u003cbool\u003e\nCADDY_DOCKER_NO_SCOPE=\u003cbool, default scope used\u003e\n```\n\nCheck **examples** folder to see how to set them on a Docker Compose file.\n\n## Docker images\nDocker images are available at Docker hub:\nhttps://hub.docker.com/r/lucaslorentz/caddy-docker-proxy/\n\n### Choosing the version numbers\nThe safest approach is to use a full version numbers like 0.1.3.\nThat way you lock to a specific build version that works well for you.\n\nBut you can also use partial version numbers like 0.1. That means you will receive the most recent 0.1.x image. You will automatically receive updates without breaking changes.\n\n### Chosing between default or alpine images\nOur default images are very small and safe because they only contain Caddy executable.\nBut they're also quite hard to troubleshoot because they don't have shell or any other Linux utilities like curl or dig.\n\nThe alpine images variant are based on the Linux Alpine image, a very small Linux distribution with shell and basic utilities tools. Use `-alpine` images if you want to trade security and small size for a better troubleshooting experience.\n\n### CI images\nImages with the `ci` tag suffix means they were automatically generated by automated builds.\nCI images reflect the current state of master branch and their stability is not guaranteed.\nYou may use CI images if you want to help testing the latest features before they're officially released.\n\n### ARM architecture images\nCurrently we provide linux x86_64 images by default.\n\nYou can also find images for other architectures like `arm32v6` images that can be used on Raspberry Pi.\n\n### Windows images\nWe recently introduced experimental windows containers images with the tag suffix `nanoserver-ltsc2022`.\n\nBe aware that this needs to be tested further.\n\nThis is an example of how to mount the windows Docker pipe using CLI:\n```shell\n$ docker run --rm -it -v //./pipe/docker_engine://./pipe/docker_engine lucaslorentz/caddy-docker-proxy:ci-nanoserver-ltsc2022\n```\n\n### Custom images\nIf you need additional Caddy plugins, or need to use a specific version of Caddy, then you may use the `builder` variant of the [official Caddy Docker image](https://hub.docker.com/_/caddy) to make your own `Dockerfile`.\n\nThe main difference from the instructions on the official image is that you must override `CMD` to have the container run using the `caddy docker-proxy` command provided by this plugin.\n\n```Dockerfile\nARG CADDY_VERSION=2.6.1\nFROM caddy:${CADDY_VERSION}-builder AS builder\n\nRUN xcaddy build \\\n    --with github.com/lucaslorentz/caddy-docker-proxy/v2 \\\n    --with \u003cadditional-plugins\u003e\n\nFROM caddy:${CADDY_VERSION}-alpine\n\nCOPY --from=builder /usr/bin/caddy /usr/bin/caddy\n\nCMD [\"caddy\", \"docker-proxy\"]\n```\n\n## Connecting to Docker Host\nThe default connection to Docker host varies per platform:\n* At Unix: `unix:///var/run/docker.sock`\n* At Windows: `npipe:////./pipe/docker_engine`\n\nYou can modify Docker connection using the following environment variables:\n\n* **DOCKER_HOST**: to set the URL to the Docker server.\n* **DOCKER_API_VERSION**: to set the version of the API to reach, leave empty for latest.\n* **DOCKER_CERT_PATH**: to load the TLS certificates from.\n* **DOCKER_TLS_VERIFY**: to enable or disable TLS verification; off by default.\n\n## Volumes\nOn a production Docker swarm cluster, it's **very important** to store Caddy folder on persistent storage. Otherwise Caddy will re-issue certificates every time it is restarted, exceeding Let's Encrypt's quota.\n\nTo do that, map a persistent Docker volume to `/data` folder.\n\nFor resilient production deployments, use multiple Caddy replicas and map `/data` folder to a volume that supports multiple mounts, like Network File Sharing Docker volumes plugins.\n\nMultiple Caddy instances automatically orchestrate certificate issuing between themselves when sharing `/data` folder.\n\n## Trying it\n\n### With docker-compose file\n\nClone this repository.\n\nDeploy the compose file to swarm cluster:\n```\n$ docker stack deploy -c examples/standalone.yaml caddy-docker-demo\n```\n\nWait a bit for services to startup...\n\nNow you can access each service/container using different URLs\n```\n$ curl -k --resolve whoami0.example.com:443:127.0.0.1 https://whoami0.example.com\n$ curl -k --resolve whoami1.example.com:443:127.0.0.1 https://whoami1.example.com\n$ curl -k --resolve whoami2.example.com:443:127.0.0.1 https://whoami2.example.com\n$ curl -k --resolve whoami3.example.com:443:127.0.0.1 https://whoami3.example.com\n$ curl -k --resolve config.example.com:443:127.0.0.1 https://config.example.com\n$ curl -k --resolve echo0.example.com:443:127.0.0.1 https://echo0.example.com/sourcepath/something\n```\n\nAfter testing, delete the demo stack:\n```\n$ docker stack rm caddy-docker-demo\n```\n\n### With run commands\n\n```\n$ docker run --name caddy -d -p 443:443 -v /var/run/docker.sock:/var/run/docker.sock lucaslorentz/caddy-docker-proxy:ci-alpine\n\n$ docker run --name whoami0 -d -l caddy=whoami0.example.com -l \"caddy.reverse_proxy={{upstreams 80}}\" -l caddy.tls=internal traefik/whoami\n\n$ docker run --name whoami1 -d -l caddy=whoami1.example.com -l \"caddy.reverse_proxy={{upstreams 80}}\" -l caddy.tls=internal traefik/whoami\n\n$ curl -k --resolve whoami0.example.com:443:127.0.0.1 https://whoami0.example.com\n$ curl -k --resolve whoami1.example.com:443:127.0.0.1 https://whoami1.example.com\n\n$ docker rm -f caddy whoami0 whoami1\n```\n\n## Building it\n\nYou can build Caddy using [xcaddy](https://github.com/caddyserver/xcaddy) or [caddy docker builder](https://hub.docker.com/_/caddy).\n\nUse module name **github.com/lucaslorentz/caddy-docker-proxy/v2** to add this plugin to your build.\n","funding_links":[],"categories":["HarmonyOS","Go","Community Tools","others","Container Operations"],"sub_categories":["Windows Manager","Networking","Reverse Proxy"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucaslorentz%2Fcaddy-docker-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flucaslorentz%2Fcaddy-docker-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucaslorentz%2Fcaddy-docker-proxy/lists"}