### Single File Mounts # Single File Mounts In Containerization, what is analogous to bind mounts goes over virtiofs. virtiofs can only share directories, not individual files. To support mounting a single file from the host into a container, Containerization shares the file's parent directory via virtiofs and then bind mounts the specific file to its final destination inside the container. ## How it works 1. **Detection**: During mount preparation, each virtiofs mount source is stat'd. If it's a regular file (not a directory), it enters the single-file mount path. Symlinks are resolved to the real file first. 2. **Parent directory share**: The file's parent directory is shared via virtiofs into the guest VM. If multiple single-file mounts reference files in the same parent directory, only one virtiofs share is created. 3. **Guest holding mount**: After the VM starts, the parent directory share is mounted to a holding location in the guest. 4. **Bind mount**: When the container starts, a bind mount is created from the holding location to the requested destination path inside the container. ### Example Mounting `/Users/dev/config/app.toml` to `/etc/app.toml` in the container: ``` Host: /Users/dev/config/ (shared via virtiofs) Guest VM: /temporary/holding/spot/ (virtiofs mount of parent dir) Container: /etc/app.toml (bind mount of /temporary/holding/spot/app.toml) ``` ## Trade-offs Sharing the parent directory means that sibling files in that directory are visible to the guest VM at the holding mount point under `/run`. The bind mount into the container only exposes the specific file requested, but the full parent directory contents are accessible from inside the VM itself. This is a deliberate trade-off for reliability. Prior attempts at supporting single file mounts using temporary directories with hardlinks were fragile across filesystem boundaries and with certain host filesystem configurations. ## Alternatives to single file mounts If exposing the parent directory to the guest VM is not acceptable for your use case, you can avoid single-file mounts entirely: - **Mount the whole directory**: Instead of mounting a single file, mount the directory that contains it. This is functionally equivalent (the directory is shared either way) but makes the behavior explicit and gives the container access to the full directory at the destination path. - **Stage files into a dedicated directory**: Copy the files you need into a dedicated directory on the host and mount that directory instead. This gives you full control over what is visible to the guest. --- ### X86 64 Build # x86_64 Deployment Build `make dist-x86_64` produces a self-contained x86_64 Linux deployment tarball at `bin/containerization-x86_64-.tar.gz`. The build runs entirely inside the aarch64 Linux dev container — there is no host tooling requirement beyond `make`, `container`, and the prerequisites the dev image installs. The tarball ships everything needed to run a Containerization VM on an x86_64 Linux host: the `cctl` host binary, the `cloud-hypervisor` VMM, the `virtiofsd` filesystem daemon, an x86_64 Linux kernel, and an `initfs.ext4` guest rootfs containing `vminitd` + `vmexec`. `cctl`, `cloud-hypervisor`, and `vminitd`/`vmexec` are statically linked against musl, so they run on any x86_64 Linux. **`virtiofsd` is dynamically linked against glibc 2.35+**; the deployment host must provide glibc ≥ 2.35 (Ubuntu 22.04 / Debian 12 / RHEL 9 era) plus `libseccomp.so.2` and `libcap-ng.so.0`. Both are present by default on essentially every server distro shipped in the last few years. ## Prerequisites Before the first `make dist-x86_64`: 1. **Source checkouts under `.local/`** — pinned by you, not fetched by the build. There is no fetch target; clone the revision you want shipped: ```sh git clone -b v52.0 https://github.com/cloud-hypervisor/cloud-hypervisor \ .local/cloud-hypervisor git clone https://gitlab.com/virtio-fs/virtiofsd .local/virtiofsd ``` 2. **An x86_64 kernel** at `kernel/vmlinuz-x86_64` (preferred) or `kernel/vmlinux-x86_64`. Build via `make -C kernel TARGET_ARCH=x86_64`. The build fails hard if neither exists — a tarball without a kernel is not usable. 3. **The Linux dev image.** `dist-x86_64` depends on the `linux-image` make target, so the `container build` cache handles this automatically; the first run takes a few minutes, subsequent runs are seconds. The dev image (`images/linux-dev/Dockerfile`) bundles Swiftly, the Static Linux SDK, the Rust toolchain (with `cargo-zigbuild`), a prebuilt `/opt/cross-x86_64-musl/` prefix containing zlib, xz, bzip2, libarchive, libcap-ng, and libseccomp built static-musl for x86_64, and a sibling `/opt/cross-x86_64-gnu/` prefix containing libcap-ng and libseccomp built as glibc-dynamic shared libraries for virtiofsd's link step. `scripts/build-musl-x86_64-deps.sh` and `scripts/build-glibc-x86_64-deps.sh` produce these prefixes at image build time. ## Running the build ```sh make dist-x86_64 ``` Drives `scripts/build-dist-x86_64.sh` inside the dev container via the `linux_run` macro. The container bind-mounts the repo at `/workspace`, so all build outputs land back on the host under `bin/dist-x86_64/`. ## Pipeline The script runs five build stages plus a packaging stage. Each build stage is gated by a freshness check (see [Rebuild gating](#rebuild-gating)) so unchanged components are skipped on subsequent runs. 1. **`cctl` cross-compile to x86_64-linux-musl.** `swift build --swift-sdk x86_64-swift-linux-musl --product cctl`. Always runs — this is the artifact under iteration, and Swift's incremental build is a near-no-op when nothing changed. 2. **`vminitd` + `vmexec` cross-compile to x86_64-linux-musl.** `make -C vminitd LIBC=musl MUSL_ARCH=x86_64`. The guest agent and process launcher; both run inside the VM as PID 1's children. 3. **`cloud-hypervisor` cross-compile to x86_64-unknown-linux-musl.** `cargo zigbuild --target x86_64-unknown-linux-musl --bin cloud-hypervisor` from `.local/cloud-hypervisor`. 4. **`virtiofsd` cross-compile to x86_64-unknown-linux-gnu.2.35.** `cargo zigbuild --target x86_64-unknown-linux-gnu.2.35` from `.local/virtiofsd`, with `scripts/patches/virtiofsd-skip-cap-drop-with-sandbox-none.patch` applied first. The patch is idempotent — applied if missing, skipped if already present, fails hard if it can't be applied cleanly. Unlike the other three host binaries, virtiofsd is **glibc-dynamic**: it expects the deployment host to provide glibc ≥ 2.35, `libseccomp.so.2`, and `libcap-ng.so.0`. Link-time `.so` files come from `/opt/cross-x86_64-gnu/`. 5. **`initfs.ext4` packaging.** `scripts/build-initfs.sh --vminitd … --vmexec … --ext4 …` stages the guest rootfs and writes a ready-to-mount ext4 image with the x86_64 guest binaries inside (loop mount where available, else `mke2fs -d`). The x86_64 tarball ships this raw ext4 and boots it via `cctl run --initfs`, so — unlike the arm64 flow — no `vminit` OCI image is built here. 6. **Stage and tar.** Always runs. Lays out the staging tree at `bin/dist-x86_64//`: ``` / ├── bin/ │ ├── cctl │ ├── cloud-hypervisor │ └── virtiofsd ├── kernel/ │ └── vmlinuz-x86_64 # or vmlinux-x86_64, whichever was found └── initfs.ext4 ``` Then `tar -czf bin/.tar.gz`. ## Rebuild gating By default, every stage skips when its output is up-to-date. Each freshness check has a corresponding `REBUILD_*=1` environment variable that forces the stage to rerun. | Stage | Skip condition | Force rebuild | | --- | --- | --- | | `cctl` x86 cross | (never skipped — always runs) | n/a | | `vminitd` + `vmexec` | both binaries exist under `bin/dist-x86_64/` AND nothing under `vminitd/Sources/`, `vminitd/Package.swift`, or `Sources/Containerization/SandboxContext/` is newer than them | `REBUILD_VMINITD=1` | | `cloud-hypervisor` | `bin/dist-x86_64/cloud-hypervisor` exists | `REBUILD_CH=1` | | `virtiofsd` | `bin/dist-x86_64/virtiofsd` exists | `REBUILD_VIRTIOFSD=1` | | `initfs.ext4` | exists AND is newer than both staged `vminitd` and `vmexec` (also implicitly skipped when `vminitd` was skipped) | `REBUILD_INITFS=1` | | native aarch64 `cctl` | only built when `initfs.ext4` is being rebuilt | `REBUILD_INITFS=1` | | stage tree + tar | (always runs) | n/a | The freshness checks intentionally use binary presence and source mtimes rather than content hashing — fast to evaluate, easy to bypass with `touch` or `rm`. There is no global "rebuild everything" switch by design; force the specific component you want, or `rm -rf bin/dist-x86_64/` for a full clean rebuild. `cloud-hypervisor` and `virtiofsd` only check binary presence (not source mtime against `.local/`). The pinned-source convention assumes you opt into rebuilds explicitly — the `REBUILD_CH=1` / `REBUILD_VIRTIOFSD=1` escape hatches exist for exactly that case. Walking the full Rust source tree on every run was the alternative; not worth the cost. ### Common rebuild scenarios - **Iterating on host-side `cctl` or `Containerization` Swift code:** just `make dist-x86_64`. Only the x86 cctl rebuild runs (and tar). - **Touched `vminitd` source or the proto:** `REBUILD_VMINITD=1` is picked up automatically by mtime; `make dist-x86_64`. `vminitd` and `initfs.ext4` rebuild. - **Pulled new `.local/cloud-hypervisor`:** `REBUILD_CH=1 make dist-x86_64`. - **Pulled new `.local/virtiofsd`:** `REBUILD_VIRTIOFSD=1 make dist-x86_64`. - **Suspect a stale artifact:** `rm -rf bin/dist-x86_64 && make dist-x86_64` for a full clean rebuild. ## Cross-compilation toolchain Two cross toolchains live side-by-side in the dev image. `cctl`, `vminitd`/`vmexec`, and `cloud-hypervisor` target `x86_64-linux-musl` and ship statically linked so the artifacts are host-libc independent. `virtiofsd` targets `x86_64-linux-gnu.2.35` and ships dynamically linked; the deployment host provides glibc, libseccomp, and libcap-ng. - **Swift** uses Apple's Static Linux SDK (`x86_64-swift-linux-musl`), installed into the dev image by `make linux-image` (Dockerfile `SWIFT_SDK_URL`/`SWIFT_SDK_CHECKSUM` build args). The same SDK is used for both `cctl` and `vminitd` cross-builds. - **Rust C cross-compiler is Zig.** For musl stages, `zig cc -target x86_64-linux-musl` is wrapped as `x86_64-linux-musl-{gcc,g++,ar,ranlib,strip}`. For virtiofsd, parallel `x86_64-linux-gnu-*` wrappers dispatch to `zig cc -target x86_64-linux-gnu.2.35`, plus an `x86_64-linux-gnu-ld` wrapper backed by LLVM's `ld.lld` (apt-installed). The `ld` wrapper is needed because libtool's shared-library detection probes the linker with `-m elf_x86_64`; the host's aarch64 `/usr/bin/ld` rejects that and would silently disable `.so` emission. The gnu `gcc`/`g++` wrappers intercept `-print-prog-name=ld` so libtool discovers the cross-ld wrapper instead of the host linker. The pinned `.2.35` glibc baseline determines the minimum host glibc; bumping it requires editing the wrapper scripts under `images/linux-dev/wrappers/`. Zig was chosen over musl.cc / gcc cross prebuilts because aarch64-hosted versions of those aren't published. - **Rust linker** is **not** set explicitly. `cargo-zigbuild` installs its own linker wrapper that strips Rust's self-contained musl crt files (which would otherwise collide with Zig's musl crt). Setting `CARGO_TARGET_*_LINKER` ourselves overrides that and produces duplicate-symbol link errors. - **`pkg-config`** points at `/opt/cross-x86_64-musl/lib/pkgconfig` for the musl stages; the virtiofsd block overrides it in a subshell to point at `/opt/cross-x86_64-gnu/lib/pkgconfig` so `libseccomp-sys` and `libcap-ng`'s `capng-sys` resolve against the glibc-dynamic `.so` files, not the static-musl `.a` archives. The musl prefix uses GNU ld linker scripts at `lib{seccomp,cap-ng}.so` to redirect dynamic-link requests into the static archives; the gnu prefix ships real shared libraries. The cross C dep prefixes are built by `scripts/build-musl-x86_64-deps.sh` and `scripts/build-glibc-x86_64-deps.sh` during `make linux-image`. Modifying either script invalidates that layer of the dev image and triggers a rebuild on the next `make dist-x86_64`. ## Troubleshooting - **`ERROR: missing .local/cloud-hypervisor source checkout`** — see Prerequisites. There is no fetch target; clone the revision you want pinned. - **`ERROR: no x86_64 kernel found`** — run `make -C kernel TARGET_ARCH=x86_64`. The build refuses to ship a tarball without a kernel. - **`ERROR: virtiofsd cap-drop patch does not apply cleanly`** — the patch only applies to known-good upstream revisions of virtiofsd. If you bumped `.local/virtiofsd` past that, refresh `scripts/patches/virtiofsd-skip-cap-drop-with-sandbox-none.patch` against the new revision. - **Stale binary on the deployment host** — confirm the tarball SHA in `bin/containerization-x86_64-.tar.gz` matches `git rev-parse --short HEAD`. The script tags the tarball with `HEAD` at build time; uncommitted changes ship under the same SHA as their parent commit. - **Linker errors mentioning duplicate `crt*.o` symbols** — something is setting `CARGO_TARGET_*_LINKER`. Unset it and let `cargo-zigbuild` manage the linker. - **`virtiofsd: error while loading shared libraries: libseccomp.so.2`** (or `libcap-ng.so.0`) on the deployment host — install the system packages (`apt install libseccomp2 libcap-ng0` on Debian/Ubuntu, `dnf install libseccomp libcap-ng` on Fedora/RHEL). `virtiofsd` is glibc-dynamic by design; the libs are not bundled in the tarball. - **`virtiofsd: /lib/x86_64-linux-gnu/libc.so.6: version 'GLIBC_2.35' not found`** — the deployment host's glibc is older than the build's baseline. Either upgrade the host or rebuild with a lower baseline by editing the `-target x86_64-linux-gnu.` arg in `images/linux-dev/wrappers/x86_64-linux-gnu-{gcc,g++}` and the `cargo zigbuild --target x86_64-unknown-linux-gnu.` line in `scripts/build-dist-x86_64.sh`. --- ### CONTRIBUTING # 🌈 📦️ Welcome to the Containerization community! 📦️ 🌈 Contributions to Containerization are welcomed and encouraged. ## Index - [How you can help](#how-you-can-help) - [Submitting issues and pull requests](#submitting-issues-and-pull-requests) - [New to open source?](#new-to-open-source) - [AI contribution guidelines](#ai-contribution-guidelines) - [Code of conduct](#code-of-conduct) ## How you can help We would love your contributions in the form of: 🐛 Bug fixes\ ⚡️ Performance improvements\ ✨ API additions or enhancements\ 📝 Documentation\ 🧑‍💻 Project advocacy: blogs, conference talks, and more Anything else that could enhance the project! ## Submitting issues and pull requests ### Issues To file a bug or feature request, use [GitHub issues](https://github.com/apple/containerization/issues/new). 🚧 For unexpected behavior or usability limitations, detailed instructions on how to reproduce the issue are appreciated. This will greatly help the priority setting and speed at which maintainers can get to your issue. ### Pull requests We require all commits be signed with any of GitHub's supported methods, such as GPG or SSH. Information on how to set this up can be found on [GitHub's docs](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification#about-commit-signature-verification). To make a pull request, use [GitHub](https://github.com/apple/containerization/compare). Please give the team a few days to review but it's ok to check in on occasion. We appreciate your contribution! > [!IMPORTANT] > If you plan to make substantial changes or add new features, we encourage you to first discuss them with the wider containerization developer community. > You can do this by filing a [GitHub issue](https://github.com/apple/containerization/issues/new). > This will save time and increases the chance of your pull request being accepted. We use a "squash and merge" strategy to keep our `main` branch history clean and easy to follow. When your pull request is merged, all of your commits will be combined into a single commit. With the "squash and merge" strategy, the *title* and *body* of your pull request is extremely important. It will become the commit message for the squashed commit. Think of it as the single, definitive description of your contribution. Before merging, we'll review the pull request title and body to ensure it: * Clearly and concisely describes the changes. * Uses the imperative mood (for example, "Add feature," "Fix bug"). * Provides enough context for future developers to understand the purpose of the change. The pull request description should be concise and accurately describe the *what* and *why* of your changes. #### .gitignore contributions We do not currently accept contributions to add editor specific additions to the root .gitignore. We urge contributors to make a global .gitignore file with their rulesets they may want to add instead. A global .gitignore file can be set like so: ```bash git config --global core.excludesfile ~/.gitignore ``` #### Formatting contributions Make sure your contributions are consistent with the rest of the project's formatting. You can do this using our Makefile: ```bash make fmt ``` #### Applying license header to new files If you submit a contribution that adds a new file, please add the license header. You can do this using our Makefile: ```bash make update-licenses ``` ## New to open source? ### How do I pick something to work on? Take a look at the `good first issue` label in the [containerization](https://github.com/apple/containerization/contribute) or [container](https://github.com/apple/container/contribute) project. Before you start working on an issue: * Check the comments, assignees, and any references to pull requests — make sure nobody else is actively working on it, or awaiting help or review. * If someone is assigned to the issue or volunteered to work on it, and there are no signs of progress or activity over at least the past month, don't hesitate to check in with them * Leave a comment that you have started working on it. ### Getting help Don't be afraid to ask for help! When asking for help, provide as much information as possible, while highlighting anything you think may be important. Refer to the [MAINTAINERS.txt](MAINTAINERS.txt) file for the appropriate people to ping. ### I didn't get a response from someone. What should I do? It's possible that you ask someone a question in an issue/pull request and you don't get a response as quickly as you'd like. If you don't get a response within a week, it's okay to politely ping them using an `@` mention. If you don't get a response for 2-3 weeks in a row, please ping someone else. ### I can't finish the contribution I started Sometimes an issue ends up bigger, harder, or more time-consuming than expected — **and that’s completely fine.** Be sure to comment on the issue saying you’re stepping away, so that someone else is able to pick it up. ## AI contribution guidelines We welcome thoughtful use of AI tools in your contributions to this repository. We ask that you adhere to these rules in order to preserve the project's integrity, clarity, and quality, and to respect maintainer bandwidth: * You should be able to explain and justify every line of code or documentation that was generated or assisted by AI. Your submission should reflect your own understanding and intent. * Use AI to augment, not totally replace, your reasoning or familiarity, especially for non-trivial parts of the system. * Avoid dumping AI-generated walls of text that you cannot explain. Low-effort, unexplained submissions will be deprioritized to protect maintainer bandwidth. AI tools should be used to **enhance, not replace** the human elements that make OSS special: learning, collaboration, and community growth. ## Code of conduct To clarify what is expected of our contributors and community members, the Containerization team has adopted the code of conduct defined by the Contributor Covenant. This document is used across many open source communities and articulates our values well. For more detail, please read the [Code of Conduct](https://github.com/apple/.github/blob/main/CODE_OF_CONDUCT.md "Code of Conduct"). --- ### README

Containerization logo  Containerization

The Containerization package allows applications to use Linux containers. Containerization is written in [Swift](https://www.swift.org) and uses [Virtualization.framework](https://developer.apple.com/documentation/virtualization) on Apple silicon. > **Looking for command line binaries for running containers?**\ > They are available in the dedicated [apple/container](https://github.com/apple/container) repository. Containerization provides APIs to: - [Manage OCI images](./Sources/ContainerizationOCI/). - [Interact with remote registries](./Sources/ContainerizationOCI/Client/). - [Create and populate ext4 file systems](./Sources/ContainerizationEXT4/). - [Interact with the Netlink socket family](./Sources/ContainerizationNetlink/). - [Create an optimized Linux kernel for fast boot times](./kernel/). - [Spawn lightweight virtual machines and manage the runtime environment](./Sources/Containerization/LinuxContainer.swift). - [Spawn and interact with containerized processes](./Sources/Containerization/LinuxProcess.swift). - Use Rosetta 2 for running linux/amd64 containers on Apple silicon. Please view the [API documentation](https://apple.github.io/containerization/documentation/) for information on the Swift packages that Containerization provides. ## Design Containerization executes each Linux container inside of its own lightweight virtual machine. Clients can create dedicated IP addresses for every container to remove the need for individual port forwarding. Containers achieve sub-second start times using an optimized [Linux kernel configuration](/kernel) and a minimal root filesystem with a lightweight init system. [vminitd](/vminitd) is a small init system, which is a subproject within Containerization. `vminitd` is spawned as the initial process inside of the virtual machine and provides a GRPC API over vsock. The API allows the runtime environment to be configured and containerized processes to be launched. `vminitd` provides I/O, signals, and events to the calling process when a process is run. ## Backends Containerization abstracts the VMM behind the `VirtualMachineManager` / `VirtualMachineInstance` protocols and ships two implementations: - **macOS — Virtualization.framework** (`VZVirtualMachineManager`). The shipping path on Apple silicon. Uses Apple's `Virtualization` framework directly; no extra binaries required. - **Linux — cloud-hypervisor + KVM** (`CHVirtualMachineManager`). One `cloud-hypervisor` subprocess per VM, controlled over its REST-on-UDS API by the standalone [`CloudHypervisor`](./Sources/CloudHypervisor) Swift package. Block storage uses virtio-blk, shared directories use virtio-fs (one `virtiofsd` per share), networking uses TAP, and the guest agent is reached over cloud-hypervisor's hybrid vsock — same `vminitd` contract as the macOS path, so guest-side semantics are unchanged. The Linux backend requires: - `cloud-hypervisor` and `virtiofsd` on the host. Both are looked up on `PATH` by default; `CHVirtualMachineManager.init` accepts explicit URLs to override. `virtiofsd` is resolved lazily — a VM that uses only block-device mounts can run without it installed at all. Recent stable releases of each are recommended (smoke testing pins specific versions). - KVM access (`/dev/kvm` readable + writable by the calling user). - Pre-staged TAP / bridge / NAT plumbing if the container needs networking. `TAPInterface` consumes an existing TAP device by name; bringing it up, attaching it to a bridge, and configuring NAT or routing is the caller's responsibility. The integration test suite (`make linux-integration`) runs inside an apple/container Linux VM with nested virt enabled (`container run --virtualization`). The kata kernel fetched by `make fetch-default-kernel` does not enable KVM, so the integration suite uses the in-repo kernel at `kernel/vmlinux-arm64` (or `kernel/vmlinuz-x86_64` on x86_64 hosts) instead — build it with `make -C kernel` before invoking `make linux-integration`. On Linux the suite runs only the cross-platform scenarios that don't depend on macOS-only types; the full suite remains macOS-only for now. ## Requirements To build the Containerization package, you need: - Mac with Apple silicon - macOS 26 - Xcode 26 Older versions of macOS are not supported. ## Example Usage For examples of how to use the libraries' API surface, the cctl executable is a good start. This app is a useful playground for exploring the API. It contains commands that exercise some of the core functionality of the various products, such as: 1. [Manipulating OCI images](./Sources/cctl/ImageCommand.swift) 2. [Logging in to container registries](./Sources/cctl/LoginCommand.swift) 3. [Creating root filesystem blocks](./Sources/cctl/RootfsCommand.swift) 4. [Running simple Linux containers](./Sources/cctl/RunCommand.swift) ## Linux kernel A Linux kernel is required for spawning lightweight virtual machines on macOS. Containerization provides an optimized kernel configuration located in the [kernel](./kernel) directory. This directory includes a containerized build environment to easily compile a kernel for use with Containerization. The kernel configuration is a minimal set of features to support fast start times and a lightweight environment. While this configuration will work for the majority of workloads we understand that some will need extra features. To solve this Containerization provides first class APIs to use different kernel configurations and versions on a per container basis. This enables containers to be developed and validated across different kernel versions. See the [README](/kernel/README.md) in the kernel directory for instructions on how to compile the optimized kernel. ### Kernel Support Containerization allows user provided kernels but tests functionality starting with kernel version `6.14.9`. ### Pre-built Kernel If you wish to consume a pre-built kernel, make sure it has `VIRTIO` drivers compiled into the kernel (not merely as modules). The [Kata Containers](https://github.com/kata-containers/kata-containers) project provides a Linux kernel that is optimized for containers, with all required configuration options enabled. The [releases](https://github.com/kata-containers/kata-containers/releases/) page contains downloadable artifacts, and the image itself (`vmlinux.container`) can be found in the `/opt/kata/share/kata-containers/` directory. ## Prepare to build package Install the recommended version of Xcode. Set the active developer directory to the installed Xcode (replace ``): ```bash sudo xcode-select -s ``` The Linux guest init (`vminitd`/`vmexec`) is compiled as a static binary *inside a Linux container* rather than cross-compiled on your Mac, so no Swift toolchain, Swiftly, or Static Linux SDK setup is required on the host. Install the [`container`](https://github.com/apple/container) CLI, which the build uses to compile the guest: ```bash # Install per https://github.com/apple/container, then verify it is on PATH: container --version ``` The first build automatically builds the Linux dev image used to compile the guest, which can take a few minutes. ## Build the package Build Containerization from sources: ```bash make all ``` ## Test the package After building, run basic and integration tests: ```bash make test integration ``` A kernel is required to run integration tests. If you do not have a kernel locally, a default kernel can be fetched using the `make fetch-default-kernel` target. Fetching the default kernel only needs to happen after an initial build or after a `make clean`. ```bash make fetch-default-kernel make all test integration ``` ## Protobufs Containerization depends on specific versions of `grpc-swift` and `swift-protobuf`. You can install them and re-generate RPC interfaces with: ```bash make protos ``` ## Building a kernel If you'd like to build your own kernel please see the instructions in the [kernel directory](./kernel/README.md). ## Pre-commit hook Run `make pre-commit` to install a pre-commit hook that ensures that your changes have correct formatting and license headers when you run `git commit`. ## Documentation Generate the API documentation for local viewing with: ```bash make docs make serve-docs ``` Preview the documentation by running in another terminal: ```bash open http://localhost:8000/containerization/documentation/ ``` ## Contributing Contributions to Containerization are welcomed and encouraged. Please see [CONTRIBUTING.md](/CONTRIBUTING.md) for more information. ## Project Status Version 0.1.0 is the first official release of Containerization. Earlier versions have no source stability guarantees. Because the Containerization library is under active development, source stability is only guaranteed within minor versions (for example, between 0.1.1 and 0.1.2). If you don't want potentially source-breaking package updates, you can specify your package dependency using .upToNextMinorVersion(from: "0.1.0") instead. Future minor versions of the package may introduce changes to these rules as needed. --- ### SECURITY # Security disclosure process If you believe that you have discovered a security or privacy vulnerability in our open source software, please report it to us using the [GitHub private vulnerability feature](https://github.com/apple/containerization/security/advisories/new). Reports should include specific product and software version(s) that you believe are affected; a technical description of the behavior that you observed and the behavior that you expected; the steps required to reproduce the issue; and a proof of concept or exploit. The project team will do their best to acknowledge receiving all security reports within 7 days of submission. This initial acknowledgment is neither acceptance nor rejection of your report. The project team may come back to you with further questions or invite you to collaborate while working through the details of your report. Keep these additional guidelines in mind when submitting your report: * Reports concerning known, publicly disclosed CVEs can be submitted as normal issues to this project. * Output from automated security scans or fuzzers MUST include additional context demonstrating the vulnerability with a proof of concept or working exploit. * Application crashes due to malformed inputs are typically not treated as security vulnerabilities, unless they are shown to also impact other processes on the system. While we welcome reports for open source software projects, they are not eligible for Apple Security Bounties. ---