Docker & ContainersVI Β· Container LifecycleCreation and configuration
create and start β the two-phase lifecycle and what is immutable
What you'll learn
- Separate the create phase from the start phase and describe what each one writes
- Identify which container settings are frozen at create time
- Use `docker update` for the small set of fields it can actually change
- Explain why editing a running container is not an operational strategy
Prerequisites
Verified against Docker Engine 29.x Β· Docker Engine 28.x Β· Docker Compose 2.x Β· containerd 2.x Β· runc 1.2.x Β· BuildKit 0.20+ Β· Linux kernel 5.15+ Β· Ubuntu 24.04 LTS Β· Debian 12 (Bookworm) Β· 2026-08-11
docker run looks like one operation. It is two, and the seam between them
is where most of the confusion about βhow do I change this containerβ lives.
When you understand that run is create followed by start, a whole class
of operational questions answers itself: what can I change without downtime,
what forces a replacement, and why the configuration you see in
docker inspect never drifts from what the container is actually running.
The seam
That last point is the one operators trip over. A container is bound to an
image digest, not to a tag, from the moment docker create succeeds.
Seeing the phases separately
$ docker create --name web -p 8080:80 --restart unless-stopped nginx:1.273f9c0a1e5b7d2c84a6f0e1b3d5c7a9f2b4d6e8c0a2f4b6d8e0c2a4f6b8d0e2c4Illustrative output
The container now exists and consumes disk, but docker ps will not show it:
$ docker ps -a --filter name=web --format 'table {{.Names}}\t{{.State}}\t{{.Status}}'NAMES STATE STATUS
web created CreatedIllustrative output
STATE is the machine-readable field; STATUS is the human string. Both are
worth knowing β scripts that grep STATUS for the word Up break on the
Up 4 days (healthy) variant, while --filter status=running does not.
Starting it is a separate call:
docker start webdocker start -a attaches stdout and stderr and forwards signals, which makes
it behave much like a foreground docker run. docker start -i additionally
attaches stdin. Both flags exist on start; they are not exclusive to run.
Why the split exists
Three practical reasons, all of which still matter:
- Order of operations. You can create a container, attach it to a network that does not exist yet, or wait for a dependency, and start it later. The expensive part (pulling the image, allocating the layer) is done up front.
- Deterministic restart.
docker starton an existing container replays the exact stored spec. There is no command line to get wrong the second time. - Inspection before execution.
docker inspecton a created container shows you the resolved configuration β including every default the daemon filled in β before anything runs.
$ docker inspect --format '{{.State.Status}} {{.State.StartedAt}} {{.Image}}' webcreated 0001-01-01T00:00:00Z sha256:5ed8fcc66f4ed123c1b2560ed708dc148755876c3d33d7ba7a8f0f3d8b93a4e2Illustrative output
The zero timestamp is the tell: this container has never been started. The
.Image field is already a digest even though you typed a tag.
What create freezes
This is the operational core of the lesson. Almost everything is frozen.
| Setting | Changeable on a live container? | How |
|---|---|---|
| Image | No | Replace the container |
| Command / entrypoint | No | Replace the container |
| Environment variables | No | Replace the container |
| Published ports | No | Replace the container |
| Volumes and bind mounts | No | Replace the container |
| Network attachments | Partly | docker network connect / disconnect |
| Hostname, user, working dir | No | Replace the container |
| Labels | No | Replace the container |
| Name | Yes | docker rename |
| CPU limits and shares | Yes | docker update |
| Memory limits | Yes | docker update |
| PIDs limit | Yes | docker update |
| Block I/O weight | Yes | docker update |
| Restart policy | Yes | docker update |
docker update is a resource-and-restart-policy tool. Its flag list is short
and it has not grown: CPU period, quota, shares, --cpus, cpuset, memory,
memory reservation, memory swap, blkio weight, PIDs limit, and --restart.
There is no --env, no --publish, no --mount.
docker update --memory 1g --memory-swap 1g --restart unless-stopped webReplacement is the normal operation
Because the spec is frozen, the routine way to change a container is to replace it. That is not a workaround; it is the model, and it is the same model Compose and every orchestrator use.
docker stop web
docker rm web
docker run -d --name web -p 8080:80 \
--env DB_HOST=db2.example.com \
--restart unless-stopped \
nginx:1.27Two things follow from this that are easy to miss:
- Anything written to the writable layer is gone. Configuration you
patched with
docker exec, packages you installed to debug something, a log file you were reading β all of it disappears withdocker rm. Only volumes and bind mounts survive. - The new container gets a new ID and a new IP on the bridge network. Anything that recorded the old address β a reverse proxy with a cached upstream, a monitoring target list β needs to resolve by name, not by address.
start versus restart
They are not the same command with different moods:
docker startworks on a container that is not running. On a running container it is a no-op and exits 0, which is convenient in idempotent scripts and confusing when you expected a reload.docker restartstops the container β SIGTERM, wait, SIGKILL, the full stop path β and then starts it. It accepts-t/--timeoutand-s/--signalfor the stop half.
Neither re-reads the image. docker restart on a container created from
myapp:latest runs the same digest it has always run, even if the tag moved
an hour ago. Pulling a new image and restarting the old container is the
classic βI deployed and nothing changedβ incident.
Knowledge check
Knowledge check Β· 4 questions
Q1. What does `docker create` actually do?
Q2. Which of these can `docker update` change on a running container? Select all that apply.
Q3. Running `docker restart` on a container created from `myapp:latest` will pick up a newer image if the tag has moved.
Q4. A container is in the `created` state and has never been started. Which statement is true?
Passing score: 75%. Answers are checked in this browser.