# How to Configure Network Socket Forwarding and Port Publishing in apple/container

> Configure network socket forwarding and port publishing in apple/container using the -p flag for TCP/UDP and --publish-socket for Unix-domain sockets. Learn how to manage container networking efficiently.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: how-to-guide
- Published: 2026-06-24

---

**Use the `-p` or `--publish` flag for TCP/UDP port mapping and `--publish-socket` for Unix-domain sockets, parsed by [`Parser.swift`](https://github.com/apple/container/blob/main/Parser.swift) and executed by `RuntimeService.startSocketForwarders`.**

The `apple/container` runtime implements network socket forwarding and port publishing as first-class features, allowing you to expose container services on host interfaces or share Unix sockets between the host and container filesystems. This guide explains the configuration syntax, underlying data models, and runtime implementation based on the actual source code.

## Port Publishing with `-p` and `--publish`

The `-p` or `--publish` flag maps host IP addresses and ports to container ports using the format:

```

[host-ip:]host-port:container-port[/protocol]

```

- `host-ip` is optional and defaults to `0.0.0.0` (all interfaces).
- `protocol` is optional and defaults to `tcp`, but can be set to `udp`.

### The PublishPort Data Model

When the CLI parses your command, `Parser.publishPorts` (located in [`Sources/Services/ContainerAPIService/Client/Parser.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Parser.swift) at lines 11-18) constructs a `PublishPort` struct defined in [`Sources/ContainerResource/Container/PublishPort.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Container/PublishPort.swift). This struct stores:

- `hostAddress` – the IP address on the host side.
- `hostPort` – the starting host port (UInt16).
- `containerPort` – the target port inside the container.
- `proto` – either `PublishProtocol.tcp` or `.udp`.
- `count` – the number of consecutive ports to forward (defaults to 1).

The `PublishPort.validatePortRange` method (lines 88-91) ensures that `hostPort + count - 1` does not overflow `UInt16`, preventing invalid port ranges from reaching the runtime.

## Runtime Socket Forwarding

When a container starts, `RuntimeService` receives the list of `PublishPort` objects via `config.publishedPorts` and initiates the forwarding logic.

### How RuntimeService.startSocketForwarders Works

The `RuntimeService.startSocketForwarders` method in [`Sources/Services/RuntimeLinux/Server/RuntimeService.swift`](https://github.com/apple/container/blob/main/Sources/Services/RuntimeLinux/Server/RuntimeService.swift) (lines 776-848) performs three critical steps:

1. **Validation**: Checks that the list is non-empty and that no two specifications overlap using `publishedPorts.hasOverlaps()`.
2. **Address Creation**: For each `PublishPort`, creates a `SocketAddress` for the host proxy (`proxyAddress`) and a matching address on the container side (`serverAddress`).
3. **Forwarder Selection**: Chooses between `TCPForwarder` and `UDPForwarder` (lines 12-20) based on the `proto` field.

The forwarder implementations in [`Sources/SocketForwarder/TCPForwarder.swift`](https://github.com/apple/container/blob/main/Sources/SocketForwarder/TCPForwarder.swift) and [`Sources/SocketForwarder/UDPForwarder.swift`](https://github.com/apple/container/blob/main/Sources/SocketForwarder/UDPForwarder.swift) use SwiftNIO to bind a listener on the host and proxy traffic to the container’s network namespace. If you attempt to bind a privileged port (below 1024) without sufficient permissions, the runtime translates the error into a clear `ContainerizationError` (lines 28-34).

## Unix-Domain Socket Publishing with `--publish-socket`

For Unix-domain sockets, use the `--publish-socket` flag with the format:

```

host_path:container_path

```

### Socket Specification and Validation

`Parser.publishSocket` in [`Sources/Services/ContainerAPIService/Client/Parser.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Parser.swift) (lines 38-94) validates the host path, ensures the target is a Unix-domain socket (or creates the parent directory), and returns a `PublishSocket` struct defined in [`Sources/ContainerResource/Container/PublishSocket.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Container/PublishSocket.swift). This struct captures the source and destination paths for mounting.

### Mount Integration

During container creation, the `ContainerConfiguration.publishedSockets` array is populated. The runtime then mounts the socket file into the container’s filesystem using the same path resolution logic as the `--volume` implementation, ensuring the container can communicate with host services like the Docker daemon.

## Practical Configuration Examples

### Publish a Single TCP Port

Forward host `127.0.0.1:8080` to container port `80`:

```bash
container run -d --name web -p 127.0.0.1:8080:80 nginx:latest

```

### Publish a UDP Port Range

Forward host ports `9000-9004` to container ports `8000-8004` via UDP:

```bash
container run -d --publish 0.0.0.0:9000-9004:8000-8004/udp my-app

```

The `count` field becomes `5`, spawning five parallel `UDPForwarder` instances.

### Publish a Unix-Domain Socket

Expose the host Docker socket inside the container:

```bash
container run -d \
    --publish-socket /var/run/docker.sock:/var/run/docker.sock \
    --volume /var/run/docker.sock:/var/run/docker.sock \
    my-builder

```

### Combine Ports and Sockets

Multiple publish flags can be combined in a single command:

```bash
container run -d \
    -p 8080:80 \
    -p 8443:443/tcp \
    -p 9000-9002:8000-8002/udp \
    --publish-socket /tmp/my.sock:/var/run/my.sock \
    my-app

```

## Summary

- **Port publishing** uses `-p` with the format `[host-ip:]host-port:container-port[/protocol]`, stored in the `PublishPort` struct and validated by `PublishPort.validatePortRange`.
- **Runtime forwarding** is handled by `RuntimeService.startSocketForwarders`, which creates `TCPForwarder` or `UDPForwarder` instances based on the protocol.
- **Socket publishing** uses `--publish-socket` with the format `host_path:container_path`, creating `PublishSocket` entries that are mounted into the container filesystem.
- All specifications are parsed by [`Parser.swift`](https://github.com/apple/container/blob/main/Parser.swift) and processed independently by the runtime.

## Frequently Asked Questions

### What is the difference between port publishing and socket publishing?

Port publishing maps TCP or UDP ports between the host and container network namespaces, enabling external access to containerized services. Socket publishing binds a Unix-domain socket from the host into the container filesystem, allowing inter-process communication with host services like the Docker daemon.

### Can I publish a range of ports in a single command?

Yes. The `PublishPort` struct includes a `count` field that specifies how many consecutive ports to forward. The CLI syntax uses a hyphen (e.g., `9000-9004:8000-8004`), and the runtime spawns separate forwarder instances for each port in the range.

### How does the runtime handle port conflicts?

Before starting forwarders, `RuntimeService.startSocketForwarders` calls `publishedPorts.hasOverlaps()` to detect duplicate or overlapping port specifications. If conflicts are found, the container fails to start with a validation error.

### Why am I getting an error when binding to ports below 1024?

Binding to privileged ports (below 1024) requires root privileges. If the runtime lacks sufficient permissions, `TCPForwarder` or `UDPForwarder` raises an error that is translated into a descriptive `ContainerizationError` (lines 28-34 of the forwarder implementation). Run the command with elevated privileges or choose a higher port number.