relay

package
v5.7.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 11, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CheckTarget

func CheckTarget(target container.Summary, serviceName, operation string) error

CheckTarget refuses process-level operations on a relay container: it stands in for the provider's resource on the network, but there is no service process in it to act on.

func IsContainer

func IsContainer(ctr container.Summary) bool

IsContainer reports whether a container is a service's network relay rather than a regular instance of it: a static scratch-based binary with no shell or service process, so anything expecting one to be there — secrets/configs injection, lifecycle hooks, process-level commands — must skip it.

func IsRelay

func IsRelay(labels map[string]string) bool

IsRelay tells, from a container's labels, whether it is a service's network relay. Relays are long-lived infrastructure standing in for a provider's resource: they never terminate on their own, so counting them among the application's containers would keep an attached `up` waiting forever.

func Networks

func Networks(project *types.Project, service types.ServiceConfig) []string

Networks returns the compose network keys the relay must join: the union of the networks of every service depending on the provider service — the consumers the relay exists for — falling back to the project default.

Types

type Backend

type Backend interface {
	// APIClient talks to the Docker daemon.
	APIClient() client.APIClient
	// Events receives the progress of the operations.
	Events() api.EventProcessor
	// IsDesktopIntegrationActive tells whether Docker Desktop is the engine.
	IsDesktopIntegrationActive(ctx context.Context) (bool, error)
}

Backend is what the relay management needs from the engine.

type InfoAnswer

type InfoAnswer struct {
	Networks []NetworkInfo `json:"networks"`
}

InfoAnswer is the get-relay-info reply: the network the relay reaches the provider's own runtime through, with the address the HOST owns on it — its gateway. A provider running its service locally can bind that address: reachable from the relay (same-bridge local delivery), and — unlike a project's own bridge networks, which every service on them can also reach — joined by nothing else. That is isolation by network membership, not something the address alone enforces: the gateway is an address of the host itself, and a plain bind restricts by destination address, not by arrival interface, so a local container able to route to it can still reach the listener by IP. A provider keeps the endpoint relay-only by binding ONLY this address and pinning the socket to the bridge's own interface (SO_BINDTODEVICE on Linux). A single entry, or none when it could not be resolved (see ensureRelayLinkNetwork): a provider must treat that as "bind elsewhere".

type NetworkInfo

type NetworkInfo struct {
	// Name is the engine-level name of the dedicated relay-link network on a
	// standalone engine. Under Docker Desktop it is the placeholder
	// "desktop": no such network exists there, so it is only meaningful
	// for logging, never as an engine-level network reference.
	Name string `json:"name"`
	// Gateway is the address the provider's host owns that the relay can
	// reach on this network: the dedicated relay-link network's IPv4
	// gateway on a standalone engine, the host's own loopback under Docker
	// Desktop — whose proxy dials host-process endpoints through
	// 127.0.0.1, making it factually the gateway to the host from the
	// relay's vantage point. Empty when unresolved (network not created
	// yet, driver without a host-owned gateway, IPv6-only).
	Gateway string `json:"gateway,omitempty"`
}

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service manages the relay containers and relay link networks on a Backend.

func New

func New(backend Backend) *Service

New creates a Service working with the given Backend.

func (*Service) Ensure

func (s *Service) Ensure(ctx context.Context, project *types.Project, service types.ServiceConfig, endpoints map[int]string, networkKeys []string) error

Ensure converges the relay container standing in for a provider service that published endpoints: consumers reach the provider's resource at the compose-native address (http://<service>:<port>) through it. The relay is a regular project container (standard compose labels, canonical name, service alias on the consumers' networks) so label-driven commands treat it as the service, plus the RelayLabel identifying its role — the reconciler leaves provider services' containers alone, and process-level commands (exec) refuse it.

networkKeys (see relayNetworks) is computed by the caller under the shared project mutex: this function performs only Docker API work and must not touch project.Services, which concurrent provider runs mutate.

func (*Service) Info

func (s *Service) Info(ctx context.Context, project *types.Project, service types.ServiceConfig) InfoAnswer

Info assembles the get-relay-info answer for one provider service: the dedicated relay-link network (ensureRelayLinkNetwork) — never one of the project's own bridge networks, which every other service attached to them could also reach — resolved for the address a locally-run endpoint should bind. Compose owns the platform knowledge — the provider just binds what is announced. Best-effort by design: a provider must treat a missing gateway as "bind elsewhere".

func (*Service) LinkNetworks

func (s *Service) LinkNetworks(ctx context.Context, projectName string) ([]network.Summary, error)

LinkNetworks lists the relay link networks of every provider service of a project — what a `down` has to remove, since removeServiceRelay's own network cleanup only runs when a later `up` decides a relay is no longer needed, a path a full `down` never takes (the relay container itself is swept by the generic per-service container removal instead), so without this the dedicated network would outlive the relay it was created for. Looked up directly by label — not by walking project.Services and checking Provider — because a project reconstructed from live containers (getProjectWithResources, the path a `down` without an explicit compose file takes) never repopulates Provider: nothing in a container's own labels says its service declared one, so a per-service check here would silently skip every service and leak the network on every such down — the common case, not an edge one.

func (*Service) Remove

func (s *Service) Remove(ctx context.Context, projectName, serviceName string) error

Remove removes a service's relay container, if any. Called whenever an up finds the provider publishing no endpoint — whether it never did, or a relay from an earlier up is now stale — so a relay that still routes to an upstream the provider no longer serves doesn't linger.

func (*Service) RemoveLinkNetwork

func (s *Service) RemoveLinkNetwork(ctx context.Context, n network.Summary) error

RemoveLinkNetwork is the single place a relay-link network is removed, shared by the up path (removeRelayLinkNetwork) and the down path (ensureRelayLinkNetworksDown). Every caller removes the relay container first, but the daemon disconnects its endpoints asynchronously, so a ContainerRemove that already returned can still race NetworkRemove: a conflict (errdefs.IsConflict) is tolerated, left for a later up/down to retry, as is the network already being gone (errdefs.IsNotFound).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL