Introduction
A file removed from a container image may still exist in an earlier image layer. Git ignore rules also do not control what Docker receives during a build.
You will investigate a prepared image, restrict its build inputs, and verify every layer of a new image. The worker and Docker workflow follow the previous lab. All credentials are fictional local fixtures; the cached base and inspection helpers are prepared.
Inspect the Prepared Build Inputs
In this step, you will separate source-control ignore rules from Docker build inputs.
cd /home/labex/project/ticket-image
ls -a
ls -a includes dot-prefixed files. This project contains the worker, public configuration, input/output directories, private.env, and debug.txt. The last two are private local inputs, not delivery files.
cat .gitignore
Git ignores the two private names. That affects Git's tracking workflow, not Docker's build context.
cat .dockerignore
The file is currently empty. .dockerignore controls which paths Docker excludes when it receives the build context. A file can be ignored by Git and still be sent to a Docker build.
cat Dockerfile
COPY . /app/ copies the entire available context. The later RUN rm ... removes private files from the final filesystem, but that does not undo the earlier image layer.
Find the Hidden Layer Copy
In this step, you will compare the final filesystem with saved image layers.
The prepared legacy tag ticket-image:legacy was built from this Dockerfile. Run a one-time inspection container. --rm automatically removes this temporary container after ls finishes; its command overrides the image's default worker startup:
sudo docker run --rm ticket-image:legacy ls -a /app
The final /app should not list private.env or debug.txt. It still contains the worker and public configuration.
docker history shows image-building instructions. --no-trunc keeps the full instruction text:
sudo docker history --no-trunc ticket-image:legacy
Find the broad copy followed by removal. History explains the sequence, but not every file's contents. The prepared course-image-scan helper saves this actual image and reads every saved layer plus image configuration:
sudo course-image-scan ticket-image:legacy
Expect findings naming private files in an earlier layer and a redacted target practice credential. Exit 1 means findings; 2 or CHECK ERROR means inspection failed. The helper's fixed scope is these listed private names and this fake credential, not a complete production secret scanner.
Later layer deletions do not erase earlier bytes. Passing a final-filesystem ls is therefore insufficient.
Exclude Private Build Inputs
In this step, you will keep the local private files while excluding them from the Docker context.
nano .dockerignore
Use this complete file:
private.env
debug.txt
input/
output/
Each line is a path or directory to exclude. These patterns remove private configuration, debug material, and runtime data from build inputs; the worker and config.public remain available.
Save with Ctrl+O, Enter, and exit with Ctrl+X. Do not delete the local private files. Ignoring a path should limit its inclusion, not destroy the local configuration.
Limit the Dockerfile Copy Scope
In this step, you will make the image's required inputs explicit.
The old deletion instruction is now unnecessary and would fail because the excluded files are unavailable. Open the Dockerfile:
nano Dockerfile
Use this complete file:
FROM desklite-base:1.37.0
WORKDIR /app
COPY worker.sh config.public /app/
USER nobody
CMD ["sh", "/app/worker.sh"]
COPY worker.sh config.public /app/ lists only the two required business files. Keep USER nobody and the original startup command from the previous lab. Save with Ctrl+O, Enter, Ctrl+X.
The two controls work together: .dockerignore restricts available build inputs, and the explicit COPY restricts what this image includes. Neither relies on deleting a secret after it entered a layer.
Build and Inspect the New Artifact
In this step, you will inspect a newly built delivery image instead of changing the meaning of the old evidence.
sudo docker build -t ticket-image:delivery .
Expect a successful local build. The new tag is distinct from ticket-image:legacy.
sudo course-image-scan ticket-image:delivery
Expect a PASS for every saved layer and the image configuration. This target-specific result does not claim that every possible secret or vulnerability has been detected.
Now check the context independently:
sudo course-context-check .
This prepared helper builds a temporary image with a fixed COPY . probe, applies the same actual layer inspection, then removes that temporary image. Expect PASS. It demonstrates that the private files were excluded from the context, rather than merely omitted by your narrower delivery COPY.
The legacy image may still contain the original finding. Rebuilding a clean delivery artifact does not rewrite previously distributed images or revoke leaked credentials. Real exposures require the credential replacement process learned earlier and appropriate cleanup of old copies. Here the target Token is deliberately fake, and acceptance concerns the new delivery image.
Run the Original Report from the New Image
In this step, you will prove that removing private build inputs preserved the worker's required files and behavior.
The output directory is already owned by UID 65534 with private writable access. Reuse the previous lab's non-root worker and bind-mount workflow:
sudo docker run -d --name ticket-image-worker --network none --mount type=bind,src=/home/labex/project/ticket-image/input,dst=/data/input,readonly --mount type=bind,src=/home/labex/project/ticket-image/output,dst=/data/output ticket-image:delivery
sudo docker exec ticket-image-worker id -u
Expect 65534.
sudo docker logs ticket-image-worker
Expect mode=report and tickets=2. The first line comes from the required public configuration; the second comes from reading the original input and writing the actual report.
sudo docker exec ticket-image-worker cat /data/output/report.txt
Expect tickets=2. The worker still has read-only input and writable output, with no need for private configuration inside the image.
Confirm Local Sources and Delivery Evidence
In this step, you will finish with both the local private inputs and the safe delivery artifact intact.
List the private source files without printing their contents:
ls -l private.env debug.txt
Both must still exist locally. Deleting them would bypass the intended build-boundary exercise.
sudo course-image-scan ticket-image:delivery
sudo docker ps
The delivery scan should pass and ticket-image-worker should be running. The course check also probes the real build context, checks the running image ID, and verifies the original report. There is no separate written investigation file to submit.
Summary
You restricted actual Docker build inputs, copied only required business files, inspected all saved layers and image configuration, and preserved the original non-root worker. A clean final filesystem alone would not have established this boundary.



