# How to Run a Detached Nginx Container with Port Publishing in Apple Container

> Easily run a detached Nginx container with port publishing on Apple Container. Use a simple command to host your web server in the background.

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

---

**Use `container run -d -p 8080:80 nginx:latest` to start a background Nginx container and map host port 8080 to container port 80.**

The `apple/container` repository provides a Swift-based container runtime that supports standard Docker-like workflows. Learning how to run a detached Nginx container with port publishing allows you to deploy web services that persist after terminal disconnect and remain accessible via host networking.

## Understanding the Container Run Command

The `container run` command serves as the primary interface for creating and starting containers in the Apple Container ecosystem. According to the source code in [`ContainerRun.swift`](https://github.com/apple/container/blob/main/ContainerRun.swift), this command orchestrates the entire lifecycle from flag parsing to process initialization.

### How Detached Mode Works

The **`-d`** or **`--detach`** flag triggers background execution. In [`Sources/ContainerCommands/Container/ContainerRun.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Container/ContainerRun.swift) (lines 54-60), the implementation checks `managementFlags.detach` and, when true, executes `process.start()`, immediately closes I/O handling, prints the generated container ID, and returns control to the terminal. This leaves the container process running within the runtime sandbox while freeing your shell.

### Port Publishing Syntax

Port publishing uses the **`-p`** or **`--publish`** flag with the syntax `[host‑ip:]host‑port:container‑port[/protocol]`. This maps traffic from the host's network interface to the container's internal ports. For Nginx, which listens on port 80 by default, you typically expose it on a host port like 8080.

## Step-by-Step Implementation Flow

When you execute `container run -d -p 8080:80 nginx:latest`, the following occurs:

1. **Flag Parsing**: The CLI parses `processFlags`, `resourceFlags`, and `managementFlags` (lines 38-55 in [`ContainerRun.swift`](https://github.com/apple/container/blob/main/ContainerRun.swift)), extracting `detach`, `publish`, and optional `name` parameters.

2. **Configuration Building**: The system constructs a `ContainerCreateOptions` object. The `autoRemove` property is set based on the `--rm` flag (lines 11-13 in [`ContainerRun.swift`](https://github.com/apple/container/blob/main/ContainerRun.swift)).

3. **Container Registration**: The `client.create()` method registers the container with the runtime, passing the image name (`nginx:latest`) and encoded port specifications.

4. **Background Launch**: When `detach` is true, the code enters the `if detach { … }` block (lines 54-60), starting the process without waiting for completion.

5. **Network Setup**: The runtime service ([`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift)) creates the network namespace, virtual NIC, and host-side listening socket that forwards traffic to the container's port 80.

## Practical Code Examples

### Minimal Detached Command

Start Nginx in the background with basic port mapping:

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

```

This creates a randomly named container, runs it detached, and publishes host port 8080 to container port 80. The command returns the container ID immediately.

### Named Container with CID File

For easier management and script integration:

```bash
container run -d --name web \
  -p 8080:80 \
  --cidfile /tmp/web.cid \
  nginx:latest

```

The `--name web` parameter enables referral via `container inspect web`, while `--cidfile /tmp/web.cid` writes the container ID to disk (handled in [`ContainerRun.swift`](https://github.com/apple/container/blob/main/ContainerRun.swift) lines 38-52).

### Multiple Ports and Environment Variables

Expose both HTTP and HTTPS while passing configuration:

```bash
container run -d \
  --name web \
  -p 8080:80 -p 8443:443 \
  -e NGINX_HOST=example.com \
  nginx:latest

```

Environment variables are injected via `processFlags` through `Utility.containerConfigFromFlags` (lines 95-104 in [`ContainerRun.swift`](https://github.com/apple/container/blob/main/ContainerRun.swift)).

### Verifying the Container

Check running containers and port bindings:

```bash
container list
container inspect web

```

The inspect output includes a `Ports` section showing:

```json
"Ports": [
  {
    "HostIP": "0.0.0.0",
    "HostPort": "8080",
    "ContainerPort": "80",
    "Protocol": "tcp"
  }
]

```

## Key Source Files

Understanding the implementation requires examining these files:

- **[`Sources/ContainerCommands/Container/ContainerRun.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Container/ContainerRun.swift)**: Parses CLI flags and implements the detach logic (`managementFlags.detach`).
- **[`Sources/ContainerResource/Container/ContainerCreateOptions.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Container/ContainerCreateOptions.swift)**: Defines `autoRemove` behavior derived from the `--rm` flag.
- **[`Sources/Services/RuntimeLinux/Server/RuntimeService.swift`](https://github.com/apple/container/blob/main/Sources/Services/RuntimeLinux/Server/RuntimeService.swift)**: Handles the actual networking setup and port forwarding in the Linux sandbox.
- **[`Tests/IntegrationTests/Utilities/ContainerFixture.swift`](https://github.com/apple/container/blob/main/Tests/IntegrationTests/Utilities/ContainerFixture.swift)**: Demonstrates test patterns using the same `-d` and `-p` flags.

## Summary

- Use **`container run -d -p 8080:80 nginx:latest`** to run a detached Nginx container with port publishing.
- The **`-d`** flag executes `process.start()` and returns immediately while the runtime manages the background process.
- Port publishing syntax follows **`[host-ip:]host-port:container-port[/protocol]`** and is processed by the runtime's network namespace setup.
- Source implementation resides primarily in **[`ContainerRun.swift`](https://github.com/apple/container/blob/main/ContainerRun.swift)** (CLI handling) and **[`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift)** (network forwarding).
- Name containers with **`--name`** and track IDs with **`--cidfile`** for operational convenience.

## Frequently Asked Questions

### What does the -d flag do in container run?

The `-d` or `--detach` flag tells the CLI to start the container and return immediately without waiting for the process to exit. According to [`ContainerRun.swift`](https://github.com/apple/container/blob/main/ContainerRun.swift) (lines 54-60), this executes `process.start()`, closes I/O streams, prints the container ID, and exits the CLI process while the container continues running in the runtime sandbox.

### How do I publish multiple ports when running a detached container?

Specify multiple `-p` flags when invoking `container run`. For example, `-p 8080:80 -p 8443:443` maps both HTTP and HTTPS ports. Each flag follows the `[host-ip:]host-port:container-port[/protocol]` syntax and is processed as part of the `managementFlags.publish` array in the Swift implementation.

### Where is the container ID stored when using --cidfile?

The container ID is written to the file path specified by the `--cidfile` flag immediately after container creation. In [`ContainerRun.swift`](https://github.com/apple/container/blob/main/ContainerRun.swift) (lines 38-52), the implementation generates the container ID during the creation phase and persists it to the specified file before the detach logic executes.

### How does the runtime handle port forwarding?

The actual networking implementation resides in [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift) rather than the CLI. The runtime creates a virtual network interface for the container, attaches it to the user-defined bridge, and binds the host socket according to the publish specifications. This Linux sandbox setup forwards traffic from the host port to the container's internal port 80.