Learning bite
Container networking and volumes
Separate reachability from persistence in a local container deployment.
On this page
Ask where the caller is running
Inside a normally isolated container, localhost refers to that container's network context. From your Mac it refers to your Mac. A port mapping connects a host address/port to a container port; it does not make both contexts identical. On a user-defined bridge network, Docker also provides name resolution between attached containers.
Use the restored learnwithsk-status:dev image from the previous lesson. Confirm no old sk-status container remains. Run:
docker network create sk-study-net
docker run -d --name sk-status --network sk-study-net -p 127.0.0.1:8765:8000 learnwithsk-status:dev
docker run --rm --network sk-study-net learnwithsk-status:dev python -c 'import urllib.request; print(urllib.request.urlopen("http://sk-status:8000/status.json", timeout=3).read().decode())'
curl --fail --max-time 3 http://127.0.0.1:8765/status.json
Both callers should read the fixture. The short-lived client container uses sk-status:8000, while the Mac uses 127.0.0.1:8765. The client overrides the image's default server command with its own Python command. It does not need the server's host publication to reach it over the shared network.
Predict what happens if the client requests 127.0.0.1:8765 instead. It looks inside its own container for a listener on 8765 and should fail. A database on port 5432 reached only by peer containers similarly needs no public host mapping.
Remove only these network fixtures when done:
docker stop sk-status
docker rm sk-status
docker network rm sk-study-net
Give data a lifetime independent of a process
A container's writable layer disappears with that container. A named volume is Docker-managed storage with a separate lifetime. A bind mount exposes a particular host path. A tmpfs mount is temporary memory-backed storage. A mount can also hide files that were already present at its destination in the image.
Practice with invented data, using the base Python image whose default user can write this new volume:
docker volume create sk-study-data
docker run --rm --mount type=volume,source=sk-study-data,target=/data python:3.12-slim python -c 'from pathlib import Path; Path("/data/note.txt").write_text("retained fixture\n")'
docker run --rm --mount type=volume,source=sk-study-data,target=/data,readonly python:3.12-slim python -c 'from pathlib import Path; print(Path("/data/note.txt").read_text(), end="")'
Expected reader output: retained fixture. The writer container has already been removed, yet its volume data remains. The reader mounts it read-only. This illustrates persistence, not a backup strategy, encryption guarantee, or application-consistent database restore.
After reading, remove this practice volume with docker volume rm sk-study-data. That deletes its fixture data. Do not substitute a broad volume prune. A non-root application may need carefully prepared ownership on its data directory; running everything as root is not the general solution.
Transfer the distinction to MicroBank
The inspected upstream Compose snapshot does not define explicit named database volumes. An image may create anonymous volumes, but that is not a documented stable persistence design for this project. The later guided profile introduces named volumes for the two active PostgreSQL services and checks persistence deliberately.
Checkpoint: why did the second container read the file after the first was removed? The data lived in the named volume, not the first container's writable layer. Why is it not a backup? It is still the live storage location and can be deleted or corrupted. Next, describe the local service configuration as a Compose project.
References: networking↗, volumes↗, bind mounts↗, and MicroBank snapshot↗.
Your notes and evidence
Record observations, questions, or links to your work. Keep credentials out of your notes.
Back up or restore this path
Progress and notes stay in this browser. A backup contains only this learning path.