Skip to content

Docker Perspective

Docker can be approached from two perspectives, depending on role. The Ops perspective focuses on managing running containers. The Dev perspective focuses on building applications into images. In practice you will do both - but separating them makes the mental model clearer when starting out.


The Ops workflow revolves around images and containers as runtime units - pulling them, running them, inspecting them, and cleaning them up.

Docker images contain everything an application needs to run: a stripped-down OS filesystem, the app itself, and all its dependencies. Pull one from Docker Hub:

Terminal window
docker pull nginx:latest

Verify it arrived locally:

Terminal window
docker images
# REPOSITORY TAG IMAGE ID CREATED SIZE
# nginx latest a72860cb95fd 2 weeks ago 192MB

Launch a container from the image:

Terminal window
docker run --name my-nginx -d -p 8080:80 nginx:latest
FlagWhat it does
--name my-nginxGives the container a human-readable name instead of a random one
-dDetached mode - runs in the background, your terminal stays free
-p 8080:80Maps port 8080 on your host to port 80 inside the container

Confirm it is running:

Terminal window
docker ps
# CONTAINER ID IMAGE COMMAND STATUS PORTS
# 3f4e2c1a9b82 nginx:latest "/docker-entrypoint…" Up 3 seconds 0.0.0.0:8080->80/tcp

Open http://localhost:8080 in a browser - you should see the nginx welcome page.

3. Execute Commands Inside a Running Container

Section titled “3. Execute Commands Inside a Running Container”

Attach an interactive shell to inspect the container from the inside:

Terminal window
docker exec -it my-nginx bash

Once inside, you have a shell in the container’s isolated filesystem. You can explore it like any Linux environment:

Terminal window
ls /etc/nginx/
cat /etc/nginx/nginx.conf
exit # returns you to your host terminal
Terminal window
docker stop my-nginx # gracefully stops the container (SIGTERM, then SIGKILL after timeout)
docker rm my-nginx # removes the stopped container

To see all containers including stopped ones:

Terminal window
docker ps -a

Force-stop and remove in one step (skips the graceful shutdown):

Terminal window
docker rm my-nginx -f

The Dev Perspective: Containerizing an Application

Section titled “The Dev Perspective: Containerizing an Application”

The Dev workflow starts with source code and ends with a runnable container image. This process - packaging an app and its dependencies into a single image - is called containerizing.

Containerizing an application
Terminal window
git clone https://github.com/your-org/my-node-app
cd my-node-app

Every app you containerize needs a Dockerfile - a plain-text file that tells Docker how to build the image, step by step.

A minimal Node.js example:

# Start from the official Node.js base image
FROM node:20-alpine
# Set the working directory inside the container
WORKDIR /app
# Copy dependency manifest first (for layer caching)
COPY package*.json ./
RUN npm ci --only=production
# Copy the rest of the application source
COPY . .
# Expose the port the app listens on
EXPOSE 3000
# The command to run when the container starts
CMD ["node", "server.js"]

The Dockerfile is the blueprint. Everything needed to reproduce this environment - the OS base, the runtime, the dependencies, the app code - is declared here. See Writing Dockerfiles for the full reference.

Terminal window
docker build -t my-node-app:1.0 .
PartWhat it means
docker buildReads the Dockerfile and executes each instruction as a layer
-t my-node-app:1.0Tags the resulting image with a name and version
.The build context - Docker sends this directory to the daemon

Watch the layers build in sequence. Each RUN, COPY, and FROM instruction creates a new cached layer:

Terminal window
docker build -t my-node-app:1.0 .
# [1/5] FROM node:20-alpine
# [2/5] WORKDIR /app
# [3/5] COPY package*.json
# [4/5] RUN npm ci
# [5/5] COPY . .
# Successfully built 4a7c9f21b38e
# Successfully tagged my-node-app:1.0
Terminal window
docker run --name my-app -d -p 3000:3000 my-node-app:1.0

Open http://localhost:3000 to see the live application running inside a container.


Remove a running container (force):

Terminal window
docker rm my-app -f

Remove the image from your local machine:

Terminal window
docker rmi my-node-app:1.0

Remove all stopped containers, unused networks, dangling images, and build cache in one pass:

Terminal window
docker system prune

CommandWhat it does
docker versionVerify client and daemon are installed and communicating
docker pull <image>Download an image from a registry
docker imagesList locally available images
docker run -d -p <host>:<container> <image>Start a detached container with a port mapping
docker psList running containers
docker ps -aList all containers including stopped
docker exec -it <name> bashOpen an interactive shell inside a running container
docker stop <name>Gracefully stop a container
docker rm <name>Remove a stopped container
docker rm <name> -fForce-stop and remove in one step
docker build -t <name>:<tag> .Build an image from a Dockerfile in the current directory
docker rmi <image>Remove a local image
docker system pruneClean up all stopped containers, networks, and dangling images