How to Attach to a Detached Container in Apple Container: Two Methods Explained

Use container start --attach to reconnect to stdout/stderr, or container exec -it to open an interactive shell inside the running container.

When you launch a workload with the -d or --detach flag in the apple/container repository, the container runs as a background process without blocking your terminal. Reconnecting to that container requires understanding the different attachment modes available in the Apple Container CLI.

Understanding Detached Container State

Running container run -d creates a container that executes independently of your shell session. The standard I/O streams remain open within the container runtime, but they are not forwarded to your terminal. According to the apple/container source code, you can reconnect to these streams using two distinct approaches depending on whether you need output streaming or interactive command execution.

Method 1: Attach to stdout/stderr Using container start --attach

The container start command with the --attach (or -a) flag reopens the container's standard output and error streams in your current terminal.

Understanding the --attach Flag

As documented in docs/command-reference.md, the --attach flag instructs the CLI to start a stopped container and immediately pipe its output to your terminal. This works on containers that were previously stopped after a detached run, or on running containers that have been paused. The implementation references this flag at line 275 of the command reference documentation.

When to Use This Approach

This method is ideal when you need to:

  • View logs from a container that has already stopped
  • Monitor output from a paused container without restarting it
  • Watch real-time output from a long-running process

# Run a container in detached mode

container run -d --name webserver nginx:latest

# Attach to stdout/stderr (use either form)

container start --attach webserver

# or

container start -a webserver

Method 2: Open an Interactive Shell Using container exec

For containers that are currently running, container exec spawns a new process inside the existing container namespace, allowing you to run arbitrary commands or shells.

Using -i and -t Flags

The command reference in docs/command-reference.md (line 53) shows that combining -i (--interactive) and -t (--tty) creates a fully interactive terminal session. The -i flag keeps stdin open, while -t allocates a pseudo-TTY, giving you a proper shell experience.

Executing Specific Commands

You are not limited to shell access. Any executable within the container's filesystem can be invoked:


# Open an interactive bash shell

container exec -it webserver /bin/bash

# Run a specific command interactively

container exec -it webserver cat /etc/os-release

Key Implementation Files

The attachment functionality spans several critical components in the apple/container codebase:

  • docs/command-reference.md — Defines all CLI parsing logic, including the --attach flag for container start and the exec command syntax that enables interactive shells.

  • docs/how-to.md — Contains practical scenarios for container lifecycle management, specifically detailing when and how to attach to detached containers based on different use cases.

  • Sources/ContainerPersistence/ContainerSystemConfig.swift — Stores configuration defaults, including network and DNS settings that affect how containers are started and how attachment streams are established.

  • Sources/TerminalProgress/* — Implements the live-updating progress UI rendered when you attach to a running container's output streams, providing visual feedback during the attachment process.

Summary

  • Use container start --attach when you need to reconnect to a stopped or paused container's output streams.
  • Use container exec -it when you need an interactive shell or want to run specific commands inside a running container.
  • Reference either the container name (set via --name) or the container ID for both commands.
  • The CLI parsing is defined in docs/command-reference.md, while the UI rendering logic resides in Sources/TerminalProgress/.

Frequently Asked Questions

What's the difference between container start --attach and container exec?

container start --attach reconnects to the container's main process stdout/stderr, typically used when the container was started detached and you want to see its output. container exec creates a new process inside the running container's namespace, allowing you to run additional commands or shells without disturbing the main process.

Can I attach to a stopped container?

Yes, but only using container start --attach. This command can start a stopped container (for example, one that exited after a previous container run -d) and immediately attach to its output. You cannot use container exec on a stopped container because it requires a running container to execute processes inside.

Do I need to use the container ID or can I use the name?

You can use either the container name (specified with --name during creation) or the automatically generated container ID. Both container start --attach and container exec accept either identifier, making it convenient to reference containers by memorable names rather than hexadecimal strings.

Where are the CLI flags defined in the source code?

The CLI flags for --attach and exec are defined in docs/command-reference.md, specifically around line 275 for the attach functionality and line 53 for the exec command. The actual runtime behavior is influenced by Sources/ContainerPersistence/ContainerSystemConfig.swift, which manages the underlying configuration for container I/O streams.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →