Creating Nix-Powered Docker Containers with Devbox

We designed Devbox to build fast, reproducible development environments without the overhead and complexity of Docker. As described in a previous blog post, this is how we use Devbox internally — we generate a complete development environment with a devbox shell and skip the headaches of rebuilding our Docker containers when we make changes.

While this works well for many use cases, we understand that developers may need to generate a Docker container to use their dev environment with their existing infrastructure or deploy to other cloud platforms. Developers may want to combine the reproducibility of the Nix Package Manager with the network + resource isolation of Docker.

Our philosophy is to ensure that Devbox is compatible with existing workflows. We want developers to use Devbox without reconfiguring all their infrastructure and best practices. For this reason, we added support to generate Dockerfiles and Devcontainers directly from Devbox. This blog post will look at how to create and use these files with your project:

Why Dockerfiles?

One early path we explored was having Devbox build a custom container based on the packages installed in your Devbox environment.. This approach let Devbox optimize Dockerfiles for our users,  but it presented a few tradeoffs:

  1. Developers struggled with auditing the containers and understanding what they produced.
  2. Modifying containers beyond the Devbox's defaults was complicated and required digging into the Devbox codebase or finding a temp Dockerfile.
  3. Existing infrastructure assumed the existence of a Dockerfile. Inserting Devbox as the container builder made adoption more complicated for existing users

Since our goal was ensuring compatibility with existing infrastructure and workflows, we migrated to generating and exporting the Dockerfile instead. Developers can then modify the Dockerfile however they see fit.

Creating a Nix Dockerfile for your Devbox Project

Creating a Dockerfile for your project is as easy as running devbox generate dockerfile. This will create a Dockerfile in the root of your project directory that looks like the following:

FROM debian:stable-slim

# Step 1: Installing dependencies
RUN apt-get update
RUN apt-get -y install bash binutils git xz-utils wget sudo

# Step 2: Setting up the devbox user
ENV DEVBOX_USER=devbox
RUN adduser $DEVBOX_USER
RUN usermod -aG sudo $DEVBOX_USER
RUN echo " devbox      ALL=(ALL:ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/$DEVBOX_USER

USER $DEVBOX_USER

# Step 3: Installing devbox
RUN wget --quiet --output-document=/dev/stdout https://get.jetpack.io/devbox   | bash -s -- -f
RUN chown -R "${DEVBOX_USER}:${DEVBOX_USER}" /usr/local/bin/devbox

# Step 4: Install Nix
RUN wget --output-document=/dev/stdout https://nixos.org/nix/install | sh -s -- --no-daemon
RUN . ~/.nix-profile/etc/profile.d/nix.sh
# updating PATH
ENV PATH="/home/${DEVBOX_USER}/.nix-profile/bin:/home/${DEVBOX_USER}/.devbox/nix/profile/default/bin:${PATH}"

# Step 5: Install your devbox project
WORKDIR /code
RUN sudo chown $DEVBOX_USER:root /code
COPY devbox.json devbox.json
RUN devbox install
CMD ["devbox", "shell"]

This Dockerfile generates a container for your Devbox Project by:

  1. Starting with a debian:stable-slim base image (the same base we use for Devbox Cloud) and installing the minimal set of packages needed to install Devbox + Nix
  2. Create a devbox user for installing and running Devbox + Nix
  3. Install the Devbox binary
  4. Install the Nix Package Manager in single-user mode and add its binaries to the path

To build your dev environment in a container, run docker build . (or use any other tool to build Dockerfiles). You can modify the Dockerfile directly to add environment variables, secrets, or anything else that your previous Dockerfiles used while getting the reproducibility of Nix packages via Devbox.

Exporting a Nix Dev Environment in a Devcontainer

For users of VSCode or Github Codespaces, Devbox supports exporting a Dockerfile-based Devcontainer. At the root of your project, you can run devbox generate devcontainer to produce a devcontainer.json and valid Dockerfile for your project:

{
  "name": "Devbox Remote Container",
  "build": {
    "dockerfile": "./Dockerfile",
    "context": ".."
  },
  "customizations": {
    "vscode": {
      "settings": {},
      "extensions": [
        "jetpack-io.devbox"
      ]
    }
  },
  "remoteUser": "devbox"
}

You can add your VSCode project's settings and extensions to the JSON to use them anywhere you run your Devcontainer.

If you're using our VSCode Extension, you can generate Dockerfiles and Devcontainers by running Generate Dev Container files from the command palette (Ctrl|Cmd-Shift-P or F1)

Next Steps with Devbox and Docker

Using Nix with Dockerfiles is a great way to improve the reproducibility of your existing workflows. With Devbox, generating a compatible Nix-powered Dockerfile or Devcontainer is as easy as running a single command. With this feature, you can integrate Devbox with your existing Build and Deploy systems from day one.

If you'd like to keep up with our progress, you can follow us on Twitter, or chat with our developers on our Discord Server. We also welcome issues and pull requests on our Github Repo.