KAHIBARO
Discord Login Register

21.4. Containers

What Is a Container?

A container is a lightweight, isolated environment that runs your application and everything it needs, such as libraries and runtime, on top of a shared operating system kernel.

You can think of it as a more efficient and portable alternative to a full virtual machine. Instead of emulating an entire computer, a container shares the host OS, but keeps processes, files, and network separated from other containers.

Key points:

Important: A container is a running instance of an image.
Image = template. Container = process created from that template.

Example analogy:

Or:

You can run many containers from the same image, just like you can create many objects from the same class.

Containers vs Virtual Machines

Containers and virtual machines solve a similar problem, but in different ways.

FeatureContainerVirtual Machine
Boot timeVery fast (seconds or less)Slow (tens of seconds to minutes)
Resource usageLight, shares host OS kernelHeavy, full OS per VM
IsolationProcess level, via namespaces and cgroupsStrong, full OS boundary
Image sizeSmall to mediumLarge (many GB)
PortabilityHighMedium
Typical useMicroservices, APIs, small servicesFull OS environments, legacy systems

For backend development, containers are ideal for:

You should still understand that containers use the host kernel. They are not a full OS, although they can look like one from the inside.

Basic Container Lifecycle

A container has a simple lifecycle:

  1. Pull image
    docker pull python:3.12-slim
  2. Create and start container
    docker run python:3.12-slim python -V
  3. Run main process
    The container runs its main process (for example python, uvicorn, postgres).
  4. Stop
    When the main process exits, the container stops.
  5. Remove (optional)
    You can delete stopped containers to free space.

Rule: A container exists only as long as its main process is running.
If that process exits, the container stops automatically.

Example:

bash
# Start an interactive container
docker run -it --name demo python:3.12-slim bash
# Inside the container:
exit  # or press Ctrl+D

As soon as bash exits, the container stops. docker ps will not show it anymore, but docker ps -a will.

Running Your First Containers

Running a Simple Container

Try a very simple example:

bash
docker run hello-world

What happens:

If you run:

bash
docker ps -a

you will see a stopped container with hello-world as the image.

Interactive Containers

You can start a container and get a shell inside it.

bash
docker run -it --name py-shell python:3.12-slim bash

Flags:

Inside the container:

bash
python -V
touch example.txt
ls

You will see example.txt inside the container file system, but not on your host.

Type exit to stop the container.

Outside again:

bash
docker ps -a

Look for py-shell. Status should be "Exited".

Detached vs Attached Containers

Containers can run attached to your terminal, or in the background.

Attached Mode

Example:

bash
docker run --name counter alpine:3.18 sh -c "i=0; while true; do echo $i; i=$((i+1)); sleep 1; done"

You will see numbers printed every second. To stop:

Detached Mode

To run in the background, use -d.

bash
docker run -d --name counter-bg alpine:3.18 sh -c "i=0; while true; do echo $i; i=$((i+1)); sleep 1; done"

Now:

You can see it:

bash
docker ps

To see logs:

bash
docker logs counter-bg

To stop:

bash
docker stop counter-bg

Rule:
Use -d to run a container in the background.
Use docker logs <name> to see its output.

Naming and Inspecting Containers

Naming Containers

You can let Docker auto generate names or specify your own.

bash
# Auto generated name
docker run alpine:3.18 echo "hello"
# Custom name
docker run --name my-alpine alpine:3.18 echo "hello"

Custom names are very useful when you have many containers.

Listing Containers

Common commands:

bash
# Running containers
docker ps
# All containers (including stopped)
docker ps -a

Typical columns:

ColumnMeaning
CONTAINER IDShort ID of the container
IMAGEImage used to create the container
COMMANDMain command/process
STATUSRunning, Exited, etc
PORTSPort mappings (if any)
NAMESContainer name

Inspecting Containers

You can see detailed information about a container.

bash
docker inspect my-alpine

This prints JSON with details such as:

You usually do not need all of it, but it is useful when you debug.

Container File System and Persistence

Each container has its own file system, isolated from the host.

Example:

bash
docker run -it --name files-test alpine:3.18 sh
# Inside the container:
touch /tmp/inside.txt
ls /tmp
exit

On your host:

bash
ls /tmp

You will not see inside.txt. It exists only inside the container.

If you remove the container, its file system is removed too.

bash
docker rm files-test

Important: Files created inside a container are ephemeral.
If the container is removed, those files are gone, unless you used volumes or bind mounts.

Volumes and persistent storage are covered in another chapter. For now, remember that you should not store important data only in a container file system.

Ports and Networking Basics for Containers

Backend services need to listen on a port inside the container and be reachable from the host or other containers.

Exposing a Port to the Host

Assume you have an image that runs a server on port 8000 inside the container.

To map it to port 8000 on your host:

bash
docker run -d --name web -p 8000:8000 my-backend-image

Format:

bash
-p <HOST_PORT>:<CONTAINER_PORT>

Examples:

Now you can access the service at http://localhost:8000.

If you do not add -p, the service inside the container will not be reachable from the host.

Multiple Containers from the Same Image

You can run multiple containers from the same image with different names and ports.

bash
docker run -d --name api-v1 -p 8001:8000 my-backend-image
docker run -d --name api-v2 -p 8002:8000 my-backend-image

Both containers run the same code, but you access them:

Managing Containers: Start, Stop, Remove

You will create, stop, and remove containers all the time while developing.

Stopping Containers

bash
# Graceful stop (send SIGTERM then SIGKILL if needed)
docker stop my-container
# Force stop (SIGKILL)
docker kill my-container

You normally use docker stop. Use docker kill only if the process does not respond.

Starting Containers

If a container is stopped, you can start it again.

bash
docker start my-container

This resumes the container with the same process command, environment, and configuration that were used originally.

Removing Containers

To remove a container:

bash
docker rm my-container

If the container is still running, you will get an error.

To stop and remove in one step:

bash
docker rm -f my-container

Cleaning Up

Over time you will collect many stopped containers. You can clean them up:

bash
# Remove all stopped containers
docker container prune

Docker will ask for confirmation.

Rule:
Do not store important data in containers that you plan to prune or remove.
Use volumes or an external database for persistence.

Common Practical Examples

Running a Temporary Python Script

You might want to test Python code without installing Python on your host.

bash
docker run --rm python:3.12-slim python -c "print('Hello from container')"

Here:

Testing a Simple HTTP Server

Run a tiny HTTP server in a container:

bash
docker run -d --name http-test -p 8080:80 nginx:alpine

Now open http://localhost:8080 in your browser. You will see the default Nginx welcome page.

To stop and remove:

bash
docker stop http-test
docker rm http-test

Attaching to a Running Container

If you want to get a shell inside a running container, use exec:

bash
docker exec -it http-test sh

You are now inside the container. To exit, type exit. The container keeps running because the main process (Nginx) is still alive.

Typical Mistakes New Developers Make

Here are some common issues and how to avoid them.

MistakeExplanationFix
Forgetting -p when running APIsContainer runs, but service is not reachable from hostAlways add -p HOST:CONTAINER when you need external access
Expecting data to persist inside containerData written to container filesystem is removed with itUse volumes or external databases
Confusing image and containerTrying docker start on an image, not a containerRemember you start containers, not images
Not naming containersHard to remember or manage themUse --name with a clear name
Forgetting --rm for one-off commandsMany stopped containers piling upUse --rm when running temporary commands

Understanding these basics of containers will make it much easier to build, run, and deploy backend services consistently across your development, testing, and production environments.

Views: 10

Comments

Please login to add a comment.

Don't have an account? Register now!