Configuring routes and domains
-
Routes
- HTTP versus TCP routes
- Internal container-to-container routes
- Create a route
- List routes
- View a route
- Check routes
- Map a route to your app
- Unmap a route
- Share a route with another space
- Transfer ownership of a route to another space
- Delete a route
- Routing requests to a specific app instance
- Routing requests to a specific process instance
- Domains
Page last updated:
Developers and administrators can configure routes and domains for their apps using the Cloud Foundry Command Line Interface (cf CLI). This topic describes how routes and domains work in Cloud Foundry (Cloud Foundry). For more information about routing capabilities in Cloud Foundry, see HTTP routing.
Routes
The Cloud Foundry Gorouter routes requests to apps by associating an app with an address, known as a route. This is known as a mapping.
Use the cf CLI cf map-route command to associate an app and route.
The routing tier compares each request with a list of all the routes mapped to apps and attempts to find the best match. For example, the Gorouter makes the following matches for the two routes example-app.scapp.io and example-app.scapp.io/products:
| Request | Matched Route |
|---|---|
http://example-app.scapp.io |
example-app.scapp.io |
http://example-app.scapp.io/contact |
example-app.scapp.io |
http://example-app.scapp.io/products |
example-app.scapp.io/products |
http://example-app.scapp.io/products/123 |
example-app.scapp.io/products |
http://products.scapp.io |
No match; 404 |
The Gorouter does not use a route to match requests until the route is mapped to an app. In the example, products.scapp.io might have been created as a route in Cloud Foundry, but until it is mapped to an app, requests for the route receive a 404 error.
The routing tier knows the location of instances for apps mapped to routes. After the routing tier calculates a route as the best match for a request, it makes a load-balancing calculation using the configured balancing algorithm (by default, this is round-robin), and forwards the request to an instance of the mapped app.
Developers can map many apps to a single route, resulting in load-balanced requests for the route across all instances of all mapped apps. This approach activates the blue/green rolling deployment strategy. Developers can also map an individual app to multiple routes, enabling access to the app from many URLs. The number of routes that can be mapped to each app is approximately 1000 (128 KB).
Routes belong to a space, and developers can only map apps to a route created in or shared with the same space. For more information about sharing routes across spaces, see Share a route with another space .
Routes are globally unique. Developers in one space cannot create a route with the same URL as developers in another space, regardless of which orgs control these spaces.
HTTP versus TCP routes
By default, Cloud Foundry only supports routing of HTTP requests to apps.
Routes are considered HTTP if they are created from HTTP domains, and TCP if they are created from TCP domains. For more information, see HTTP versus TCP shared domains.
HTTP routes include a domain, a host name (optional), and a context path (optional). scapp.io, example-app.scapp.io, and example-app.scapp.io/products are all examples of HTTP routes. Apps listen to the localhost port defined by the $PORT environment variable, which is 8080 on Diego. For example, requests to example-app.scapp.io are routed to the application container at localhost:8080.
Requests to HTTP routes must be sent to ports 80 or 443. Ports cannot be reserved for HTTP routes. You can update the ports on which an app can receive requests through the Cloud Controller API. For more information, see Configuring apps to listen on custom ports (Beta).
TCP routes include a domain and a route port. A route port is the port clients make requests to. This is not the same port as what an app pushed to Cloud Foundry listens on. tcp.shared-domain.example.com:60000 is an example of a TCP route. Just as for HTTP routes, apps listen to the localhost port defined by the $PORT environment variable, which is 8080 on Diego. For example, requests to tcp.shared-domain.example.com:60000 are routed to the application container at localhost:8080.
When a port is reserved for a route, it cannot be reserved for another route. Host name and path are not supported for TCP routes.
Internal container-to-container routes
Cloud Foundry apps can communicate with each other securely and directly over internal routes that never leave the platform. Apps running on Windows cells cannot use internal, container-to-container routes.
To create an internal route:
Use the cf map-route command with an internal domain. For example:
$ cf map-route app apps.internal --hostname app- After an internal route is mapped to an app, the route resolves to IP addresses of the app instances. The IP addresses are visible in the application container:
$ cf ssh app vcap@1234:~$ host app.apps.internal app.apps.internal has address 10.255.169.200 app.apps.internal has address 10.255.49.7 app.apps.internal has address 10.255.49.77 - To resolve individual instances, prepend the index to the internal route.
vcap@1234:~$ host 1.app.apps.internal 1.app.apps.internal has address 10.255.49.7
- After an internal route is mapped to an app, the route resolves to IP addresses of the app instances. The IP addresses are visible in the application container:
Create a network policy that allows your apps to communicate with each other. By default, apps cannot communicate over the container network. For more information, see Configuring container-to-container networking, or enter
cf add-network-policy --help.
Create a route
When a developer creates a route using the cf CLI, Cloud Foundry determines whether the route is an HTTP or a TCP route based on the domain. To create a HTTP route, a developer must choose an HTTP domain. To create a TCP route, a developer must choose a TCP domain.
Domains in Cloud Foundry provide a namespace from which to create routes. To list available domains for a targeted organization, use the cf domains command. For more information about domains, see Domains.
The following sections describe how developers can create HTTP and TCP routes for different use cases.
Create an HTTP route with host name
In Cloud Foundry, a host name is the label that indicates a subdomain of the domain associated with the route.
Given a domain
scapp.io, a developer can create the route example-app.scapp.io by specifying the host name example-app with the
cf create-route command as shown in this example:
$ cf create-route shared-domain.example.com --hostname example-app
Creating route example-app.shared-domain.example.com for org example-org / space example-space as username<span>@</span>example.com...
OK
The cf CLI create-route command does not require the space as an argument. It uses the space you are targeting.
http://example-app.scapp.iohttps://example-app.scapp.io- Any path under either of the these URLs, such as
http://example-app.scapp.io/bar
Create an HTTP route without host name
This approach creates a route with the same address as the domain itself and is permitted for private domains only. For more information, see Private Domains.A developer can create a route from the domain
private-domain.example.com with no host name with the cf create-route command:
$ cf create-route private-domain.example.com
Creating route private-domain.example.com for org example-org / space example-space as username@example.com...
OK
If DNS is configured correctly, this command instructs Cloud Foundry to route requests to apps mapped to this route from these URLs:
http://private-domain.example.comhttps://private-domain.example.comAny path under either of these URLs, such as `http://private-domain.example.com/foo
http://foo.private-domain.example.com, fail.
A developer can also create routes for subdomains with no host names. The following command creates a route from the subdomain
foo.private-domain.example.com:
$ cf create-route foo.private-domain.example.com
Creating route foo.private-domain.example.com for org example-org / space example-space as username@example.com...
OK
If DNS is configured for this subdomain, this command instructs Cloud Foundry to route requests to apps mapped to this route from these URLs:
http://foo.private-domain.example.comhttps://foo.private-domain.example.com- Any path under either of these URLs, such as
http://foo.private-domain.example.com/foo
Create an HTTP route with wildcard host name
An app mapped to a wildcard route acts as a fallback app for route requests if the requested route does not exist. To create a wildcard route, use an asterisk for the host name.A developer can create a wildcard route from the domain `foo.scapp.io` by running:
$ cf create-route foo.scapp.io --hostname '*'
Creating route *.foo.scapp.io for org example-org / space example-space as username@example.com...
OK
If a client sends a request to http://app.foo.scapp.io by accident, attempting to reach example-app.foo.scapp.io,
Cloud Foundry routes the request to the app mapped to the route *.foo.scapp.io.
Create an HTTP route with a path
Developers can use paths to route requests for the same host name and domain to different apps.A developer can create three routes using the same host name and domain in the space `example-space` by running:
$ cf create-route scapp.io --hostname store --path products
Creating route store.scapp.io/products for org example-org / space example-space as username@example.com...
OK
$ cf create-route scapp.io --hostname store --path orders
Creating route store.scapp.io/orders for org example-org / space example-space as username@example.com...
OK
$ cf create-route scapp.io --hostname store
Creating route store.scapp.io for org example-org / space example-space as username@example.com...
OK
The developer can then map the new routes to different apps by following the procedure in
Map a route to your app.
If the developer maps the first route with path products to the products app, the second route with path orders to the orders app, and the last route to the storefront app. After this:
- Cloud Foundry routes requests to
http://store.scapp.io/productsto theproductsapp. - Cloud Foundry routes requests to
http://store.scapp.io/ordersto theordersapp. - Cloud Foundry routes requests to
http://store.scapp.ioto thestorefrontapp.
- Routes with the same domain and host name but different paths can only be created in the same space. Private domains do not have this limitation.
- Cloud Foundry does not route requests for context paths to the root context of an app. Apps must serve requests on the context path.
Create a TCP route with a port
A developer can create a TCP route for `tcp-domain.example.com` on an arbitrary port. This is the default in the cf CLI. * An arbitrary (random) port is the default. The `–random port` flag is not supported. “`console $ cf create-route example-space tcp-domain.example.com –random-port Creating route tcp-domain.example.com for org example-org / space example-space as user@example.com… OK Route tcp-domain.example.com:60034 has been created ”` In this example, Cloud Foundry routes requests to `tcp-domain.example.com:60034` to apps mapped to this route. To request a specific port, a developer can use the `–port` flag, so long as the port is not reserved for another space. To create a TCP route for `tcp-domain.example.com` on port 60035, run: “`console $ cf create-route example-space tcp-domain.example.com –port 60035 Creating route tcp-domain.example.com:60035 for org example-org / space example-space as user@example.com… OK ”` ### List routes Developers can list routes for the current space with the `cf routes` command. A route is uniquely identified by the combination of host name, domain, port, and path. “`console $ cf routes Getting routes as user@private-domain.example.com … space host domain type apps example-space example-app scapp.io example-app example-space example-app private-domain.example.com example-app example-space store scapp.io products example-space store scapp.io orders example-space store scapp.io storefront example-space scapp.io tcp tcp-app ”` Developers can only see routes in spaces where they are a member. ### View a route Developers can view a route and its destinations within the current space with thecf route command. A route is uniquely identified by the combination of a host name, domain, port, and path.
Note that the `cf route` command is available in cf CLI v8 only.
“`console
$ cf route scapp.io –hostname example-app
Showing route example-app.scapp.io in org o / space example-space as admin…
domain: scapp.io
host: example-app
port:
path:
protocol: http
Destinations:
app process port protocol
mystore web 8080 http1
”`
Developers can only view a route within a space where they are a member.
### Check routes
Developers cannot create a route that is already taken. To find out if a route is available, developers can use the
`cf check-route` command.
To find out if a route with the host name `store` and the domain `scapp.io` and the path `products` exists, run:
“`console
$ cf check-route scapp.io –hostname store –path /products
Checking for route…
OK
Route store.scapp.io/products does exist
”`
### Map a route to your app
For an app to receive requests to a route, developers must map the route to the app with the `cf map-route` command. If the route does not already exist, this command creates it.
Any app that is not routed to port 80 or port 443 must be explicitly mapped using the cf map-route command. Otherwise, the route is mapped to port 443.
You can create and reserve routes for later use by following the procedure in [Manually map a route](#map-route-manually). You can also map routes to their app immediately as part of a push. See [Map a route with app push](#map-route-on-push).
Changes to route mappings are run asynchronously. On startup, an app becomes accessible at its route within a few seconds. Similarly, upon mapping a new route to a running app, the app becomes accessible at this route within a few seconds of the CLI exiting.
Manually map a route
For these routes and apps:| Route | Apps |
|---|---|
| store.scapp.io/products | products |
| store.scapp.io/orders | orders |
| store.scapp.io | storefront |
| tcp-domain.example.com:60000 | tcp-app |
Map a route with app push
Developers can map a route to their app with the `cf push` command. The best way to do this is by using the `routes` property in the manifest. “`console $ cf push example-app ”` To customize the route during `push`, specify the domain using the `-d` flag and the host name with the `–hostname` flag. The following command creates the `foo.private-domain.example.com` route for `example-app`: “`console $ cf push example-app -d private-domain.example.com –hostname foo ”` To map a TCP route during `push`, specify a TCP domain and request a random port using `–random-route`. To specify a port, push the app without a route, then create and map the route manually by following the procedure in [Create a TCP route with a port](#create-route-w-port). “`console $ cf push tcp-app -d tcp-domain.example.com –random-route ”`Map a route using app manifest
Developers can map a route to their app with a manifest by editing the `route` attribute to specify the host, domain, port, and path components of the route. For more information, see [Deploying with app manifests](../deploy-apps/manifest.html#routes).Map a route to multiple apps
Cloud Foundry allows multiple apps, or versions of the same app, to be mapped to the same route. This feature activates blue-green deployment. For more information see Using blue-green deployment to reduce downtime and risk.
Routing multiple apps to the same route might cause undesirable behavior in some situations by routing incoming requests randomly to one of the apps on the shared route.
For more information about troubleshooting this problem, see [Routing conflict](troubleshoot-app-health.html#routing-conflict) in _Troubleshooting app deployment and health_.Map multiple routes to one app
You can have multiple routes to an app, but those routes cannot have different context paths. These routes are valid for a single app:| Route 1 | Route 2 |
|---|---|
example-app.example.com |
example-app.apps.cf.example.com |
example-app.example.com/foo |
example-app.apps.cf.example.com/foo |
| Route 1 | Route 2 |
|---|---|
example-app.example.com/foo |
example-app.apps.cf.example.com/bar |
example-app.apps.cf.example.com/foo |
example-app.example.com/bar |
Map an internal route to an app
You can map an internal route to any app. This internal route allows your app to communicate with other apps without leaving the platform. After it is mapped, this route becomes available to all other apps on the platform. This example creates a `foo.apps.internal` internal route for `example-app`: “`console $ cf map-route example-app apps.internal –hostname foo ”` ### Unmap a route Developers can remove a route from an app using the `cf unmap-route` command. The route remains reserved for later use in the space where it was created until the route is deleted. To unmap an HTTP route from an app, identify the route using the host name, domain, and path: “`console $ cf unmap-route tcp-app private-domain.example.com –hostname example-app –path mypath ”` To unmap a TCP route from an app, identify the route using the domain and port: “`console $ cf unmap-route tcp-app tcp-domain.example.com –port 60000 ”` ### Share a route with another spaceDOMAINis the domain in the route for your app.HOSTNAMEis the host name in the route for your app.PATHis the path in the route for your app.SPACEis the space with which you want to share the route for your app.ORGis the org containing space with which you want to share the route for your app. If the space with which you want to share the route is within the same org as the space that contains the route, do not include the-oflag.
cf move-route command. You can use this command if you are unable to maintain or delete a shared route within the space with which it was shared. For information about sharing routes across spaces, see [Share a route with another space](#share-route).
To move a route:
1. In a terminal window, target the space from which the route was originally shared by running:
“`
cf target -s SPACE -o ORG
”`
Where:
SPACEis the space from which the route was originally shared.ORGis the org containing space from which the route was originally shared. If the space from which the route was originally shared is within the same org as the space with which the route was shared, do not include the-oflag.
DOMAINis the domain in the route for your app.HOSTNAMEis the host name in the route for your app.PATHis the path in the route for your app.SPACEis the space to which you want to move the route for your app.ORGis the org containing space to which you want to move the route for your app. If the space to which you want to move the route is within the same org as the space that contains the route, do not include the-oflag.
| X-Cf-Routererror value | Reason for error | Response body |
|---|---|---|
invalid_cf_app_instance_header |
The value provided for X-Cf-App-Instance was an incorrectly formatted GUID. |
None |
unknown_route |
The value provided for X-Cf-App-Instance is a correctly formatted GUID, but no instance is found with that GUID for the route
requested. |
400 Bad Request: Requested instance ('1') with guid ('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa') does not exist for route
('example-route.cf.com') |
| X-Cf-Routererror value | Reason for error | Response body |
|---|---|---|
invalid_cf_process_instance_header |
The value provided for X-Cf-Process-Instance was an incorrectly formatted GUID. |
None |
unknown_route |
The value provided for X-Cf-Process-Instance is a correctly formatted GUID, but no backend is found with that GUID and index for the route
requested. |
400 Bad Request: Requested process instance ('1') with guid ('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa') does not exist for route
('example-route.cf.com') |
unknown_route |
The value provided for X-Cf-Process-Instance is a correctly formatted GUID but no backend is found with that GUID for the route
requested. |
400 Bad Request: Requested process instance with guid ('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa') does not exist for route
('example-route.cf.com') |
Create a shared domain
Admins can create an HTTP shared domain with the `cf create-shared-domain` command: ”`console $ cf create-shared-domain scapp.io “`
To create a domain that requires mutual TLS and enforces identity-based route policies, add the --enforce-route-policies flag (optionally with --scope). This setting is fixed when the domain is created and cannot be changed afterward. See Configuring identity-aware routing.
cf CLI v7+ does not support TCP routing or creating shared domains with router groups.
Delete a shared domain
Admins can delete a shared domain from Cloud Foundry with the `cf delete-shared-domain` command: ”`console $ cf delete-shared-domain example.com “`Internal domain
The internal domain is a special type of shared domain used for app communication internal to the platform. When you activate service discovery, the internal domain `apps.internal` becomes available for route mapping. Admins can configure multiple internal domains. Add a custom internal domain name to the `internal_domains` property on the `bosh-dns-adapter` job. Then create an internal domain using the `–internal` option: ”`console $ cf create-shared-domain scapp.io –internal “` The `–router-group` option is not used with internal domains. ### Private domains Org managers can add private domains, or custom domains, and give members of the org permission to create routes for privately registered domain names. Private domains can be shared with other orgs and spaces. These are called as shared private domains and are not the same as shared domains. For more information, see [Shared domains](#shared-domains). When using private domains, you can have routes with the same host name and domain name across different orgs and spaces. This cannot be done with shared domains. Private domains can be HTTP or HTTPS only. TCP routing is supported for shared domains only.Create a private domain
Org managers can create a private domain by running: ”`console $ cf create-private-domain example-org private-domain.example.com “`
Org managers can create an identity-aware private domain by adding --enforce-route-policies (optionally with --scope). This setting is fixed at creation. See Configuring identity-aware routing.
Org managers can create a private domain for a subdomain by running:
$ cf create-private-domain example-org foo.private-domain.example.com
Sharing a private domain with one or more orgs
Org managers can grant or revoke access to a private domain to other orgs if they have permissions for these orgs.
The cf unshare-private-domain command provides a warning and requires confirmation before it proceeds.
$ cf share-private-domain test-org private-domain.example.com
$ cf unshare-private-domain test-org private-domain.example.com
Delete a private domain
Org managers can delete a domain from Cloud Foundry with the cf delete-domain command:
$ cf delete-private-domain private-domain.example.com
Requirements for parent and child domains
In the domain example-app.scapp.io, scapp.io is the parent domain of subdomain example-app. The following list describes requirements for creating domains:
You can only create a private domain that is parent to a private subdomain.
You can create a shared domain that is parent to either a shared or a private subdomain.
The domain foo.example-app.scapp.io is the child subdomain of example-app.scapp.io. The following list describes requirements for creating subdomains:
You can create a private subdomain for a private parent domain only if the domains belong to the same org.
You can create a private subdomain for a shared parent domain.
You can only create a shared subdomain for a shared parent domain.
You cannot create a shared subdomain for a private parent domain.
DNS for domains
To create customized access to your apps, you can map specific or wildcard custom domains to Cloud Foundry by using your DNS provider.
Mapping Domains to your custom domain
To associate a registered domain name with a domain on Cloud Foundry, configure a CNAME record with your DNS provider, pointing at any shared domain offered in Cloud Foundry.
Mapping a single domain to your custom domain
To map a single domain to a custom domain to Cloud Foundry, configure a CNAME record with your DNS provider.
Here are some example CNAME record mappings.
| Record set in custom domain | Type | Target in Cloud Foundry |
|---|---|---|
| example-app.yourcustomdomain.com. | CNAME | example-app.scapp.io |
| www.yourcustomdomain.com. | CNAME | example-app.scapp.io |
After you create the CNAME mapping, your DNS provider routes your custom domain to example-app.scapp.io.
See your DNS provider documentation to find out if the trailing . is required.
Mapping multiple subdomains to your custom domain
Use a wildcard CNAME record to point all of the subdomains in your custom domain to scapp.io.
Each separately configured subdomain has priority over the wildcard configuration.
Here are some example wildcard CNAME record mappings.
| Record set in custom domain | Type | Target in Cloud Foundry |
|---|---|---|
| *.yourcustomdomain.com. | CNAME | *.scapp.io |
| *.yourcustomdomain.com. | CNAME | *.example-app.scapp.io |
If you use a wildcard as the subdomain name, then your DNS provider can route from *.YOURCUSTOMDOMAIN to any of the following:
*.scapp.iofoo.example-app.scapp.iobar.foo.example-app.scapp.io
Configuring DNS for your registered root domain
To use your root domain for apps on Cloud Foundry, you can use custom DNS record types like ALIAS and ANAME, if your DNS provider offers them, or you can use subdomain redirection.
If your DNS provider supports using an ALIAS or ANAME record, configure your root domain with your DNS provider to point at a shared domain in Cloud Foundry.
| Record | Name | Target | Note |
|---|---|---|---|
| ALIAS or ANAME | empty or @ | private-domain.example.com. | To decide whether to use an empty or @ value for the Name entry, see the documentation for your DNS provider. |
If your DNS provider does not support ANAME or ALIAS records, you can use subdomain redirection, also known as domain forwarding, to redirect requests for your root domain to a subdomain configured as a CNAME.
Configure the root domain to point at a subdomain such as www, and configure the subdomain as a CNAME record pointing at a shared domain in
Cloud Foundry.
| Record | Name | Target | Note |
|---|---|---|---|
| URL or Forward | private-domain.example.com | www.private-domain.example.com | This method causes a 301 permanent redirect to the subdomain you configure. |
| CNAME | www | example-app.scapp.io |