diff --git a/docs/concepts/flox-vs-containers.md b/docs/concepts/flox-vs-containers.md index 6b8cfb09..10bf478c 100644 --- a/docs/concepts/flox-vs-containers.md +++ b/docs/concepts/flox-vs-containers.md @@ -424,6 +424,10 @@ you need to build a container so that it can be deployed. You can also produce build artifacts from a Flox environment. See the [builds documentation][builds] for more information. + For an alternative that doesn't require image rebuilds, see + [Thin Containers][thin-containers], which resolve environments at + startup from a shared Nix store. + === "Containers" Typically your `Dockerfile` will contain multiple stages, @@ -447,3 +451,4 @@ you need to build a container so that it can be deployed. [manifest]: ../concepts/environments.md#manifesttoml [builds]: ../concepts/builds.md [ci-cd]: ../tutorials/ci-cd.md +[thin-containers]: ../containers/thin-containers/intro.md diff --git a/docs/containers/containerize/getting-started.md b/docs/containers/containerize/getting-started.md new file mode 100644 index 00000000..bea7d70d --- /dev/null +++ b/docs/containers/containerize/getting-started.md @@ -0,0 +1,118 @@ +--- +title: "Getting started with Containerize" +description: "Build a container image from a Flox environment." +--- + +# Getting started with Containerize + +This guide walks you through building a traditional OCI container image from a Flox environment using [`flox containerize`][containerize-man]. + +!!! tip + If you don't need a self-contained image, consider using [thin containers](../thin-containers/intro.md) instead. + Thin containers resolve environments at startup and don't require image rebuilds when your environment changes. + +## Prerequisites + +- The [Flox CLI][flox-install] +- [Docker][docker-install] or [Podman][podman-install] (required on macOS; optional on Linux) + +## 1. Create an environment + +Create a new environment and install some packages: + +```{ .bash .copy } +mkdir myproject && cd myproject +flox init +flox install hello curl +``` + +## 2. Build the image + +Load the image directly into your container runtime: + +```{ .bash .copy } +flox containerize --runtime docker +``` + +Alternatively, write the image to a file: + +```{ .bash .copy } +flox containerize -f myproject.tar +``` + +You can then load the file into Docker manually: + +```{ .bash .copy } +docker load -i myproject.tar +``` + +!!! note "macOS" + On macOS, `flox containerize` uses a proxy container (Docker or Podman) to build the Linux image. + You may be prompted for file-sharing permissions on the first run. + +## 3. Run the container interactively + +```{ .bash .copy } +docker run --rm -it +``` + +You'll be dropped into a shell with the environment activated --- all your packages and environment variables are available: + +```{ .console .no-copy } +[floxenv] $ hello +Hello, world! +[floxenv] $ curl --version +curl 8.x.x ... +``` + +## 4. Run a command directly + +```{ .bash .copy } +docker run --rm hello +``` + +```{ .console .no-copy } +Hello, world! +``` + +This runs the command inside the activated environment without starting an interactive shell, similar to `flox activate -- hello`. + +## 5. Tag and push + +Build with a specific tag: + +```{ .bash .copy } +flox containerize --tag v1 --runtime docker +``` + +Then push to a registry: + +```{ .bash .copy } +docker tag :v1 myregistry.example.com/myproject:v1 +docker push myregistry.example.com/myproject:v1 +``` + +## 6. Customize the image + +You can configure OCI metadata for the container image in the `[containerize.config]` section of your manifest. +Run `flox edit` and add: + +```toml +[containerize.config] +working-dir = "/app" +exposed-ports = ["8080/tcp"] +cmd = ["hello"] +``` + +See the [`flox containerize` reference][containerize-man] for the full list of configuration options, including `user`, `volumes`, `labels`, and `stop-signal`. + +## Next steps + +- Read about [how containerize differs from thin containers](../tech.md) at a technical level +- Learn about [thin containers](../thin-containers/intro.md) for faster iteration without image rebuilds +- See the full [`flox containerize` reference][containerize-man] for all CLI options + +[containerize-man]: ../../man/flox-containerize.md +[flox-install]: ../../install-flox/install.md +[docker-install]: https://docs.docker.com/get-docker/ +[podman-install]: https://podman.io/docs/installation diff --git a/docs/containers/containerize/intro.md b/docs/containers/containerize/intro.md new file mode 100644 index 00000000..7860a486 --- /dev/null +++ b/docs/containers/containerize/intro.md @@ -0,0 +1,47 @@ +--- +title: "Containerize" +description: "Build traditional OCI container images from Flox environments." +--- + +# Containerize + +[`flox containerize`][containerize-man] exports a Flox environment as a standard OCI container image with all dependencies baked in at build time. +Unlike [thin containers](../thin-containers/intro.md) and [Imageless Kubernetes](../imageless-kubernetes/intro.md), the resulting image does **not** use Flox or the Nix store at runtime --- it's a conventional container image that can be pushed to any registry and run anywhere. + +## Consider thin containers first + +Before reaching for `flox containerize`, consider whether [thin containers](../thin-containers/intro.md) or [Imageless Kubernetes](../imageless-kubernetes/intro.md) would be a better fit for your use case. +With `flox containerize`, you give up several advantages of the thin-container model: + +| | Thin Containers | Containerize | +| --- | --- | --- | +| **Image rebuilds** | Not needed --- environments resolve at startup | Required on every environment change | +| **Caching** | Shared Nix store across all environments | Each image is self-contained | +| **Image size** | Tiny base image; packages from shared store | All packages baked into the image | +| **FloxHub management** | Centralized --- changes propagate automatically | Frozen at build time | +| **Iteration speed** | ~5s startup (after first run) | Rebuild + push + pull cycle | + +## When to use `flox containerize` + +`flox containerize` is the right choice when deploying to infrastructure that **requires standard container images** and cannot support a mounted Nix store volume: + +- Container registries and orchestrators that expect self-contained images (e.g., AWS ECS, Docker Swarm, cloud functions) +- Environments where volume mounts are restricted or unavailable +- Distribution to users who don't have Flox or a Nix store + +## What you still get + +Even though `flox containerize` uses the traditional model, the images it produces are superior to hand-written Dockerfiles: + +- **Fully pinned** --- the same lockfile that drives your development environment drives the image, so you get identical software down to the Git revisions of upstream source repositories +- **Cross-platform** --- define one environment, build images for multiple architectures +- **Reproducible** --- the same lockfile always produces the same image contents +- **Configurable** --- set OCI metadata (ports, volumes, labels, user, working directory) via the manifest's `[containerize.config]` section + +## Next steps + +Follow the [getting started guide](getting-started.md) to build your first container image from a Flox environment. + +See the [`flox containerize` reference][containerize-man] for the full list of CLI options and manifest configuration. + +[containerize-man]: ../../man/flox-containerize.md diff --git a/docs/imageless-kubernetes/config.md b/docs/containers/imageless-kubernetes/config.md similarity index 95% rename from docs/imageless-kubernetes/config.md rename to docs/containers/imageless-kubernetes/config.md index 81cf3a77..709d0ffb 100644 --- a/docs/imageless-kubernetes/config.md +++ b/docs/containers/imageless-kubernetes/config.md @@ -24,7 +24,7 @@ flox auth token \ ``` !!! note "Token expiry" - Tokens generated with `flox auth token` are associated with your user account and will expire 1 month from when they were issued. For a more robust alternative see [Machine Access Tokens for Organizations](../concepts/organizations.md#machine-access-tokens). + Tokens generated with `flox auth token` are associated with your user account and will expire 1 month from when they were issued. For a more robust alternative see [Machine Access Tokens for Organizations](../../concepts/organizations.md#machine-access-tokens). !!! note "Flox CLI version" The user creating the token via `flox auth token` will need at least version 1.7.6 of the Flox CLI. @@ -106,7 +106,7 @@ By default, Imageless Kubernetes pods start in `run` mode. `run` mode is intende The `flox.dev/activate-mode` annotation can be used to configure the mode, which may be useful for applications such as running CI jobs in Flox-enabled pods. -See the [`options.activate.mode`](../man/manifest.toml.md#options) option in the manifest for more details on modes. +See the [`options.activate.mode`](../../man/manifest.toml.md#options) option in the manifest for more details on modes. ```yaml apiVersion: v1 @@ -200,6 +200,6 @@ metadata: The difference from `skip-containers` is that while `skip-containers-exec` containers will have their main process run from the Flox environment, commands run via `kubectl exec` or equivalent will be run outside of it. This option is best used when you want the container's main workload to run in the Flox environment, but need exec commands (for debugging, health checks, or auxiliary tasks) to run in the base container environment without Flox. [intro]: ./intro.md -[floxhub]: ../concepts/floxhub.md -[flox_auth]: ../man/flox-auth.md -[generations]: ../concepts/generations.md +[floxhub]: ../../concepts/floxhub.md +[flox_auth]: ../../man/flox-auth.md +[generations]: ../../concepts/generations.md diff --git a/docs/imageless-kubernetes/examples/gitlab-ci.md b/docs/containers/imageless-kubernetes/examples/gitlab-ci.md similarity index 98% rename from docs/imageless-kubernetes/examples/gitlab-ci.md rename to docs/containers/imageless-kubernetes/examples/gitlab-ci.md index e23898c5..54c0a010 100644 --- a/docs/imageless-kubernetes/examples/gitlab-ci.md +++ b/docs/containers/imageless-kubernetes/examples/gitlab-ci.md @@ -66,4 +66,4 @@ Since the CI environment doesn’t rely on a container image, updates are instan [gitlab-k8s-docs]: https://docs.gitlab.com/runner/executors/kubernetes/ [config]: ../config.md -[floxhub]: ../../concepts/floxhub.md +[floxhub]: ../../../concepts/floxhub.md diff --git a/docs/imageless-kubernetes/examples/kind-demo.md b/docs/containers/imageless-kubernetes/examples/kind-demo.md similarity index 100% rename from docs/imageless-kubernetes/examples/kind-demo.md rename to docs/containers/imageless-kubernetes/examples/kind-demo.md diff --git a/docs/imageless-kubernetes/install/eks.md b/docs/containers/imageless-kubernetes/install/eks.md similarity index 100% rename from docs/imageless-kubernetes/install/eks.md rename to docs/containers/imageless-kubernetes/install/eks.md diff --git a/docs/imageless-kubernetes/install/self-managed.md b/docs/containers/imageless-kubernetes/install/self-managed.md similarity index 99% rename from docs/imageless-kubernetes/install/self-managed.md rename to docs/containers/imageless-kubernetes/install/self-managed.md index 0efa241d..aadaab8c 100644 --- a/docs/imageless-kubernetes/install/self-managed.md +++ b/docs/containers/imageless-kubernetes/install/self-managed.md @@ -150,6 +150,6 @@ Once the nodes have Flox and the shim installed, you are ready to create pods us A sample `Pod` manifest is available in the [Introduction][intro-section], but any Kubernetes resource that creates a pod (e.g. `Deployment`) can be used by setting the `runtimeClassName` parameter to `flox`. [intro-section]: ../intro.md -[install-flox]: ../../install-flox/install.md +[install-flox]: ../../../install-flox/install.md [shim-installer]: https://hub.flox.dev/flox/containerd-shim-flox-installer [runtime-class]: https://kubernetes.io/docs/concepts/containers/runtime-class/ diff --git a/docs/imageless-kubernetes/install/troubleshooting.md b/docs/containers/imageless-kubernetes/install/troubleshooting.md similarity index 100% rename from docs/imageless-kubernetes/install/troubleshooting.md rename to docs/containers/imageless-kubernetes/install/troubleshooting.md diff --git a/docs/imageless-kubernetes/install/uninstall.md b/docs/containers/imageless-kubernetes/install/uninstall.md similarity index 96% rename from docs/imageless-kubernetes/install/uninstall.md rename to docs/containers/imageless-kubernetes/install/uninstall.md index 6c5d6557..19c713fe 100644 --- a/docs/imageless-kubernetes/install/uninstall.md +++ b/docs/containers/imageless-kubernetes/install/uninstall.md @@ -59,4 +59,4 @@ rm /usr/local/bin/containerd-shim-flox-v2 And finally, uninstall Flox from each node by following the instructions from the [Uninstall Flox][uninstall-flox] page. [self-managed]: ./self-managed.md -[uninstall-flox]: ../../install-flox/uninstall.md +[uninstall-flox]: ../../../install-flox/uninstall.md diff --git a/docs/imageless-kubernetes/install/upgrading.md b/docs/containers/imageless-kubernetes/install/upgrading.md similarity index 95% rename from docs/imageless-kubernetes/install/upgrading.md rename to docs/containers/imageless-kubernetes/install/upgrading.md index eaf33bf4..dfc603a4 100644 --- a/docs/imageless-kubernetes/install/upgrading.md +++ b/docs/containers/imageless-kubernetes/install/upgrading.md @@ -31,4 +31,4 @@ after which, all new pods will be created with the new shim version. Existing Flox pods will only use the new version once they are restarted. [eks]: ./eks.md -[install-flox]: ../../install-flox/install.md +[install-flox]: ../../../install-flox/install.md diff --git a/docs/imageless-kubernetes/intro.md b/docs/containers/imageless-kubernetes/intro.md similarity index 98% rename from docs/imageless-kubernetes/intro.md rename to docs/containers/imageless-kubernetes/intro.md index 32c46e40..49dbf47c 100644 --- a/docs/imageless-kubernetes/intro.md +++ b/docs/containers/imageless-kubernetes/intro.md @@ -84,6 +84,6 @@ Imageless Kubernetes is also currently available for: See the [installation][install-section] for more details on installing Imageless Kubernetes in your cluster. -[generations-concept]: ../concepts/generations.md +[generations-concept]: ../../concepts/generations.md [install-section]: ./install/eks.md [examples-section]: ./examples/kind-demo.md diff --git a/docs/containers/intro.md b/docs/containers/intro.md new file mode 100644 index 00000000..f6590634 --- /dev/null +++ b/docs/containers/intro.md @@ -0,0 +1,63 @@ +--- +title: "Flox in Containers" +description: "Run Flox environments inside containers for isolation, reproducibility, and fast iteration." +--- + +# Flox in Containers + +Flox environments can run inside containers, giving you isolated, reproducible execution with the same packages you use during development. +The key difference from traditional container workflows is that packages live in a shared [Nix store][nix-store] mounted into the container rather than baked into the image. +This eliminates image rebuilds, enables shared caching across environments, and dramatically speeds up iteration. + +## Choosing an approach + +Flox offers three ways to run environments in containers. +The first two use the thin-container model described above; the third is a traditional approach included for compatibility. + +### Thin Containers (Docker / Podman) {: .recommended } + + +**Recommended for: local development, CI/CD, AI agent sandboxing** + +Run any FloxHub environment in a Docker or Podman container with a single command, or use the `--sandbox` flag on `flox activate` for a seamless experience. +Packages are cached in a shared Nix store volume, so only the first run is slow (~30-60s); subsequent runs start in ~5 seconds. + +No image builds. No Dockerfiles. No image pipelines. + +[Get started with Thin Containers :material-arrow-right:](thin-containers/intro.md){ .md-button } + +### Imageless Kubernetes + + +**Recommended for: production Kubernetes workloads** + +Run Kubernetes pods backed by Flox environments instead of container images. +A containerd shim resolves environments from FloxHub at pod startup, giving you centralized management, an audit trail of changes, and the same software you used during development. + +[Get started with Imageless Kubernetes :material-arrow-right:](imageless-kubernetes/intro.md){ .md-button } + +### Containerize + + +**Traditional approach: when standard OCI images are required** + +[`flox containerize`][containerize-man] builds a self-contained OCI image from a Flox environment with all dependencies baked in. +Unlike thin containers and Imageless Kubernetes, the resulting image does **not** use Flox or the Nix store at runtime --- it's a conventional container image. + +Use this only when deploying to infrastructure that requires standard container images and cannot support the thin-container model. +The trade-offs are significant: + +- Images must be rebuilt every time the environment changes +- No shared caching --- each image is self-contained +- Larger image sizes compared to the thin-container approach +- No centralized management via FloxHub + +[Get started with Containerize :material-arrow-right:](containerize/intro.md){ .md-button } + +## How it works + +All three approaches build on the same foundation: Flox environments backed by Nix. +See [How it works](tech.md) for the technical details of how packages are resolved and mounted inside containers. + +[nix-store]: https://nix.dev/manual/nix/latest/store/ +[containerize-man]: ../man/flox-containerize.md diff --git a/docs/containers/tech.md b/docs/containers/tech.md new file mode 100644 index 00000000..d09b9131 --- /dev/null +++ b/docs/containers/tech.md @@ -0,0 +1,97 @@ +--- +title: "How it works" +description: "The technology behind running Flox environments inside containers." +--- + +# How it works + +Flox is a language-agnostic package and environment manager built on [Nix][nix]. +Every environment produces a lockfile when built, so anyone using Flox can reproduce the exact same set of packages. +This makes Flox environments a natural fit for containers: the same environment works on your machine, in CI, and inside a container. + +There are two fundamentally different ways to get a Flox environment into a container, and the choice determines how the container behaves at runtime. + +## The thin-container model + +Thin containers resolve Flox environments **at container startup** rather than baking dependencies into the image at build time. +This is the model used by both [Thin Containers](thin-containers/intro.md) (Docker/Podman) and [Imageless Kubernetes](imageless-kubernetes/intro.md). + +### Base images + +The two thin-container approaches use different base images: + +- **Docker / Podman** use the [`flox/thin`][flox-thin] image, which is an Ubuntu-based image containing the Flox CLI, Nix, and an entrypoint that resolves environments and activates them inside the container. +- **Imageless Kubernetes** uses the [`flox/empty`][flox-empty] image, which is only a few bytes --- it exists to satisfy Kubernetes's requirement for an image reference. Environment resolution is handled externally by the [containerd shim](#containerd-shim). + +In both cases, the actual packages come from the Nix store, not the image. + +### The Nix store volume + +Packages are stored in a persistent volume mounted at `/nix` inside the container. +For Docker and Podman, this is a named volume (e.g., `flox-store:/nix`) that persists across container runs. + +The first time you run a container with a given environment, Flox populates the Nix store with the required packages. +This takes 30--60 seconds depending on the environment size. +On subsequent runs, the packages are already cached in the volume, so startup drops to roughly 5 seconds. + +Because the Nix store is content-addressed, packages shared between different environments are stored only once. +Running `flox/redis` and `flox/python-pip` on the same host shares common dependencies automatically. + +### Environment resolution + +At container startup, Flox resolves the environment definition: + +- **Remote environments**: pulled from FloxHub using the environment reference (e.g., `flox/redis`) +- **Local environments**: read from a `.flox/` directory mounted into the container + +Once resolved, Flox activates the environment inside the container, making all declared packages, environment variables, and hook scripts available. + +### Docker and Podman + +For Docker and Podman, the container image's entrypoint handles the full lifecycle: + +1. Start the Nix daemon (required for store operations inside the container) +2. Resolve the Flox environment from FloxHub or a local `.flox/` directory +3. Run `flox activate` to configure the shell with all packages and variables +4. Execute the user's command (or drop into an interactive shell) + +The `flox activate --sandbox` flag wraps this Docker machinery behind a single CLI flag, automatically handling volume mounts, TTY detection, and argument forwarding. + +### Kubernetes (containerd shim) {: #containerd-shim } + +For Kubernetes, the [`containerd-shim-flox-v2`][shim-repo] intercepts the container configuration before `runc` creates the container. + +![containerd](../img/containerd.png) + +The shim: + +1. Reads the Flox environment reference from pod annotations +2. Pulls the environment to the node so it can be mounted into the container +3. Modifies the container's command to run inside the Flox environment +4. Passes the modified configuration to `runc` + +This is transparent to the pod spec author --- they specify a Flox environment in an annotation and a command to run, and the shim handles the rest. + +## The traditional model: `flox containerize` + +[`flox containerize`][containerize-man] takes a fundamentally different approach. +It bundles **all** packages and dependencies into a self-contained OCI image at build time. +The resulting image does not use Flox or the Nix store at runtime --- it behaves like any conventional container image. + +This means the image must be rebuilt every time the environment changes, and there is no shared caching between environments. +However, the images are fully pinned and deterministic, producing better results than hand-written Dockerfiles. + +Use `flox containerize` only when deploying to infrastructure that requires standard container images and cannot support the thin-container model. +For all other cases, [Thin Containers](thin-containers/intro.md) or [Imageless Kubernetes](imageless-kubernetes/intro.md) provide significant advantages: + +- **No image rebuilds** --- environment changes take effect on the next container start +- **Shared caching** --- the Nix store volume is shared across all environments on a host +- **Faster iteration** --- ~5 second startup after the first run +- **Centralized management** --- environments are managed via FloxHub, not frozen in an image +- **Smaller footprint** --- the base image is tiny; packages come from the shared store + +[nix]: https://nix.dev/ +[flox-thin]: https://hub.docker.com/r/flox/thin +[flox-empty]: https://hub.docker.com/r/flox/empty +[shim-repo]: https://github.com/flox/containerd-shim-flox +[containerize-man]: ../man/flox-containerize.md diff --git a/docs/containers/thin-containers/getting-started.md b/docs/containers/thin-containers/getting-started.md new file mode 100644 index 00000000..f9aa773d --- /dev/null +++ b/docs/containers/thin-containers/getting-started.md @@ -0,0 +1,162 @@ +--- +title: "Getting started with Thin Containers" +description: "Run your first Flox environment in a Docker container in under a minute." +--- + +# Getting started with Thin Containers + +This guide walks you through running Flox environments in Docker containers, from your first command to using sandbox mode with your own projects. + +## Prerequisites + +- [Docker Desktop][docker-install] (macOS/Windows) or Docker Engine (Linux), or [Podman][podman-install] +- For sandbox mode (steps 5--6): the [Flox CLI][flox-install] + +## 1. Run your first thin container + +Run a command from a FloxHub environment: + +```{ .bash .copy } +docker run --rm -v flox-store:/nix \ + flox/thin flox/redis -- redis-server --version +``` + +Here's what happens: + +1. Docker pulls the lightweight `flox/thin` image (if not already cached) +2. The Nix store volume (`flox-store`) is created and mounted at `/nix` +3. Flox resolves the `flox/redis` environment from FloxHub and installs the packages +4. The `redis-server --version` command runs inside the activated environment + +!!! note + The first run takes 30--60 seconds as it populates the Nix store with packages. + This is a one-time cost --- subsequent runs reuse the cached store. + +## 2. See the caching in action + +Run another command from the same environment: + +```{ .bash .copy } +docker run --rm -v flox-store:/nix \ + flox/thin flox/redis -- redis-cli --version +``` + +This time it completes in ~5 seconds. +The packages are already in the `flox-store` volume, so there's nothing to download or build. + +## 3. Explore interactively + +Drop into an interactive shell inside the environment: + +```{ .bash .copy } +docker run --rm -it -v flox-store:/nix \ + flox/thin flox/redis +``` + +Inside the container, only the packages declared in the environment are available: + +```{ .console .no-copy } +# These work --- they're in the Flox environment +$ redis-server --version +Redis server v=7.x.x ... + +$ redis-cli --version +redis-cli 7.x.x + +# These don't --- isolation from the host +$ which vim +$ # not found +$ which curl +$ # not found +``` + +Type `exit` to leave the container. + +## 4. Try a different environment + +Run a Python environment to see that common packages are shared: + +```{ .bash .copy } +docker run --rm -v flox-store:/nix \ + flox/thin flox/python-pip -- python3 --version +``` + +Because the Nix store is content-addressed, packages shared between `flox/redis` and `flox/python-pip` (like `glibc`) are stored only once in the `flox-store` volume. + +## 5. Use sandbox mode + +If you have the Flox CLI installed, the `--sandbox` flag handles all the Docker details for you: + +```{ .bash .copy } +flox activate --sandbox -r flox/redis +``` + +Inside the sandbox you get the same isolated environment, but you didn't need to remember any Docker flags. + +Run a command directly: + +```{ .bash .copy } +flox activate --sandbox -r flox/redis -- redis-server --version +``` + +### Custom image registry + +If you're behind a firewall that blocks Docker Hub, use the `--container-image` flag to specify an alternative registry: + +```{ .bash .copy } +flox activate --sandbox \ + --container-image myregistry.example.com/flox/thin:latest \ + -r flox/redis +``` + +## 6. Sandbox with your project + +Sandbox mode mounts your current working directory into the container at `/work`. +Your code runs in isolation, but file changes persist on the host. + +Create a test script: + +```{ .bash .copy } +mkdir -p /tmp/sandbox-demo && cd /tmp/sandbox-demo +cat > hello.py << 'EOF' +import sys +print(f"Hello from sandbox! Python {sys.version}") +EOF +``` + +Run it in a sandbox: + +```{ .bash .copy } +flox activate --sandbox -r flox/python-pip -- python3 hello.py +``` + +```{ .console .no-copy } +Hello from sandbox! Python 3.12.x +``` + +The script ran inside the container, but `hello.py` is still on the host after the container exits. + +## 7. Cleanup + +Remove the cached Nix store volume when you no longer need it: + +```{ .bash .copy } +docker volume rm flox-store +``` + +Remove the demo files: + +```{ .bash .copy } +rm -rf /tmp/sandbox-demo +``` + +## Next steps + +- Read about [how thin containers work](../tech.md) under the hood +- Learn about [Imageless Kubernetes](../imageless-kubernetes/intro.md) for running the same model in production +- Explore [FloxHub][floxhub] to find environments to try + +[docker-install]: https://docs.docker.com/get-docker/ +[podman-install]: https://podman.io/docs/installation +[flox-install]: ../../install-flox/install.md +[floxhub]: ../../concepts/floxhub.md diff --git a/docs/containers/thin-containers/intro.md b/docs/containers/thin-containers/intro.md new file mode 100644 index 00000000..1c83a62d --- /dev/null +++ b/docs/containers/thin-containers/intro.md @@ -0,0 +1,70 @@ +--- +title: "Thin Containers" +description: "Run Flox environments in Docker or Podman containers without building images." +--- + +# Thin Containers + +Thin containers are a lightweight way to run Flox environments inside Docker or Podman containers. +Unlike traditional containers where all dependencies are baked into an image, thin containers resolve packages **at startup** from a shared Nix store volume. +This means: + +- **No image rebuilds** when your environment changes +- **Shared caching** across environments --- common packages are stored once +- **Fast startup** after the first run (~5 seconds vs. 30--60 seconds) +- **True isolation** from the host system --- only packages declared in the environment are available + +## Two ways to use thin containers + +### 1. Direct Docker or Podman commands + +Run any FloxHub environment with a single `docker run` command: + +```{ .bash .copy } +docker run --rm -v flox-store:/nix flox/thin flox/redis -- redis-server --version +``` + +This is useful when you don't have Flox installed on the host, or when integrating with existing Docker-based workflows. + +### 2. Sandbox mode (`flox activate --sandbox`) + +If you have the Flox CLI installed, the `--sandbox` flag wraps the Docker machinery behind a familiar interface: + +```{ .bash .copy } +flox activate --sandbox -r flox/redis +``` + +Sandbox mode automatically handles volume mounts, TTY detection, and argument forwarding. +Your current working directory is mounted into the container at `/work`, so your code runs in isolation but file changes persist on the host. + +## Prerequisites + +- **Docker Desktop** ([download][docker-install]) on macOS or Windows, or **Docker Engine** on Linux +- Alternatively, **Podman** ([download][podman-install]) +- For sandbox mode: the **Flox CLI** ([install][flox-install]) + +## Known limitations + +**macOS and Windows** +: Docker on macOS and Windows runs Linux containers. + Sandbox mode uses Linux packages, not native macOS or Windows packages. + This is acceptable for CI/CD, AI agent sandboxing, and testing, but is not a substitute for native `flox activate` for day-to-day macOS development. + +**First run performance** +: The first run with a new environment takes 30--60 seconds as it populates the Nix store. + Subsequent runs reuse the cached store and start in ~5 seconds. + +**Services** +: The `[services]` section of the manifest is not yet supported in sandbox mode. + +**Private environments** +: FloxHub authentication is passed through automatically when using `flox activate --sandbox`. + Direct Docker usage requires manually mounting the Flox config file. + +## Next steps + +Follow the [getting started guide](getting-started.md) for a step-by-step walkthrough. + +[docker-install]: https://docs.docker.com/get-docker/ +[podman-install]: https://podman.io/docs/installation +[flox-install]: ../../install-flox/install.md diff --git a/docs/imageless-kubernetes/tech.md b/docs/imageless-kubernetes/tech.md deleted file mode 100644 index f21e2167..00000000 --- a/docs/imageless-kubernetes/tech.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: "Tech" -description: "The tech behind Imageless Kubernetes" ---- - -# The Tech Behind Imageless Kubernetes - -Flox is a next-generation, language-agnostic package and environment manager. -With it you define "environments" that contain packages, environment variables, setup scripts, services, and more. -Every environment produces a lockfile when built so that anyone using Flox can reproduce the environment. -This means that the same environment works on your machine, your coworker's machine, in CI, and in production. - -From a user's perspective, activating a Flox environment places the user into a shell that contains all of the packages, variables, etc defined in their environment. -Contrast this with a container that contains a filesystem image that has been imperatively built via a Dockerfile or some other means. - -With Imageless Kubernetes you deploy pods that run commands inside of a Flox environment rather than a container instantiated from a container image. - -## containerd-shim - -Under the hood, Imageless Kubernetes works by wrapping `containerd-shim-runc-v2` to make Flox-specific modifications to the container config and filesystem. -The diagram below shows the high level overview of how Imageless Kubernetes works. - -![containerd](../img/containerd.png) - -Typically `containerd` produces a `config.json` describing the container's namespace requirements, mount points, etc. -This `config.json` is provided to a `containerd-shim` that then calls `runc` in order to create the container. -`runc` then creates and starts the container using the information in `config.json`. - -With Imageless Kubernetes, `containerd-shim-flox-v2` intercepts the container configuration to prepare the container with everything needed to run the Flox environment. -The shim performs a number of operations to prepare the container's filesystem, including pulling the specified Flox environment to the node so that it can be mounted into the container. - -The shim also modifies the container's command to run it in the context of the Flox environment rather than running the command directly. diff --git a/docs/tutorials/ci-cd.md b/docs/tutorials/ci-cd.md index 59779c44..65ce9aed 100644 --- a/docs/tutorials/ci-cd.md +++ b/docs/tutorials/ci-cd.md @@ -111,7 +111,7 @@ Now that you know _how_ to use your Flox environment in CI/CD, the world is your Here are some suggestions for things you can do with your Flox environment in CI: - Run a linter to ensure that new changes adhere to your team's style. -- Use [flox containerize][containerize] to build a container from your environment to deploy elsewhere. +- Use [flox containerize][containerize] to build a container from your environment to deploy elsewhere. See the [Containerize guide][containerize-guide] for a full walkthrough. - Build artifacts for multiple systems. - Run a link checker over your documentation. @@ -127,3 +127,4 @@ Here are some suggestions for things you can do with your Flox environment in CI [layering_guide]: ./layering-multiple-environments.md [customizing_guide]: ./customizing-environments.md [containerize]: ../man/flox-containerize.md +[containerize-guide]: ../containers/containerize/intro.md diff --git a/mkdocs.yml b/mkdocs.yml index 8aceab09..b69cd488 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -57,18 +57,26 @@ nav: - Installing Flox from its repository on Debian and Red Hat: tutorials/installing-from-repo.md - Migration guides: - ... | flat | tutorials/migrations/* - - Imageless Kubernetes: - - Introduction: imageless-kubernetes/intro.md - - Tech: imageless-kubernetes/tech.md - - Installation: - - Amazon EKS: imageless-kubernetes/install/eks.md - - Self-managed: imageless-kubernetes/install/self-managed.md - - Troubleshooting: imageless-kubernetes/install/troubleshooting.md - - Upgrading: imageless-kubernetes/install/upgrading.md - - Uninstall: imageless-kubernetes/install/uninstall.md - - Examples: - - ... | flat | imageless-kubernetes/examples/* - - Configuration: imageless-kubernetes/config.md + - Flox in Containers: + - Introduction: containers/intro.md + - How it works: containers/tech.md + - Thin Containers: + - Introduction: containers/thin-containers/intro.md + - Getting started: containers/thin-containers/getting-started.md + - Containerize: + - Introduction: containers/containerize/intro.md + - Getting started: containers/containerize/getting-started.md + - Imageless Kubernetes: + - Introduction: containers/imageless-kubernetes/intro.md + - Installation: + - Amazon EKS: containers/imageless-kubernetes/install/eks.md + - Self-managed: containers/imageless-kubernetes/install/self-managed.md + - Troubleshooting: containers/imageless-kubernetes/install/troubleshooting.md + - Upgrading: containers/imageless-kubernetes/install/upgrading.md + - Uninstall: containers/imageless-kubernetes/install/uninstall.md + - Examples: + - ... | flat | containers/imageless-kubernetes/examples/* + - Configuration: containers/imageless-kubernetes/config.md - Concepts: - Environments: concepts/environments.md - Activating environments: concepts/activation.md @@ -374,13 +382,23 @@ plugins: 'cookbook/languages/python.md': 'languages/python.md' 'cookbook/languages/ruby.md': 'languages/ruby.md' 'cookbook/languages/rust.md': 'languages/rust.md' - 'k8s/intro.md': 'imageless-kubernetes/intro.md' - 'k8s/tech.md': 'imageless-kubernetes/tech.md' - 'k8s/install/eks.md': 'imageless-kubernetes/install/eks.md' - 'k8s/install/self-managed.md': 'imageless-kubernetes/install/self-managed.md' - 'k8s/install/troubleshooting.md': 'imageless-kubernetes/install/troubleshooting.md' - 'k8s/install/upgrading.md': 'imageless-kubernetes/install/upgrading.md' - 'k8s/install/uninstall.md': 'imageless-kubernetes/install/uninstall.md' - 'k8s/config.md': 'imageless-kubernetes/config.md' - 'k8s/examples/gitlab-ci.md': 'imageless-kubernetes/examples/gitlab-ci.md' - 'k8s/examples/kind-demo.md': 'imageless-kubernetes/examples/kind-demo.md' + 'k8s/intro.md': 'containers/imageless-kubernetes/intro.md' + 'k8s/tech.md': 'containers/tech.md' + 'k8s/install/eks.md': 'containers/imageless-kubernetes/install/eks.md' + 'k8s/install/self-managed.md': 'containers/imageless-kubernetes/install/self-managed.md' + 'k8s/install/troubleshooting.md': 'containers/imageless-kubernetes/install/troubleshooting.md' + 'k8s/install/upgrading.md': 'containers/imageless-kubernetes/install/upgrading.md' + 'k8s/install/uninstall.md': 'containers/imageless-kubernetes/install/uninstall.md' + 'k8s/config.md': 'containers/imageless-kubernetes/config.md' + 'k8s/examples/gitlab-ci.md': 'containers/imageless-kubernetes/examples/gitlab-ci.md' + 'k8s/examples/kind-demo.md': 'containers/imageless-kubernetes/examples/kind-demo.md' + 'imageless-kubernetes/intro.md': 'containers/imageless-kubernetes/intro.md' + 'imageless-kubernetes/tech.md': 'containers/tech.md' + 'imageless-kubernetes/install/eks.md': 'containers/imageless-kubernetes/install/eks.md' + 'imageless-kubernetes/install/self-managed.md': 'containers/imageless-kubernetes/install/self-managed.md' + 'imageless-kubernetes/install/troubleshooting.md': 'containers/imageless-kubernetes/install/troubleshooting.md' + 'imageless-kubernetes/install/upgrading.md': 'containers/imageless-kubernetes/install/upgrading.md' + 'imageless-kubernetes/install/uninstall.md': 'containers/imageless-kubernetes/install/uninstall.md' + 'imageless-kubernetes/config.md': 'containers/imageless-kubernetes/config.md' + 'imageless-kubernetes/examples/gitlab-ci.md': 'containers/imageless-kubernetes/examples/gitlab-ci.md' + 'imageless-kubernetes/examples/kind-demo.md': 'containers/imageless-kubernetes/examples/kind-demo.md'