container

repository·main·Indexed 13 days ago

https://github.com/apple/container

A Swift-based tool for creating and running OCI-compatible Linux containers as lightweight virtual machines on Apple silicon Macs. It features the `container machine` subcommand for managing persistent Linux environments and supports integration with Visual Studio Code's Remote - SSH extension.

Tokens
29.5K
Snippets
146
Records
160
Agent score
98%

What's inside container

  1. Explore container topics and guides

    main

    The container project provides specialized guides for advanced usage beyond the basic tutorial. Depending on your requirements, you can find detailed documentation for:

    • Resource Management: CPU/memory limits, overcommitting, monitoring with container stats, and disk reclamation.
    • Storage: Bind-mounting host directories, creating named volumes, and using tmpfs storage.
    • Networking: DNS-based naming, container connectivity, port forwarding, and isolated networks.
    • Host Integration: Forwarding SSH agents and accessing Mac services from within a container.
    • System Limits: Configuring ulimits (e.g., open-file and process-count limits).
    • Runtime Configuration: Linux capabilities, path masking/read-only settings, nested virtualization, and custom init processes.
    • Multiplatform Support: Building and running images for both Apple silicon and x86-64.
    • Inspection & Logging: Using inspect and list for scripting, and accessing container, VM, or system logs.
    • Configuration: Using config.toml to customize the system.
    • Container Machines: Managing persistent Linux environments with mounted home directories.
    • Developer Experience: Installing shell completions for zsh, bash, and fish.
  2. Understand the `container` architecture and components

    main

    The container system consists of a CLI, a background API server, and several XPC helpers that manage different aspects of the container lifecycle:

    • container CLI: The primary interface for starting/managing containers, building images, and interacting with OCI registries.
    • container-apiserver: A launch agent started via container system start and stopped via container system stop. It provides the client APIs for managing container and network resources.
    • container-core-images: An XPC helper launched by the apiserver that manages the local content store and image management APIs.
    • container-network-vmnet: An XPC helper launched by the apiserver that manages the virtual network.
    • container-runtime-linux: A container runtime helper launched by container-apiserver for each specific container to expose its management API.
  3. Requirements for running container

    main

    To use container, ensure your environment meets the following criteria:

    • Hardware: A Mac with Apple silicon.
    • Operating System: macOS 26 or newer. container utilizes specific virtualization and networking enhancements introduced in macOS 26; older versions are not supported.
  4. Understand the Runtime Library Exception for Apache 2.0 License

    main

    Certain dependencies used by this project, such as swift-argument-parser, swift-collections, swift-protobuf, and swift-system, are licensed under the Apache License v2.0 with Runtime Library Exception.

    This exception allows you to use the software to compile your source code and embed portions of it into a binary product. If this occurs, you may redistribute the resulting binary product without providing the attribution normally required by Sections 4(a), 4(b), and 4(d) of the standard Apache 2.0 License.

  5. How `container` manages container isolation and resources

    main

    Unlike traditional approaches that use a single shared Linux VM for all containers, container uses the Containerization package to launch a lightweight, dedicated VM for each container you create.

    This architecture provides:

    • Security: Full VM isolation for each container using a minimal set of core utilities.
    • Privacy: Selective mounting of host data into each specific VM rather than mounting all data into a shared VM.
    • Performance: Lower memory footprint than full VMs with boot times comparable to shared-VM container models.

    container is OCI-compliant, meaning it can consume and produce standard OCI images, ensuring interoperability with other container tools.

  6. Configure plugin-specific settings in [plugin.<id>]

    main

    Plugins can define their own configuration schemas under [plugin.<id>], where <id> is the plugin's identifier. Values in one plugin's section are isolated and cannot leak into others. Consult the specific plugin's documentation for its schema.

    [plugin.my-plugin-id]
    plugin_key = "plugin_value"
  7. How container-to-container networking works

    main

    Containers on the same network can communicate using each other's DNS names, provided you have completed the DNS setup described in the Set up DNS-based container names guide.

    Important Limitations:

    • Domain Suffix Required: On the default network, you must use the fully qualified domain name (e.g., http-server.test). Bare hostnames (e.g., http-server) are not currently supported for discovery.
    • Custom Networks: On custom networks created via container network create, bare hostname lookup is not yet implemented. To reach a container on a custom network, use its IP address (found via container inspect <name>).
    container run --rm -d --name http-server python:alpine python3 -m http.server
    container run -it --rm alpine/curl curl -v http://http-server.test:8000
  8. Quickstart: Create and run your first container machine

    main

    To get started, create a container machine from an OCI image (e.g., alpine:latest) and name it. You can then use container machine run to execute commands or open an interactive shell. The run command automatically boots the machine if it is stopped. By default, your macOS username and home directory are mapped into the Linux environment at /Users/<username> (accessible via $HOME inside the container).

    ```bash
    container machine create alpine:latest --name dev
    container machine run -n dev whoami       # your host username, not root
    container machine run -n dev pwd          # /home/<you> — your Mac home dir, mounted in
    container machine run -n dev              # interactive shell; cd into your repos in $HOME
    ```埋
  9. Push a multiplatform image to a registry

    main

    Pushing a multiplatform image to a container registry uses the same syntax as pushing a single-platform image. The container image push command will handle the multi-architecture manifest automatically.

    container image push registry.example.com/fido/web-test:latest
  10. Set per-process resource limits with --ulimit

    main

    Use the --ulimit flag with container run or container create to set Linux resource limits (rlimits) for the container's init process.

    Syntax Patterns

    • Single value: Sets both the soft and hard limits to the same value.
    • Soft and hard limits: Use the colon separator (<soft>:<hard>) to set them independently.
    • Multiple limits: Repeat the --ulimit flag for each limit you wish to set.
    • Unlimited: Use the keyword unlimited to remove limits for a specific type.

    Important Note on nofile=unlimited

    Setting nofile=unlimited will cause the container to fail to start with NSPOSIXErrorDomain Code=1 "Operation not permitted". This occurs because unlimited attempts to set the limit to UINT64_MAX, which exceeds the Linux ceiling defined by /proc/sys/fs/nr_open. To avoid this, use an explicit value that is less than or equal to the guest's nr_open limit (e.g., nofile=1048576).

    # Set both soft and hard limits to 65536
    container run --ulimit nofile=65536 -it ubuntu:24.04 bash
    
    # Set soft limit to 65536 and hard limit to 131072
    container run --ulimit nofile=65536:131072 -it ubuntu:24.04 bash
    
    # Set multiple limits
    container run --ulimit nofile=65536:131072 --ulimit cpu=60 -it ubuntu:24.04 bash
    
    # Set a limit to unlimited
    container run --ulimit nproc=unlimited -it ubuntu:24.04 bash
  11. Share host data using bind mounts

    main

    You can share data between your host system and a container using bind mounts. This allows you to persist data across multiple container runs and access host files directly from within the container.

    Use the --volume option with the syntax [host_path]:[container_path] or the --mount option with key=value syntax.

    # Using --volume (host_path:container_path)
    container run --volume ${HOME}/Desktop/assets:/content/assets docker.io/python:alpine ls -l /content/assets
    
    # Using --mount (key=value syntax)
    container run --mount source=${HOME}/Desktop/assets,target=/content/assets docker.io/python:alpine ls -l /content/assets
  12. Build and test the container project

    main

    To build container and its background services from source and run both basic and integration tests, use the make command. It is recommended to use an isolated application data directory by setting APP_ROOT to avoid polluting your system configuration.

    Requirements:

    • Mac with Apple silicon
    • macOS 15 minimum (macOS 26 recommended)
    • Xcode 26 set as the active developer directory

    Important Note on macOS 26: A bug in the vmnet framework on macOS 26 causes network creation to fail if helper applications are located in Documents or Desktop directories. To avoid this, either:

    1. Use make install to place binaries in /usr/local.
    2. Move your project directory to a location like ~/projects/container if using the binaries in the bin and libexec directories created by make all.
    # Build and run tests in an isolated directory
    rm -rf test-data
    make APP_ROOT=test-data all test integration