keepcalculator

06 Numbers and Powers

jq Missing in Dev Container: Install & Make It Stick

Card No. 06·38016 · Updated · Standard formula, shown below

If jq is missing from your dev container, you can install it and make it persist by adding it to the container’s Dockerfile or using a lifecycle script in your devcontainer.json. The exact steps depend on your base image and package manager, but the key is to install it during the image build or post-create phase, not just in a running shell. This article explains the background, the methods, and common pitfalls so you can get jq available every time you rebuild.

Why jq Goes Missing in Dev Containers

Dev containers are ephemeral by design. When you rebuild a container, the filesystem resets to the state defined by the image and the devcontainer.json configuration. Anything you install manually with apt, apk, or dnf inside a running container is lost on rebuild. This is a common source of confusion because it feels like the container should “remember” what you did, but it doesn’t unless you explicitly encode it.

Another reason jq might be missing is that the base image you chose (e.g., mcr.microsoft.com/devcontainers/base:ubuntu or node:20) does not include jq by default. Many official images strip out non-essential tools to keep the image small. You need to add it yourself.

How to Install jq and Make It Persistent

There are two main approaches: modify the Dockerfile (if you use one) or use the postCreateCommand in devcontainer.json. The Dockerfile approach is the most reliable because it runs during the image build, so the installed package is baked into the image layer. The lifecycle script approach runs after the container is created, but it still runs on every rebuild, so the package will be present.

Here are the steps for the most common scenarios:

  • Ubuntu/Debian (apt): Add RUN apt-get update && apt-get install -y jq to your Dockerfile, or use "postCreateCommand": "apt-get update && apt-get install -y jq" in devcontainer.json.
  • Alpine (apk): Add RUN apk add --no-cache jq to your Dockerfile, or use "postCreateCommand": "apk add --no-cache jq".
  • CentOS/RHEL/Fedora (dnf/yum): Add RUN dnf install -y jq (or yum) to your Dockerfile, or use the corresponding command in postCreateCommand.

If you are using a devcontainer.json without a Dockerfile, the postCreateCommand is the simplest way. It runs every time the container is created, so it will reinstall jq after each rebuild. However, if you use the postStartCommand instead, it runs every time you start the container (even if it wasn’t rebuilt), which is unnecessary but also works.

Choosing Between Dockerfile and Lifecycle Scripts

Which method you choose depends on your workflow:

  • Dockerfile: Best if you already have a Dockerfile or want to share the image with others. It’s the most reproducible because the package is part of the image. You can also combine it with other setup steps like copying config files.
  • postCreateCommand: Best for quick tweaks without rebuilding the image. It’s easier to read and modify, but it runs every time the container is created, which can slow down startup if you have many commands.
  • postStartCommand: Use this only if you need jq to be installed every time the container starts, even if it wasn’t rebuilt. This is rare; usually postCreate is enough.

A common pattern is to use a Dockerfile for the base setup and a postCreateCommand for project-specific tools. For jq specifically, either works, but the Dockerfile is more robust because it doesn’t depend on network access during the post-create phase (though most dev containers have network).

Common Problems and How to Fix Them

Even after following the steps, you might run into issues:

  • Command not found after install: This usually means the package manager didn’t install it where your shell looks. Check the PATH. On most systems, jq installs to /usr/bin/jq, which is in the default PATH. If you installed it to a custom location, add it to PATH.
  • Permission denied: If you get a permission error during install, you might need to run the command with sudo. In a dev container, you often run as root, but if not, use sudo.
  • Package not found: If your package manager can’t find jq, update the package list first. For apt, run apt-get update before install. For apk, use apk update.
  • postCreateCommand not running: Make sure you placed it in the correct section of devcontainer.json. It should be at the top level, not inside build or runArgs. Also, check the logs in VS Code (Output panel -> Dev Containers) to see any errors.
  • Rebuild not picking up changes: If you modified the Dockerfile, you need to rebuild the container with “Rebuild Container” (not just restart). In VS Code, use the command palette and select “Dev Containers: Rebuild Container”.

Alternative: Use a Base Image That Includes jq

Some dev container images come with jq pre-installed. For example, many of the official Microsoft dev container images (like mcr.microsoft.com/devcontainers/base:ubuntu) include jq as part of their standard tools. If you are using a custom image, check its documentation or inspect the image to see if jq is already there. If not, you can switch to an image that includes it, but that might be overkill if you only need jq for one project.

Another alternative is to use a multi-stage build in your Dockerfile to copy jq from a smaller image, but that’s more complex. For most users, installing via the package manager is the simplest.

How to Verify jq Is Installed

After you’ve added the install command, rebuild the container and run jq --version in the terminal. You should see output like jq-1.7.1. If you get a “command not found” error, check the installation logs and PATH. You can also run which jq to see the full path.

To test that it works, you can pipe some JSON to it: echo '{"key":"value"}' | jq '.key' should output "value". This confirms not only that jq is installed but also that it’s in your PATH.

Frequently Asked Questions

Why does jq disappear after I rebuild the container?

Because dev containers are ephemeral. The filesystem resets to the image state on rebuild. Anything you install manually in a running container is lost unless you add it to the Dockerfile or a lifecycle script.

What is the difference between postCreateCommand and postStartCommand?

postCreateCommand runs only when the container is created (i.e., after a rebuild). postStartCommand runs every time the container starts, even if it wasn’t rebuilt. For installing jq, postCreateCommand is usually sufficient because the container is created when you rebuild.

Can I install jq using a package manager other than apt?

Yes, it depends on your base image. Alpine uses apk, CentOS uses dnf or yum, and Debian/Ubuntu use apt. The command is different for each, as shown in the examples above.

Do I need to run apt-get update before installing jq?

Yes, on Debian/Ubuntu systems, you need to update the package list first, otherwise apt may not find the package or may install an older version. The command is apt-get update && apt-get install -y jq.

Is there a way to install jq without modifying the Dockerfile?

Yes, you can use the postCreateCommand in devcontainer.json. This is a good option if you don’t have a Dockerfile or want to keep the image clean. Just add the install command as a string in the JSON.

What if I’m using a remote container (e.g., on a server)?

The same principles apply. The container is still ephemeral, so you need to install jq during the build or post-create phase. The commands are the same, just executed in the remote environment. Make sure you have the necessary permissions to install packages.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →