Help us shape the future of Go! Take the 2026 Go Developer Survey

relay

package
v5.7.0 Latest Latest
Warning

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

Go to latest
Published: Nov 2, 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