1.2Running containers: ports, names, modes, variables
The essentials in 30 seconds
- Publishing a port = the entry door: -p 8080:80 links port 8080 of the machine to port 80 of the container — left = host, right = container; without publishing, the service stays invisible.
- Detached or interactive, two modes: services run with -d (background), one-off tools with -it (attached terminal) — a server in -it blocks the terminal.
- Configuring without rebuilding: -e KEY=value drives official images and --name gives a stable identity to target the container (logs, exec, stop).
Running mini-case — Idir launches the test stack
Idir must show the application to his manager: a Postgres database and an Nginx frontend on his machine. He launches the database detached, named bdd, with the password passed via -e — without publishing its port, useless for a local demo. Then he launches the web named web with -p 8080:80 and opens http://localhost:8080: the page displays. When his manager asks « which container is the database? », Idir answers « bdd » — a name, not a hexadecimal identifier.
Continuation of case 1.1 — Idir moves from chosen images to launched containers.
1. Publishing a port: the entry door
A container lives in its isolated network: without publishing, its port 80 is invisible from the machine. -p 8080:80 links port 8080 of the machine to port 80 of the container. The rule: left = host, right = container. Two containers can expose the same internal port with different host ports.
Publish only what must be reached from the outside: the web frontend yes, the database no (it stays reachable internally, section 1.4).
2. Detached or interactive: two modes
Services run detached (-d, in the background). One-off tools run interactive (-it, attached terminal: docker run -it --rm ubuntu:24.04 bash). Never mix them: a server in -it blocks the terminal, a shell in -d is unusable.
The reflex: « is it a service that must run alone? -d. Is it a tool I need the keyboard for? -it. »
3. Configuring without rebuilding: -e and --name
Official images are driven by environment variables (-e POSTGRES_PASSWORD=secret): no need to rebuild an image to change a password. --name gives a stable identity to target the container (logs, exec, stop).
Name + variables + ports: 90% of launches fit on one line. Variables are frozen at creation: to change one, delete and relaunch.
🔎 Concrete example — 🔎 Concrete example — Reachable Postgres and Nginx
Idir's demo stack: a discreet database, an accessible web.
docker run -d --name bdd -e POSTGRES_PASSWORD=secret postgres:16.4
docker run -d --name web -p 8080:80 nginx:1.27
Reading: the database runs in the background with no published port (useless), the web answers on http://localhost:8080.
Lesson: publish only what must be reached from the outside.
Section vocabulary
- -p host:container
- Publishing a container port to the host machine; left = host, right = container.
Simple example: -p 8080:80 makes Idir's web reachable on http://localhost:8080.
What it is not: opening a port only inside the container.
Reflex: re-read left/right before each run.
- -d (detached)
- Background mode: the container runs without blocking the terminal; the mode for services.
Simple example: Idir's bdd database and web run with -d during the demo.
What it is not: an attached terminal you must leave open.
Reflex: long-lived service = -d.
- -it (interactive)
- Terminal attached to the container (often with --rm for throwaway uses); the mode for one-off tools.
Simple example: docker run -it --rm ubuntu:24.04 bash to tinker.
What it is not: the mode of a production server.
Reflex: need the keyboard = -it, never for a server.
- -e and --name
- -e injects a configuration variable at startup; --name gives a stable identity to control the container.
Simple example: -e POSTGRES_PASSWORD=secret and --name bdd at Idir's.
What it is not: configuration hard-coded into the image.
Reflex: config in -e, systematic naming on long-lived services.
In practice — In practice — Launching two services
- Launch a named postgres database with password via -e.
- Launch nginx with 8080:80 publishing and open localhost:8080.
- Open a shell in each container (exec) and compare.
- Stop and cleanly remove both containers.
Script ready to say — launching a service (30 s)
« I launch detached with a name: --name web -d. I publish the host port to the container: -p 8080:80, left host, right container. I pass the config via -e variables, without touching the image. I check on localhost:8080. »
Say while typing the command line by line; show the terminal blocked by -it for contrast.
Copy-paste template — the launch line
docker run -d --name MONSERVICE \
-p HOTE:CONTENEUR \
-e CLE=valeur \
image:tag-fige
# E.g. Idir's web:
# docker run -d --name web -p 8080:80 nginx:1.27
Idir's demo in Algiers
As above: unpublished bdd + web on 8080:80 — the manager sees the app, the database stays invisible from the outside.
Throwaway tool
docker run -it --rm ubuntu:24.04 bash: attached terminal, auto-removal on exit — the mode for tools, never for servers.
Two frontends coexist
Two Nginx with the same internal port 80, published as 8080:80 and 8081:80: the host port differs, the container port is identical.
Changing a password
Variables with -e are frozen at creation: delete the container and relaunch with the new value — no magic restart.
✓ Best practices
- Systematically name long-lived services.
- Publish only the needed ports.
- Pass config via -e, never hard-coded in the image.
✗ Common pitfalls
- Reversing host:container in -p.
- Launching a server with -it (blocked terminal).
- Putting a plain-text password in history without thinking.
Key takeaways
- -p links host and container (left/right).
- -d for services, -it for tools.
- -e configures without rebuilding.
- --name makes everything manageable.
48h challenge — apply tomorrow
Launch two named services (database with -e unpublished + web on 8080:80), open localhost:8080, then stop and remove cleanly. Note the host:container order without reversing it.
- I publish ports in the right order (host:container).
- I choose -d for a service, -it for a tool.
- I configure with -e and name each long-lived service.
Frequently asked questions
Why does localhost:80 not answer although the container runs?
Because the port is not published: the service listens in the container's isolated network. Add -p host:container to the run — left = host, right = container.
Must I restart to change an -e variable?
Yes: variables are frozen at creation. Delete and relaunch (or move to Compose at level 3 to version it all).
You run 'docker run -d -p 8080:80 nginx'. What does 8080:80 mean?