How to Use Environment Variables and Env-Files in Container Run Commands
The container CLI supports the -e/--env flag for setting individual variables and the --env-file flag for loading variables from a file, merging them with the host environment before launching the container process.
The container run command provides flexible mechanisms for injecting configuration into containers at runtime. Whether you need to pass a single secret or load an entire configuration set, the CLI handles environment variables and env-files through dedicated flags defined in the command parser. These flags are available on every command that creates a container process, including container run and container exec, as documented in docs/command-reference.md.
Command-Line Flags for Environment Variables
The CLI implements two complementary approaches for environment configuration, parsed in Sources/Services/ContainerAPIService/Client/Flags.swift and processed by the runtime service.
Using -e and --env for Inline Variables
The -e (or --env) flag sets a variable inside the container. Provide a key-value pair explicitly, or supply only the key to inherit the value from the host environment.
container run -e FOO=bar -e BAZ=qux ubuntu:latest env
When only the key is supplied, the CLI copies the corresponding value from the host's environment:
export MY_TOKEN=secret123
container run -e MY_TOKEN alpine:latest sh -c 'echo $MY_TOKEN'
Using --env-file for Batch Loading
The --env-file flag reads a file containing KEY=VALUE pairs, ignoring blank lines and lines starting with #. This is optimal for managing related configuration variables such as API keys or feature toggles.
Create a file named .env:
# .env
APP_MODE=production
DB_HOST=db.example.com
# comment lines are ignored
Then reference it in the run command:
container run --env-file .env node:18 npm start
Implementation Details
According to the apple/container source code, the environment variable handling follows a specific pipeline across two key files.
In Sources/Services/ContainerAPIService/Client/Flags.swift, the CLI defines the --env and --env-file options and links them to the command-line parser. This module collects the variables specified by the user.
The collected variables are forwarded to Sources/Services/RuntimeLinux/Server/RuntimeService.swift, which merges them with the host environment before spawning the container process. The runtime ensures that values from --env flags override those from --env-file, and both override the host environment defaults.
Integration tests in Tests/IntegrationTests/Run/TestCLIRunCommand.swift verify that the CLI correctly parses and forwards these variables to the runtime.
Practical Examples
Setting Multiple Variables Inline
Pass several explicit values using multiple -e flags:
container run -e API_KEY=sk_live_123 -e DEBUG=0 python:3.9 myscript.py
Inheriting Host Environment Variables
Export a variable in your shell, then reference it by key only:
export CONTAINER_REGISTRY_TOKEN=ghp_abc123
container run -e CONTAINER_REGISTRY_TOKEN ubuntu:latest \
sh -c 'echo Token is $CONTAINER_REGISTRY_TOKEN'
Combining Flags and Files
You can mix --env-file with inline -e flags. Inline values take precedence over file contents:
container run -e OVERRIDE=local --env-file config.env \
-e INHERIT_FROM_HOST \
myimage:latest mycmd
In this example, OVERRIDE is set to local regardless of what appears in config.env, while INHERIT_FROM_HOST pulls its value from the current shell.
Enabling Debug Mode via Environment Variables
The CLI respects specific host environment variables listed in its help documentation. Setting CONTAINER_DEBUG before invocation enables diagnostic output:
export CONTAINER_DEBUG=1
container run ubuntu:latest ls /
This triggers the debug logging system as implemented in the runtime service.
Summary
- The
-e/--envflag sets individual variables or inherits them from the host when only the key is provided. - The
--env-fileflag loads variables from a file, ignoring comments and blank lines. - Implementation resides in
Sources/Services/ContainerAPIService/Client/Flags.swift(parsing) andSources/Services/RuntimeLinux/Server/RuntimeService.swift(runtime merging). - Flag precedence follows the order: inline
-eflags override--env-filevalues, which override host environment defaults. - Integration tests in
Tests/IntegrationTests/Run/TestCLIRunCommand.swiftvalidate the end-to-end behavior.
Frequently Asked Questions
Can I use multiple --env-file flags in a single command?
Yes. You can specify multiple --env-file flags to load variables from several files. The CLI processes them in the order they appear on the command line, with later files potentially overriding earlier ones if duplicate keys exist.
What happens if I specify the same key in both --env-file and -e?
The inline -e flag takes precedence. According to the implementation in RuntimeService.swift, the CLI merges environments by applying --env-file variables first, then overlaying the explicit -e values, ensuring that command-line overrides are respected.
Does the container inherit all host environment variables automatically?
No. The container only receives variables explicitly passed via -e (when providing only the key) or loaded through --env-file. Unlike Docker's --env behavior without explicit values, the container CLI requires you to specify which host variables to inherit by listing them as -e VARNAME without a value.
Are environment variables available in container exec commands?
Yes. The -e and --env-file flags are available on every command that creates a container process, including container exec. The same parsing logic in Flags.swift and merging behavior in RuntimeService.swift applies to both run and exec subcommands.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →