Building, running, and the container lifecycle

From Dockerfile to running container

Build, then run
click Run to see this pane's output

docker build -t my-app . reads the Dockerfile in the current directory, producing an image tagged my-app. docker run my-app starts a container from that image — an instance from that class, in the terms of the earlier concept.

Reaching a container from outside: port mapping

A process running inside a container is, by default, only reachable from inside that container. -p maps a port on your machine to a port inside the container:

Port mapping
click Run to see this pane's output

8000:5000 reads as “your machine’s port 8000 forwards to the container’s port 5000.” From outside, you’d reach the app at localhost:8000, even though the app itself, inside the container, might be listening on 5000. Recall EXPOSE alone doesn’t do this-p is what actually publishes the port.

Overriding configuration at run time

ENV sets a default baked into the image; -e at docker run time overrides it for a specific container, without needing to rebuild the image:

Overriding LOG_LEVEL at run time
click Run to see this pane's output

Running in the background: -d

Every example so far ties up the terminal — the container runs in the foreground, printing its output directly, until you stop it or it exits. -d (“detached”) starts it in the background instead, immediately returning control of the terminal and printing the new container’s ID:

Running detached
click Run to see this pane's output

This is the normal way to run something you intend to keep running while you do other things — including, as covered next, actually inspecting and managing it.

The lifecycle: seeing, reading, entering, and stopping a container

docker ps lists currently running containers; docker logs shows everything a container has printed, even running detached; docker exec runs a command inside an already-running container, useful for inspecting or debugging something live without stopping it; docker stop sends a shutdown signal and waits for a graceful exit, and docker rm actually removes the stopped container — its filesystem, its logs, everything. A stopped container still exists until it’s explicitly removed:

The full lifecycle, one command at a time
click Run to see this pane's output

You can refer to a container by its full ID, a shortened prefix (as shown above), or the auto-generated name docker ps displays (like happy_turing) — all three work interchangeably with every command in this section.

Check your understanding
1/6

In docker run -p 8000:5000 my-app, what does 8000:5000 mean?

This one’s a real terminal, backed by an actual Docker daemon in a disposable sandbox — not a script. The Dockerfile from the last concept is already sitting there, waiting to be built.

Run the full lifecycle yourself, one command at a time: build the image as my-app, start it detached with 8000:5000 mapped and LOG_LEVEL=debug set, confirm it’s running with docker ps, check its startup output with docker logs, peek inside it with docker exec, then stop and remove it. When you’re done, submit for grading — it checks the actual commands you ran and their real output, not just whether the container happens to still exist.

Real terminal · live Docker sandbox

Starting this spins up a real, disposable sandbox with its own Docker daemon — it's ready for you to use for 5 minutes.