Below is probably way more verbose than it needs to be, and as @francislavoie suggests you probably can connect directly.
If you do need to route through Caddy such as for centralizing TLS, you can do so with a network alias for a service as shown below.
If you are having weird networking issues because of indirect connections (host IP / public DNS instead of direct container DNS), you may want to look over this reference table for docker network caveats.
Docker networks and container DNS records
Docker Compose will create a custom network (equivalent to docker network create
) for each compose.yaml
, and docker run
will always start containers on the legacy docker bridge network (which has slightly different functionality, this network is discouraged vs custom networks).
If all your service containers are on the same network, they can reach each other by their service name in compose.yaml
, their container_name
if assigned, or their hostname
too. You can also use links
, extra_hosts
, external_links
, or the more useful one networks.<network-name-here>.aliases
.
Compose will define the default network created for each compose.yaml
as default
internally, while the external name that is used can be found under docker network ls
if you need to reference it. Alternatively you can add your own networks with a custom external name, and you can override the default one Compose generates by using the default
network name.
Network alias
Now that we’ve clarified all that. When you want Gitea to connect to Authentik, it’s as simple as referencing any of the various sources mentioned above for valid DNS names to resolve (which the default embedded DNS that Docker provides will handle for you).
If you want traffic to route through Caddy for that service instead of a direct connection, just like you would without containers or were connecting via the browser, then network aliases are perfect for this.
You may only need this for Authentik btw. If you do need a separate FQDN like I did, your Caddyfile will also need to reference the alias as another site-address along with cert provisioned.
Here’s a rough example:
services:
reverse-proxy:
image: caddy:2.8
container_name: caddy
# If also wanting to reach from the host via `https://example.localhost`
ports:
- "127.0.0.1:80:80"
- "127.0.0.1:443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
# Containers on this network will resolve these aliases to the IP of this container:
networks:
default:
aliases:
- auth.example.test
Basic Caddyfile example:
{
local_certs
}
# Auth service:
# I have two different TLDs here, neither is publicly resolvable:
# - `.localhost` for host / browser requires no custom DNS or /etc/hosts config
# - `.test` for containers DNS since they cannot use `.localhost`
# These both use the same cert, if you have LetsEncrypt for public but
# internal CA for non-public domains like `.test` you'd need separate site blocks?
auth.example.localhost, auth.example.test {
reverse_proxy authelia:80
}
# Standard service like your gitea:
my-service-a.example.localhost {
reverse_proxy my-service-a:80
}
# Forward auth example to require Authelia for login to access this service
my-service-b.example.localhost {
forward_auth authelia:80 {
uri /api/authz/forward-auth
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
}
# After forward auth is successful, continues to intended service:
reverse_proxy my-service-b:80
}
Nothing really special going on there in the Caddyfile, but note how I adjusted the site block for Authelia to recognize the Compose network alias added for Caddy. You can probably use the same custom TLD that you already have, mine was a workaround for .localhost
usage on the host.
The distinction was helpful when I was learning about IdP integration as your services like gitea may be configured with both if they differ. Here’s an example for Roundcube:
// Browser URL related:
$config['oauth_auth_uri'] = 'https://auth.example.localhost/api/oidc/authorization';
// Internal only:
$config['oauth_token_uri'] = 'https://auth.example.test/api/oidc/token';
$config['oauth_identity_uri'] = 'https://auth.example.test/api/oidc/userinfo';
You could get it working without Caddy and do a direct container connection, some IdP are more strict however and it can be more convenient to centralize traffic + TLS through Caddy this way.