Introduction
TIDE opens two artists' studios to visitors for one day. Its website offers a programme, directions and a downloadable guide. The City site is live, and the Riverside reference preview still works. The Courtyard preview container has disappeared. Recover that venue without replacing either neighboring site or the shared networks.
You need basic terminal skills and prior experience with Docker images, containers and published ports. Terraform is new here: you will learn HCL configuration, providers, resources, data sources, plans and state. Tools and complete website images are supplied. This is local Docker infrastructure on one training instance; it requires no cloud account or application programming.
Use Live Studios, Reference Preview, Venue Preview and Workstation. Venue Preview is unavailable until recovery. This environment starts independently. Terraform 1.14.3 and the community kreuzwerker/docker provider 3.0.2 are fixed for this exercise. A local provider mirror makes learner initialization independent of the public registry.
Declare the Preview and Its Ownership Boundary
In this step, you will use the working visitor journey, then declare only the missing venue container. Begin in Live Studios. The homepage shows LIVE PROGRAMME / City. Select Meet the two studios, read the Form & Field and Small Editions sessions, then select Find directions and the programme. Select Download the day programme and open the downloaded text: it must contain City and both studio schedules. Expand Do I need to book?; entry is free without booking.
Switch to Reference Preview. The same journey shows REFERENCE PREVIEW / Riverside. Keep this container: it belongs to this Terraform configuration and is still needed. Venue Preview currently cannot connect because its container is missing. A missing server differs from an HTTP 404: a 404 comes from a running server that cannot find a particular page.
Read the Root and the State
Switch to Workstation. A Terraform root is the directory whose .tf files are evaluated together. Running Terraform in another directory selects a different root; it does not automatically scan neighboring directories. pwd prints your current path:
pwd
/home/labex/project/preview/courtyard
ls lists files, and cat prints a text file. Read the prepared configuration:
ls
cat main.tf
A .tf file uses HCL, a configuration language. Blocks group settings with braces; name = value assigns a setting. Quoted text is a string, while port numbers are numbers without quotes. The terraform block pins the core program and required provider. A provider is a plugin that translates Terraform operations into Docker API requests. provider "docker" {} uses this instance's Docker daemon. It does not connect to a public cloud.
The two data "docker_network" blocks read existing networks. A data source looks up an object but does not take ownership of creating or deleting it. city and venue are local labels used in references. The network names identify the real Docker objects. Image data sources similarly read the prepared image IDs. Using an actual image ID avoids repeatedly treating a tag and the resolved ID as different images.
cat reference.tf
A resource declares an object that this root manages. docker_container.reference is a Terraform address, combining the resource type and local label. Its Docker name is tide-reference. The reference container serves port 80 internally and publishes it as port 8083 on this instance. The expression data.docker_image.reference.id reads the image data source's id attribute. It is an expression, so it is not quoted.
Keep main.tf and reference.tf unchanged. Both networks, all image records and the live container are outside this root's managed ownership. The root manages two containers: the reference and the missing preview.
State maps Terraform addresses to real object IDs. The prepared terraform.tfstate remembers both containers, including the now missing one. State is neither the configuration nor a backup of the website. Do not edit or delete it. A later plan asks Docker what really exists rather than trusting that remembered ID alone.
Write the Missing Resource Declaration
Create preview.tf. Terraform combines it with the other .tf files in this root; the filename does not create a separate environment. cat > preview.tf replaces only that file. The quoted HCL begins a here-document: paste the whole block, including the final HCL on its own line. Quoting keeps the contents literal.
cat > preview.tf <<'HCL'
resource "docker_container" "preview" {
name = "tide-preview"
image = data.docker_image.site.id
ports {
internal = 80
external = 8082
}
networks_advanced {
name = data.docker_network.venue.name
}
}
HCL
This declares one container from the complete Courtyard image. The nested ports block publishes its HTTP service; networks_advanced connects it to the existing venue network. The live service uses 8081 and the reference uses 8083, so 8082 avoids a collision. A network reference does not make that network a managed resource.
Initialize this root. init prepares the provider plugin; it does not create infrastructure:
terraform init
Expect Terraform has been successfully initialized!. The supplied local mirror provides version 3.0.2. .terraform holds the initialized provider, and .terraform.lock.hcl records the chosen provider and checksums. Keep the lock file with the configuration. terraform state list prints the remembered addresses:
terraform state list
The output includes docker_container.preview and docker_container.reference, plus the image and network data sources. The preview address being listed does not prove its container still exists.
fmt formats HCL spacing; validate checks configuration syntax and provider argument types. Neither proves that the website is running:
terraform fmt
terraform validate
Expect Success! The configuration is valid. If you see a syntax error, read its filename and line, compare preview.tf with the complete block above, fix it, then repeat fmt and validate. Do not delete state or rewrite the shared configuration to clear an error. You now have a declaration that can recreate the target while leaving the reference unchanged.
Review and Apply a Precise Recovery
In this step, you will distinguish remembered state from live infrastructure, restore the complete Courtyard journey and confirm that nothing else changes. Start in Workstation in the same root.
Preview the Change Before Making It
terraform plan refreshes its understanding by reading Docker, compares that reality with the declaration and proposes changes. -out=recovery.tfplan saves this proposal in a binary plan file so apply can execute the reviewed plan. A saved plan can contain sensitive configuration; this exercise contains no credentials. Keep it in the project directory.
terraform plan -out=recovery.tfplan
Look for a refresh of the remembered preview ID, followed by:
## docker_container.preview will be created
...
Plan: 1 to add, 0 to change, 0 to destroy.
The resource's + means create. ~ would mean an in-place update; - would mean destroy; -/+ would mean replacement. The missing preview needs one creation. The reference must have no proposed changes. No network should be created, replaced or destroyed: those are existing shared data sources, not resources owned here.
If you see any destruction, replacement or another resource, stop before applying. Check pwd, preview.tf and whether reference.tf was accidentally edited. Restore only your mistaken edit from the supplied example and make a new plan. A wrong network name may produce network not found; compare it with the existing data blocks instead of creating a substitute shared network. Do not remove containers by a name prefix or run terraform destroy as a recovery shortcut.
Execute the Reviewed Plan
terraform apply recovery.tfplan executes the saved changes. Unlike apply without a plan filename, it does not ask for another yes; saving a plan is not itself authorization to execute it, so review before this command:
terraform apply recovery.tfplan
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
If Terraform reports that the saved plan is stale, another operation changed the state after planning. Generate and review a new plan before applying it. If port 8082 is already allocated, inspect the exact competing container rather than deleting every container. In this prepared lab it should be free; recheck the configured external port and preserve 8081 and 8083.
Switch to Venue Preview. Reload once the container has started. It should show VENUE PREVIEW / Courtyard. Follow Meet the two studios → Find directions and the programme → Download the day programme. Open the download and confirm Courtyard and both demonstration times. The full pages, styles, illustration and download come from the supplied image, not a new empty Nginx welcome page.
Switch to Live Studios and Reference Preview. Both original visitor journeys must still work, with City and Riverside respectively. Different names on a homepage alone do not prove preservation; the underlying objects must remain the same.
Confirm Convergence and Preservation
Return to Workstation. A second plan is a new observation of the current declaration and Docker reality:
terraform plan
No changes. Your infrastructure matches the configuration.
This is convergence: the desired resources now exist with their declared settings. Terraform does not continuously watch and repair containers; a person or automation must run the workflow again after a later change. This recovery restores replaceable infrastructure and supplied website content, not lost user data or an entire host.
terraform state show displays one resource's remembered attributes. Compare its id with Docker's actual ID. The Docker --format option selects one field; single quotes keep the template literal:
terraform state show docker_container.preview
docker inspect --format '{{.Id}}' tide-preview
Both should identify the same new container. The ID can vary; do not copy an example ID into state. Read the original neighbors and both existing networks without changing them:
docker inspect --format '{{.Name}} {{.Id}} {{.State.StartedAt}}' tide-live tide-reference
docker network inspect --format '{{.Name}} {{.Id}}' tide-city tide-courtyard
The course checks these identities against their original values. The live container is outside this root, while the reference is a managed resource deliberately retained in it. Both boundaries matter. You have recovered one missing preview while preserving the other sites and shared infrastructure.
Summary
You used HCL and a pinned Docker provider to declare a missing venue container. Data sources kept shared networks and images outside this root's managed ownership. You compared configuration, state and live Docker objects, applied one reviewed creation, checked the complete visitor journey and reached a no-change plan while retaining the live and reference sites.



