Networking¶
Other services reach yours by name. The internet reaches it through a route you declare.
services:
web:
image: my-app:local
expose:
- "9090" # (1)!
ports:
- "8080:8000" # (2)!
x-ingress:
routes:
- hostname: app.example.com # (3)!
port: 8000 # (4)!
- Open to the other services only.
- On your machine,
localhost:8080reaches port8000of the container. - The public address of the service.
- The port of the container, not the one of your machine.
Generated on every release. You never write these files or see them.
apiVersion: v1
kind: Service
metadata:
labels:
com.docker.compose.project: my-app
com.docker.compose.service: web
name: web
namespace: my-app
spec:
ports:
- name: p-8000-tcp # (1)!
port: 8000
protocol: TCP
targetPort: 8000
- name: p-9090-tcp # (2)!
port: 9090
protocol: TCP
targetPort: 9090
selector:
com.docker.compose.project: my-app
com.docker.compose.service: web
type: ClusterIP # (3)!
- From
ports: the port of the container. The8080of your machine is not here. - From
expose. - An address inside the cluster only.
One route for each hostname, attached to the gateway of the platform.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: web-28059829b1
namespace: my-app
labels:
com.docker.compose.project: my-app
com.docker.compose.service: web
spec:
hostnames:
- app.example.com # (1)!
parentRefs:
- name: envoy-external # (2)!
namespace: network
rules:
- backendRefs:
- name: web
port: 8000 # (3)!
matches:
- path:
type: PathPrefix
value: / # (4)!
- Your
hostname. - The gateway of the platform.
- Your
port. - Your
path.
ports opens the port on your machine
In a development Compose, ports opens the port on your machine. On the cluster it does
nothing by itself: combined with x-ingress, the platform builds the public entry.
Fields¶
| Field | Required | Default | Values |
|---|---|---|---|
expose |
No | Ports for the other services: "8000", a range "8000-8005", or with a protocol "53/udp" |
|
ports |
No | Ports you publish, in Compose syntax: "8080:8000" |
|
x-ingress.routes |
Yes | One route or more | |
x-ingress.routes[].hostname |
Yes | A domain, in lowercase | |
x-ingress.routes[].port |
Yes | A container port declared in ports |
|
x-ingress.routes[].path |
No | / |
A path that starts with / |
Any other field in x-ingress is an error.
What you get¶
On your machine¶
| You declare | What it does |
|---|---|
expose |
The other services of the stack reach it by name, at web:9090 |
ports |
Opens the port on your machine: localhost:8080 reaches port 8000 of the container |
x-ingress |
Nothing. Docker does not serve the domain |
On the cluster¶
| You declare | What it does |
|---|---|
expose |
The other services reach it by the same name and port, web:9090 |
ports |
Nothing by itself. Port 8080 of your machine is not opened anywhere |
ports with x-ingress |
The platform builds the public entry: app.example.com reaches port 8000 |
The gateway, its certificates, and the entry to the cluster belong to the platform. You write no manifest.
Who can reach your services¶
You declare nothing. Compose puts every service of your application on one network, and the platform keeps it that way on the cluster.
| Who calls | Reaches your services |
|---|---|
| Another service of your application | Yes |
| The internet | Only the port of a route in x-ingress, through the gateway |
| A service of another project | No |
| Your application in another environment | No |
Your services keep their way out: they reach the internet and resolve names as before.
services:
web:
image: my-app:local
ports:
- "8080:8000"
x-ingress:
routes:
- hostname: app.example.com
port: 8000
worker:
image: my-app:local
command: [python, worker.py]
Generated on every release. You never write these files or see them.
The services of your application accept each other, and nobody else.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
labels:
com.docker.compose.project: my-app
com.docker.compose.network.default: 'true'
name: default-network
namespace: my-app
spec:
ingress:
- from: # (1)!
- podSelector:
matchLabels:
com.docker.compose.project: my-app
com.docker.compose.network.default: 'true'
podSelector:
matchLabels:
com.docker.compose.project: my-app
com.docker.compose.network.default: 'true'
policyTypes:
- Ingress # (2)!
- Who may come in: only the services of your application.
- Only what comes in is limited. Your services still reach the internet.
The gateway reaches web, and only the port of its route.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
labels:
com.docker.compose.project: my-app
com.docker.compose.service: web
name: web-gateway
namespace: my-app
spec:
ingress:
- from:
- namespaceSelector: # (1)!
matchLabels:
kubernetes.io/metadata.name: network
podSelector:
matchLabels:
gateway.envoyproxy.io/owning-gateway-name: envoy-external
gateway.envoyproxy.io/owning-gateway-namespace: network
ports:
- port: 8000 # (2)!
protocol: TCP
podSelector:
matchLabels:
com.docker.compose.project: my-app
com.docker.compose.service: web
policyTypes:
- Ingress
- The gateway of the platform, and nobody else.
- Only the port of your route.
Several domains¶
Add one route for each domain. All of them reach the same service.
services:
web:
image: my-app:local
ports:
- "8080:8000"
x-ingress:
routes:
- hostname: ${WEB_UY_HOST:?Set WEB_UY_HOST} # (1)!
port: 8000
- hostname: ${WEB_AR_HOST:?Set WEB_AR_HOST}
port: 8000
- A Compose variable, so each environment sets its own domain. Compose stops with your message if the variable has no value.
Generated on every release. You never write these files or see them. Here the variables are
uy.example.com and ar.example.com.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: web-32a076014b
namespace: my-app
labels:
com.docker.compose.project: my-app
com.docker.compose.service: web
spec:
hostnames:
- uy.example.com
parentRefs:
- name: envoy-external
namespace: network
rules:
- backendRefs:
- name: web
port: 8000
matches:
- path:
type: PathPrefix
value: /
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: web-3a76e3c803
namespace: my-app
labels:
com.docker.compose.project: my-app
com.docker.compose.service: web
spec:
hostnames:
- ar.example.com
parentRefs:
- name: envoy-external
namespace: network
rules:
- backendRefs:
- name: web
port: 8000
matches:
- path:
type: PathPrefix
value: /
Rules¶
| Rule | Detail |
|---|---|
| A published port without a route stays internal | The platform warns and publishes nothing |
| A route points to a published port | port is a TCP container port declared in ports |
| A route is HTTP | A UDP port, or one that does not speak HTTP, cannot have a route |
| A route is unique | Two routes cannot share hostname and path |
| No ports, no address | A service with no expose and no ports is not reachable by name on the cluster |
| One network for the application | A networks declaration of your own is rejected |
