Skip to main content
Run shell commands inside a Docker development container on your local machine. Commands can be run inline or saved as named aliases for reuse. In a CI job that already runs inside the devenv image, the command runs in place. See Running in CI.

Syntax

Options

Arguments

Prerequisites

A development environment must be created first:
This configures the Docker image, mount directory, and shell used by lager exec.

Command Reference

Run an Inline Command

Save a Command for Reuse

Run a Saved Command

Append Extra Arguments

Put -- before extra arguments that start with a dash. Without it, lager exec takes an argument that matches one of its own options, such as --verbose, for itself.

Pass Environment Variables

--passenv copies the value from your shell into the container. Do not pass PATH: the host value replaces the PATH of the image, and the container then does not find its own tools.

Running in CI

lager exec reads the CI environment variables before it starts a container. In a job on one of these CI systems, it runs the command in place, with no container: A job on one of these systems usually runs inside the devenv image already. The variables name the CI system, not the container, so the CLI also checks whether this process is in one. It looks for /.dockerenv, /run/.containerenv, the container environment variable, and a container runtime in the cgroup of process 1. The command runs in place only when both are true. A GitHub Actions or GitLab CI job without a container: block runs on the runner itself. The CLI starts a container there and prints one line to say so. In place, the command runs as follows:
  • The shell is the DEVENV shell from .lager, or /bin/bash.
  • The command runs in the current directory. mount_dir does not apply.
  • The command gets the environment of the job, plus environment from .lager and each --env. --passenv has no effect because the job environment is already present.
  • The exit code of the command is the exit code of lager exec.
  • --mount, --volume, --user, and --group have no effect. If you pass any of them, the CLI prints one warning line, for example Warning: --mount, --volume ignored: the command runs in the current container, so there is nothing to start.
  • --interactive and --tty have no effect.
A Jenkins agent, another CI system, or a computer outside CI still starts a container.

Choosing the path yourself

LAGER_EXEC_IN_PLACE overrides the check. Set it to 1, true, or yes to run the command in place, and to 0, false, or no to start a container. Any other value is ignored, and the CLI falls back to what it detected.
LAGER_EXEC_IN_PLACE changes lager exec and nothing else. Box locking, the lock holder, and the collision wait are the same with it set.
LAGER_CI_OVERRIDE still works here, and it costs more. It stops every other lager command that sees it from detecting CI. A box lock then fails at once instead of waiting, unless LAGER_LOCK_WAIT is set. The lock holder is your user name rather than the CI job. Prefer LAGER_EXEC_IN_PLACE=0, which starts a container without touching locks.

How It Differs from Other Commands

Saved Command Management

Saved commands are stored in the devenv section of your .lager config. Use lager devenv to manage them:

Examples

Notes

  • The container is created with --rm so it is removed after each command
  • Exit codes from the container are propagated to the CLI
  • Every LAGER* environment variable in your shell is passed into the container
  • Source code is mounted from your local filesystem into the container
  • Lager configuration (~/.lager) is mounted into the container when present
  • The COMMAND argument and --command option are mutually exclusive; use one or the other