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 generate OCI-compatible containers directly from your development environment using nix2container. No Dockerfile required — the same devenv.nix that defines your shell also defines what goes into the image.
Containers were introduced in devenv v0.6.

Adding the required inputs

The containers command requires two additional inputs. Add them with:
$ devenv inputs add nix2container github:nlewo/nix2container --follows nixpkgs
$ devenv inputs add mk-shell-bin github:rrbutani/nix-mk-shell-bin

Predefined containers

By default, devenv provides two ready-made containers:
NameEquivalent commandDescription
shelldevenv shellEnters the development environment
processesdevenv upStarts all defined processes
Build either one with devenv container build <name>.

Entering the development environment

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

  languages.python.enable = true;
}
Build the shell container:
$ devenv container build shell
/nix/store/...-image-devenv.json
Run it locally using Docker to verify:
$ 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 strategy is to run each process as an entrypoint to a container:
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";
  };

  # Exclude the source repo to make the container smaller.
  # containers.processes.copyToRoot = null;
}
Build and run the processes container:
$ 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!
06:30:08 hello-nix.1    | Hello Nix!
06:30:08 hello-docker.1 | Hello Docker!

Custom containers

Running a single process

Specify exactly which command runs when the container starts:
devenv.nix
{
  processes.serve.exec = "python -m http.server";

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

Running build artifacts

If you build binaries as part of the development environment, you can include only those in the final image:
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 a container to a registry

Use the copy subcommand with --registry to push a container image:
$ devenv container --registry docker:// copy processes

Deploying to fly.io

Any arguments passed to --copy-args are forwarded to skopeo copy:
$ devenv container --registry docker://registry.fly.io/ --copy-args="--dest-creds x:$(flyctl auth token)" copy processes
You can also declare these options in devenv.nix to avoid repeating them on every deploy:
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 getting-started setup.

Changing behaviour based on build type

Use config.container.isBuilding to conditionally include packages or settings that should only apply to native (non-container) environments:
devenv.nix
{ pkgs, config, lib, ... }:

{
  packages = [ pkgs.openssl ]
    ++ lib.optionals (!config.container.isBuilding) [ pkgs.git ];
}
You can also target a specific container by name — for example, config.containers."processes".isBuilding — to customise behaviour for just that image.
For a full list of all container options, see the containers options reference.

Build docs developers (and LLMs) love