🖼️ Image Management
Pulling and Listing Images
bash
# Pull an image from Docker Hub
docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete
a9edb18cadd1: Pull complete
589b7251471a: Pull complete
Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Status: Downloaded newer image for nginx:latest
# Pull a specific version
docker pull nginx:1.24
docker pull python:3.11-slim
docker pull mysql:8.0
# List local images
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 2 weeks ago 141MB
nginx 1.24 a8758716bb6a 3 weeks ago 141MB
python 3.11-slim f9a40a850103 1 week ago 137MB
mysql 8.0 3218b38490ce 3 weeks ago 516MB
# Search for images
docker search redis
NAME DESCRIPTION STARS OFFICIAL
redis Redis is an open source ... 11000 [OK]Deleting Images
bash
# Delete a specific image
docker rmi nginx:1.24
# Force delete (even if containers are using it)
docker rmi -f nginx:latest
# Clean up all unused images (free up space)
docker image prune
# Nuclear option: delete all unused images, containers, networks
docker system prune -aUnderstanding Image Layers
Docker images are stacked layer by layer, like a mille-feuille cake 🍰. Each layer only records the differences from the previous layer.
bash
# View layer information of an image
docker history nginx:latest
IMAGE ID CREATED COMMAND SIZE
605c77e624dd 2 weeks ago CMD ["nginx" "-g" "daemon off;"] 0B
<missing> 2 weeks ago STOPSIGNAL SIGQUIT 0B
<missing> 2 weeks ago EXPOSE map[80/tcp:{}] 0B
<missing> 2 weeks ago ENTRYPOINT ["/docker-entrypoint.sh"] 0B
<missing> 2 weeks ago COPY 30-tune-worker-processes.sh /docker... 4.62kB
<missing> 2 weeks ago RUN /bin/sh -c set -x && addgroup -g 101... 61.1MB
<missing> 2 weeks ago /bin/sh -c #(nop) ADD file:caec368f5a54f... 77.8MB💡 Tip: 💡 Why do layers matter? Multiple images can share the same layers! For example, both nginx and python are based on debian — the debian base layer is stored only once, saving disk space.
Building Images with Dockerfile
A Dockerfile is the recipe for an image — it tells Docker step by step how to "cook" it.
dockerfile
# Base image
FROM python:3.11-slim
# Set working directory (equivalent to cd /app)
WORKDIR /app
# Copy dependency files first (leverages caching — if deps haven't changed, no reinstall)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application code
COPY . .
# Expose port
EXPOSE 8000
# Startup command
CMD ["python", "app.py"]bash
# Build the image
docker build -t myapp:1.0 .
[+] Building 12.5s (10/10) FINISHED
=> [internal] load build definition from Dockerfile
=> [internal] load .dockerignore
=> [internal] load metadata for docker.io/library/python:3.11-slim
=> [1/5] FROM docker.io/library/python:3.11-slim@sha256:...
=> [2/5] WORKDIR /app
=> [3/5] COPY requirements.txt .
=> [4/5] RUN pip install --no-cache-dir -r requirements.txt
=> [5/5] COPY . .
=> exporting to image
=> => naming to docker.io/library/myapp:1.0
# Run a container with the built image
docker run -d -p 8000:8000 myapp:1.0Multi-Stage Builds (Advanced)
Multi-stage builds are like preparing the dish in the kitchen, then only bringing the dish out — not the pots and pans. This can dramatically reduce the final image size.
dockerfile
# ===== Stage 1: Build =====
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# ===== Stage 2: Run =====
FROM nginx:alpine
# Only copy the build output, no node_modules
COPY --from=builder /app/dist /usr/share/nginx/html💡 Tip: 💡 Result: the Node.js image is ~900MB, while nginx:alpine is only 40MB. The final image is 800MB+ smaller!