By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
Hyper-practical, zero-fluff guide for engineers in production
You’re debugging a Kubernetes pod that’s mysteriously filling up disk space, or you’re trying to optimize a Docker image that’s ballooned to 2GB. Images and containers aren’t just "files" – they’re layered filesystems with copy-on-write (CoW) mechanics. Ignore this, and you’ll waste storage, slow down deployments, or break applications when they least expect it.
Real-world scenario:- You deploy a new version of your app, but the container fails to start because /var/log is full. The logs should be ephemeral, but they’re persisting across restarts. Why? Because you wrote to a layer that wasn’t supposed to exist.- Your CI/CD pipeline takes 10 minutes to build an image because it’s re-downloading 1.5GB of dependencies every time. You could cut that to 30 seconds if you understood layers.
/var/log
This guide gives you:✅ The mental model to debug storage issues in seconds.✅ The power to shrink images by 90% and speed up builds.✅ The confidence to explain to your team why docker commit is a terrible idea.
docker commit
Dockerfile
FROM
RUN
&&
COPY
ADD
ENV
CMD
ENTRYPOINT
/var/lib/docker/volumes/
.dockerignore
.gitignore
docker build
node_modules
.git
docker --version
Goal: See how layers work in a real image.
bash docker pull node:18-alpine
bash docker inspect node:18-alpine --format='{{.RootFS.Layers}}'
[sha256:abc123... sha256:def456...]
Count the layers: bash docker inspect node:18-alpine --format='{{len .RootFS.Layers}}' Output: 5 (or similar).
bash docker inspect node:18-alpine --format='{{len .RootFS.Layers}}'
5
Why this matters: If you see 100+ layers, your image is bloated. Each layer adds overhead.
Goal: See how CoW works when a container modifies a file.
dockerfile FROM alpine:3.18 RUN echo "Original content" > /data.txt CMD ["cat", "/data.txt"]
Build and run: bash docker build -t cow-demo . docker run --name cow-test cow-demo Output: Original content
bash docker build -t cow-demo . docker run --name cow-test cow-demo
Original content
Modify the file inside the container: bash docker exec -it cow-test sh -c "echo 'Modified content' > /data.txt && cat /data.txt" Output: Modified content
bash docker exec -it cow-test sh -c "echo 'Modified content' > /data.txt && cat /data.txt"
Modified content
Check the container layer: bash docker diff cow-test Output: C /data.txt
bash docker diff cow-test
C /data.txt
C = Changed (CoW in action! The file was copied to the writable layer).
C
Delete the container and restart: bash docker rm -f cow-test docker run --name cow-test2 cow-demo Output: Original content (the modification is gone because it was in the container layer).
bash docker rm -f cow-test docker run --name cow-test2 cow-demo
Goal: Reduce a 1.2GB Node.js image to 150MB.
dockerfile FROM node:18 WORKDIR /app COPY . . RUN npm install CMD ["node", "index.js"]
Build it: bash docker build -t naive-node-app . docker images | grep naive-node-app Output: naive-node-app latest abc123... 1.2GB
bash docker build -t naive-node-app . docker images | grep naive-node-app
naive-node-app latest abc123... 1.2GB
Optimize it: dockerfile FROM node:18-alpine # 1. Use Alpine (smaller base) WORKDIR /app COPY package*.json ./ # 2. Copy package files first (cache npm install) RUN npm install --production # 3. Only install prod deps COPY . . # 4. Copy app code last (changes most often) CMD ["node", "index.js"]
dockerfile FROM node:18-alpine # 1. Use Alpine (smaller base) WORKDIR /app COPY package*.json ./ # 2. Copy package files first (cache npm install) RUN npm install --production # 3. Only install prod deps COPY . . # 4. Copy app code last (changes most often) CMD ["node", "index.js"]
Rebuild: bash docker build -t optimized-node-app . docker images | grep optimized-node-app Output: optimized-node-app latest def456... 150MB
bash docker build -t optimized-node-app . docker images | grep optimized-node-app
optimized-node-app latest def456... 150MB
Why this works:
npm install
package.json
--production
USER
dockerfile RUN adduser -D appuser && chown -R appuser /app USER appuser
docker scan
bash docker scan optimized-node-app
FROM node:18-alpine COPY --from=builder /app/dist ./dist CMD ["node", "dist/index.js"] - Set resource limits in Kubernetes to avoid noisy neighbors:yaml resources: limits: cpu: "1" memory: "512Mi" ```
- Set resource limits in Kubernetes to avoid noisy neighbors:
latest
bash docker build -t myapp:v1.2.3 .
node_modules .git *.log
bash docker stats --no-stream
javascript console.log("This goes to stdout");
docker history
docker secret
Typical questions:1. "You need to reduce the size of a Docker image. What’s the most effective step?" - ✅ Use multi-stage builds (discards build-time dependencies). - ❌ "Use a smaller base image" (helps, but not as much as multi-stage).
❌ "The image is too large" (image size is fixed; container layer grows).
"What happens when a container modifies a file from a read-only layer?"
Key trap distinctions:- Image vs Container: Images are read-only; containers are ephemeral instances.- Layer vs Volume: Layers are for the filesystem; volumes are for persistent data.- OverlayFS vs AUFS: OverlayFS is the default (faster, fewer layers); AUFS is older (slower, more layers).
Challenge:You have a Dockerfile that installs Python and a bunch of dependencies. The image is 1.5GB. Optimize it to under 300MB without removing any functionality.
Solution:
# Stage 1: Build FROM python:3.9-slim AS builder WORKDIR /app COPY requirements.txt .RUN pip install --user -r requirements.txt # Stage 2: Runtime FROM python:3.9-alpine WORKDIR /app COPY --from=builder /root/.local /root/.local COPY . .ENV PATH=/root/.local/bin:$PATH CMD ["python", "app.py"]
Why it works:- Uses python:3.9-alpine (smaller base).- Multi-stage build discards build-time dependencies.- --user installs Python packages locally (avoids sudo).
python:3.9-alpine
--user
sudo
docker history <image>
docker diff <container>
A
D
docker build --no-cache
docker run -v /host/path:/container/path
docker run -v myvolume:/container/path
Dockerfile: COPY --chown=user:group
docker system df
docker prune
OverlayFS max layers
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.