Skip to content

Instantly share code, notes, and snippets.

@horaceho
Created July 31, 2026 07:15
Show Gist options
  • Select an option

  • Save horaceho/22769d97a5d56986e28d1846e25d49f1 to your computer and use it in GitHub Desktop.

Select an option

Save horaceho/22769d97a5d56986e28d1846e25d49f1 to your computer and use it in GitHub Desktop.

SKILL: macOS-Ubuntu-Container

Metadata

  • Name: macos-ubuntu-container
  • Version: 1.0.0
  • Platform: macOS (Apple Silicon)
  • Tool: apple/container (brew installed)
  • Objective: Create, manage, and interact with a persistent Ubuntu LTS container optimized for development, with working network and package management.

1. Prerequisites (Pre-flight Check)

Before running any container, ensure the host environment is ready:

  • macOS 26 (Tahoe) or higher on Apple Silicon.
  • Homebrew installed.
  • Apple Container tool installed: brew install apple/container/apple-container.
  • Service initialized: container system start (select y when prompted to install the default kernel).

2. Core Workflow (Create Persistent Container)

Why a persistent container? A standard container run -ti --rm is ephemeral. For a development environment, we need a container that persists state (files, installed packages) across restarts, similar to a VM. We achieve this by running a background process that never exits (sleep infinity).

The Correct Creation Command (Includes Network Fix): To avoid Temporary failure resolving 'ports.ubuntu.com', we explicitly set the DNS server during creation.

container run -d --name <CONTAINER_NAME> --dns 8.8.8.8 --dns 1.1.1.1 ubuntu:latest sleep infinity

Parameter Breakdown:

  • -d: Runs the container in the background (detached).
  • --name <CONTAINER_NAME>: Assigns a persistent name (e.g., debi).
  • --dns 8.8.8.8 / --dns 1.1.1.1: Sets reliable external DNS resolvers (this resolves the apt update failure).
  • ubuntu:latest: Pulls the latest Ubuntu LTS release.
  • sleep infinity: Keeps the container alive indefinitely, preventing immediate exit.

Example:

container run -d --name debi --dns 8.8.8.8 --dns 1.1.1.1 ubuntu:latest sleep infinity

3. Interaction (Entering the Shell)

To get an interactive bash shell inside the persistent container:

container exec -it <CONTAINER_NAME> /bin/bash

Example:

container exec -it debi /bin/bash

You are now root inside / of the Ubuntu filesystem.


4. Post-Creation Setup (Inside the Container)

Once inside the shell, always update the package index first:

apt update
apt upgrade -y
apt install -y curl git vim build-essential

5. Container Lifecycle Management (Host Commands)

Action Command
Stop the container container stop <NAME>
Start the container container start <NAME>
Re-enter shell container exec -it <NAME> /bin/bash
Check status container ps -a
Delete (permanent) container rm -f <NAME>

6. Troubleshooting Reference

DNS / apt update Fails

Symptom: Temporary failure resolving 'ports.ubuntu.com'. Fix: If you forgot --dns at creation, you can temporarily fix inside the container via echo "nameserver 8.8.8.8" > /etc/resolv.conf. For a permanent fix, delete and recreate using the --dns flags as shown in Section 2.

Kernel Panic / VM Failures

Symptom: container: vmexec error. Fix: Restart the underlying container service:

container system stop
container system start

Clean Slate

If the environment becomes corrupted, wipe all existing containers and start over:

container system prune -af

7. Why avoid container machine?

The container machine create <image> --name <name> command currently lacks a --command or --entrypoint flag. Since the default CMD for Ubuntu is /bin/bash, it exits immediately when run without an interactive TTY (during creation), resulting in a stopped state that cannot be started again (no container machine start subcommand exists). The standard detached container (container run -d) is the officially stable method for persistent environments.


8. Agent Execution Summary (The "Act" Block)

When an AI agent receives a request to "Set up Ubuntu on this Mac", execute this exact sequence:

  1. container system start (ensure service is up).
  2. container run -d --name ubuntu-dev --dns 8.8.8.8 --dns 1.1.1.1 ubuntu:latest sleep infinity.
  3. container exec -it ubuntu-dev /bin/bash (or if fully automated, use container exec ubuntu-dev apt update).
  4. Echo to the user: "Ubuntu LTS is ready. Use container exec -it ubuntu-dev /bin/bash to enter."

End of SKILL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment