Define the environment you will reproduce
In a fictional batch-automation project, the author can work in their container, but RUN needs to prepare another instance. The lab starts with an already-available Python image and adds only a learner user and demonstration file. The versionable configuration defines image, project mount, opened directory, users, two public variables and lifecycle steps. Before execution, predict which files will be on the host, which will belong only to the instance and which already exist in the image. Record the resolved image identity as well as the tag name. A reused tag can refer to different contents. This exercise uses Dev Containers CLI 0.89.0; CLI results do not amount to testing the VS Code graphical interface.
Locate the write before choosing recovery
The project is mounted at /workspace. The author creates input.txt on the host; tooling reads it and writes output.txt, which also appears on the host. Outside the mount, it creates manual-helper.txt in /home/learner. Both remain after stopping and starting the same instance. Removing and recreating the container preserves output.txt in the shared directory but loses manual-helper.txt. For RUN, these observations justify two different actions: protect workspace changes and turn manual preparation into repeatable steps. Stop/start is not a reconstruction test. Moving the helper to another path in the writable layer is also insufficient. If the file is needed, the environment definition must explain how it is recreated. The example uses a demonstration file rather than actually installing a tool.
Separate process identity and environment
The exercise sets containerUser=root and remoteUser=learner to make their difference observable. The CLI runs Python with UID 1001; docker exec without user selection observes UID 0. DR_CONTAINER_FLAG appears in both processes. DR_REMOTE_FLAG, defined through remoteEnv, appears only in the tooling process. These are public values without credentials. During diagnosis, first identify what launched the process and which context it received. Success in a terminal does not establish the environment of a startup process. It also does not demonstrate become on a managed node: this lab executes neither Ansible nor SSH. On a real Linux host, check numeric IDs and bind-mount permissions; the Docker Desktop macOS result does not establish identical mapping on another platform.
Distinguish startup, creation and effective configuration
Markers make lifecycle visible. Initial creation has postCreateCommand append one line to created.txt and postStartCommand another to started.txt. On the next start of the same instance, only the start marker gains another line. InitializeCommand writes host-init.txt on the host and must not be confused with internal image preparation. Next, the exercise changes containerEnv from initial to revised and reuses the instance: its process still receives initial. Only recreation supplies revised and executes the creation step again. When approving a change, compare configuration file, instance identity and observed effective value. A dependency-preparation hook can fail while the container remains active; acceptance should include completed preparation and commands the project actually uses.
Interpret mounts and missing files
A read-only probe reads the reference but fails when writing forbidden.txt. Confirming RW=false guides the solution: choose a writable result destination without making the reference writable. Another probe mounts the project at /opt/dr-fixture, where the image already contained base.txt. The file disappears from view; a container without that mount reads it again. The mount obscured contents without deleting them from the image. Before reinstalling an apparently missing tool, inspect mount destinations. With a remote daemon, the source must exist on the daemon side; a laptop-only directory is not transferred by a bind mount. That remote case is documentation-based configuration analysis rather than an operation executed by this local lab.
RUN handover with executable criteria
The complete exercise was repeated: 26 checks per run using CLI 0.89.0, Docker Engine 29.1.3 and Python 3.13.16 inside the container. Owned resources were removed afterward. Give RUN the project revision, image identity, expected mount, user, dependencies and acceptance commands. Have the recipient prepare a fresh instance and explain differences. If the play later runs in a separate EE, inspect that image and its collections too. Dev-container acceptance does not establish node access, service functionality or RHEL persistence after reboot. The learner should justify each retained or lost file and reconstruct the environment without depending on the author’s accumulated state. This original exercise does not reproduce official EX294 tasks.
OBSERVATIONS
CLI exec: UID=1001; cwd=/workspace
docker exec: UID=0
remoteEnv: tooling only
stop/start: manual helper remains
recreation: helper disappears; output.txt remains
containerEnv: initial -> recreation -> revised
readonly: write rejected
mount at /opt/dr-fixture: base.txt obscuredThe manual helper survives stop/start but disappears in a fresh instance; output.txt persists because it belongs to the bind mount.
Common pitfalls
Confusing restart with recreation, remoteUser with every process, edited containerEnv with its effective value, or a mount with automatic copying to a remote daemon.
Related topics: Git and executed revision · Roles and collections · Managed-node access
Accept the environment through observed recreation, identifying where each dependency and effect lives.
Reference: Dev Container metadata reference · EX294 current objectives inspected 2026-09-30; RHCE in Ansible framework effective 2026-05-11; booking product version not publicly pinned