Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/cachix/devenv/llms.txt

Use this file to discover all available pages before exploring further.

devenv can build OCI-compliant container images directly from your development environment. The same devenv.nix that defines your local shell can produce a minimal, reproducible image ready for Docker, Kubernetes, or any OCI registry — no Dockerfile required.
Container support was introduced in devenv v0.6.

Prerequisites

Add the two required inputs to your project:
$ devenv inputs add nix2container github:nlewo/nix2container --follows nixpkgs
$ devenv inputs add mk-shell-bin github:rrbutani/nix-mk-shell-bin

Quick Reference

CommandWhat it does
devenv container build shellBuild a container that enters the dev shell
devenv container build processesBuild a container that starts all processes
devenv container run <name>Run the named container locally with Docker
devenv container --registry docker://ghcr.io/ copy <name>Push to a registry

Entering the Development Environment

Given a simple Python environment:
devenv.nix
{
  name = "simple-python-app";

  languages.python.enable = true;
}
Build the shell container (equivalent to running devenv shell):
$ devenv container build shell
/nix/store/...-image-devenv.json
Test it locally with Docker:
$ devenv container run shell
...
(devenv) bash-5.2# python
Python 3.10.9 (main, Dec  6 2022, 18:44:57) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Running Processes

A common deployment pattern is to use the processes container, which runs all defined processes as the container entrypoint — equivalent to devenv up.
devenv.nix
{
  name = "myapp";

  packages = [ pkgs.procps ];

  processes = {
    hello-docker.exec = "while true; do echo 'Hello Docker!' && sleep 1; done";
    hello-nix.exec = "while true; do echo 'Hello Nix!' && sleep 1; done";
  };

  # Uncomment to exclude the source repo and reduce image size:
  # containers.processes.copyToRoot = null;
}
$ devenv container run processes
...
06:30:06 system         | hello-docker.1 started (pid=15)
06:30:06 hello-docker.1 | Hello Docker!
06:30:06 system         | hello-nix.1 started (pid=16)
06:30:06 hello-nix.1    | Hello Nix!
06:30:07 hello-nix.1    | Hello Nix!
06:30:07 hello-docker.1 | Hello Docker!

Defining Custom Containers

Single Process Container

Run one specific process as the container’s startup command:
devenv.nix
{
  processes.serve.exec = "python -m http.server";

  containers."serve" = {
    name = "myapp";
    startupCommand = config.processes.serve.exec;
  };
}
$ devenv container run serve

Artifact-Only Container

If your build produces binaries in ./dist, ship only those artefacts in the final image — keeping it as small as possible:
devenv.nix
{
  # Watch local changes and build the project to ./dist
  processes.build.exec = "${pkgs.watchexec}/bin/watchexec my-build-tool";

  containers."prod" = {
    copyToRoot = ./dist;
    startupCommand = "/mybinary serve";
  };
}
$ devenv container run prod
...

Copying Containers to a Registry

Use the copy subcommand with --registry to push an image.
$ devenv container --registry docker:// copy processes
Any arguments passed via --copy-args are forwarded directly to skopeo copy. You can also declare registry settings in devenv.nix so they apply automatically:
devenv.nix
{
  containers."processes" = {
    registry = "docker://registry.fly.io/";
    defaultCopyArgs = [
      "--dest-creds"
      "x:\"$(${pkgs.flyctl}/bin/flyctl auth token)\""
    ];
  };
}
See the fly.io example for a complete working setup.

Changing the Environment Based on Build Type

Sometimes you want a package available in local development but excluded from the container image. Use config.container.isBuilding to conditionalise:
devenv.nix
{ pkgs, config, lib, ... }:

{
  packages = [ pkgs.openssl ]
    ++ lib.optionals (!config.container.isBuilding) [ pkgs.git ];
}
You can also target a specific container by name:
lib.optionals (!config.containers."processes".isBuilding) [ pkgs.git ]
See the full list of container options for all available configuration keys.

Build docs developers (and LLMs) love