Tools: 5 Docker Scenarios Every Developer Should Practice (With Fixes & Best Practices) (2026)

Tools: 5 Docker Scenarios Every Developer Should Practice (With Fixes & Best Practices) (2026)

Scenario 1: The Broken Build πŸ”¨

❌ The Broken Dockerfile

1. Troubleshoot the Build

2. Fix Layer Caching

3. Optimize the Image

4. Security Hardening

Scenario 2: The Ghost Data πŸ‘»

1. Run an Ephemeral Container

2. Write Data Inside the Container

3. Destroy & Recreate

4. Named Volume Persistence

5. Verify Persistence

6. Cleanup

Scenario 3: The Flaky Database Connection 🐘

The Broken docker-compose.yml

1. Run the Stack

2. Add a Healthcheck to Postgres

3. Fix depends_on with a Condition

4. Move Secrets to .env

5. Keep Secrets Out of Git

Scenario 4: The Evil Image Scanner πŸ”

1. Build a Vulnerable Image

2. Install Trivy

3. Scan the Image

4. Fix the Base Image

5. Rescan

1. Build the Optimized Image

3. Verify the Restrictions

4. Export the Image

5. Simulate an Offline Machine

6. Restore the Image

7. Run Without Internet

What You've Learned πŸŽ“ So you know the basics of Docker β€” docker run, docker build, maybe some docker compose up. But do you know what happens when things break? This guide walks you through 5 real-world Docker scenarios that will sharpen your skills around debugging, security, storage, and production-readiness. Fix a broken Dockerfile, then optimize it to be 10x smaller and production-ready. There are at least 3 issues hiding in that Dockerfile: Copy requirements.txt first, install deps, then copy the rest of the app. This way, changing app.py won't trigger a full pip install on every build. Switch from ubuntu:latest to a slim base: Target: < 150MB image size βœ… Run with a read-only filesystem: Understand Docker's storage lifecycle and how to make data actually persist. Visit http://localhost:8080/test.txt β€” it's there! The file is gone. Why? Because the container filesystem is ephemeral β€” it only lives as long as the container does. Stop and remove the container, then start a new one with the same volume β€” your file will still be there. πŸŽ‰ Note: system prune removes stopped containers, dangling images, and unused networks β€” but not named volumes unless you add --volumes. Fix service startup dependency issues in Docker Compose. The problem: depends_on only waits for the container to start, not for Postgres to be ready to accept connections. Your web app crashes on startup. Now your web service won't start until Postgres passes its healthcheck. βœ… Never commit .env files. Ever. Find and fix vulnerabilities hiding in your Docker images. You'll see a wall of HIGH and CRITICAL CVEs. This is what ships to production when nobody checks. Expected: 0 CRITICAL vulnerabilities βœ… Make image scanning part of your CI/CD pipeline β€” not an afterthought. Run containers safely under strict resource constraints and enable offline portability. Use the hardened image from Scenario 1. Monitor resource usage live: Works fully offline. πŸš€ Great for air-gapped environments, demos, or CI runners without registry access. After completing all five scenarios, you now have hands-on experience with: Want more? Drop a comment and I can turn this into a full GitHub repo with solutions, or expand each scenario into its own deep-dive post. Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Code Block

Copy

from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return "Hello from Docker!" if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return "Hello from Docker!" if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return "Hello from Docker!" if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) Flask==2.3.0 Flask==2.3.0 Flask==2.3.0 FROM ubuntu:latest RUN apt-get update RUN apt-get install python3 COPY . /opt/app RUN pip install -r requirements.txt USER root CMD python /opt/app/app.py FROM ubuntu:latest RUN apt-get update RUN apt-get install python3 COPY . /opt/app RUN pip install -r requirements.txt USER root CMD python /opt/app/app.py FROM ubuntu:latest RUN apt-get update RUN apt-get install python3 COPY . /opt/app RUN pip install -r requirements.txt USER root CMD python /opt/app/app.py docker build -t broken-app . docker build -t broken-app . docker build -t broken-app . COPY requirements.txt . RUN pip install -r requirements.txt COPY . /opt/app COPY requirements.txt . RUN pip install -r requirements.txt COPY . /opt/app COPY requirements.txt . RUN pip install -r requirements.txt COPY . /opt/app FROM python:3.12-slim WORKDIR /opt/app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 5000 CMD ["python", "app.py"] FROM python:3.12-slim WORKDIR /opt/app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 5000 CMD ["python", "app.py"] FROM python:3.12-slim WORKDIR /opt/app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 5000 CMD ["python", "app.py"] # Run as non-root USER 1001 # Run as non-root USER 1001 # Run as non-root USER 1001 docker run --read-only --tmpfs /tmp myapp:latest docker run --read-only --tmpfs /tmp myapp:latest docker run --read-only --tmpfs /tmp myapp:latest docker run -d --name web-test -p 8080:80 nginx docker run -d --name web-test -p 8080:80 nginx docker run -d --name web-test -p 8080:80 nginx docker exec -it web-test bash echo "hello" > /usr/share/nginx/html/test.txt docker exec -it web-test bash echo "hello" > /usr/share/nginx/html/test.txt docker exec -it web-test bash echo "hello" > /usr/share/nginx/html/test.txt docker stop web-test docker rm web-test docker run -d --name web-test2 -p 8080:80 nginx docker stop web-test docker rm web-test docker run -d --name web-test2 -p 8080:80 nginx docker stop web-test docker rm web-test docker run -d --name web-test2 -p 8080:80 nginx docker volume create web-data docker run -d \ --name web-test \ -p 8080:80 \ -v web-data:/usr/share/nginx/html \ nginx docker volume create web-data docker run -d \ --name web-test \ -p 8080:80 \ -v web-data:/usr/share/nginx/html \ nginx docker volume create web-data docker run -d \ --name web-test \ -p 8080:80 \ -v web-data:/usr/share/nginx/html \ nginx docker exec -it web-test bash echo "persistent data" > /usr/share/nginx/html/test.txt docker exec -it web-test bash echo "persistent data" > /usr/share/nginx/html/test.txt docker exec -it web-test bash echo "persistent data" > /usr/share/nginx/html/test.txt docker system prune -f docker system prune -f docker system prune -f version: '3' services: web: build: . ports: - "5000:5000" environment: - DB_HOST=postgres depends_on: - postgres postgres: image: postgres:15 environment: - POSTGRES_PASSWORD=secret version: '3' services: web: build: . ports: - "5000:5000" environment: - DB_HOST=postgres depends_on: - postgres postgres: image: postgres:15 environment: - POSTGRES_PASSWORD=secret version: '3' services: web: build: . ports: - "5000:5000" environment: - DB_HOST=postgres depends_on: - postgres postgres: image: postgres:15 environment: - POSTGRES_PASSWORD=secret docker compose up docker compose up docker compose up postgres: image: postgres:15 environment: - POSTGRES_PASSWORD=secret healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 10 postgres: image: postgres:15 environment: - POSTGRES_PASSWORD=secret healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 10 postgres: image: postgres:15 environment: - POSTGRES_PASSWORD=secret healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 10 web: depends_on: postgres: condition: service_healthy web: depends_on: postgres: condition: service_healthy web: depends_on: postgres: condition: service_healthy POSTGRES_PASSWORD=secret POSTGRES_PASSWORD=secret POSTGRES_PASSWORD=secret environment: - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} environment: - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} environment: - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} FROM nginx:1.21.0 FROM nginx:1.21.0 FROM nginx:1.21.0 brew install aquasecurity/trivy/trivy brew install aquasecurity/trivy/trivy brew install aquasecurity/trivy/trivy curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh trivy image nginx:1.21.0 trivy image nginx:1.21.0 trivy image nginx:1.21.0 FROM nginx:1.25-bookworm FROM nginx:1.25-bookworm FROM nginx:1.25-bookworm FROM nginx:alpine FROM nginx:alpine FROM nginx:alpine trivy image nginx:1.25-bookworm trivy image nginx:1.25-bookworm trivy image nginx:1.25-bookworm docker run -d \ --memory=256m \ --cpus=0.5 \ --read-only \ --tmpfs /tmp \ myapp:latest docker run -d \ --memory=256m \ --cpus=0.5 \ --read-only \ --tmpfs /tmp \ myapp:latest docker run -d \ --memory=256m \ --cpus=0.5 \ --read-only \ --tmpfs /tmp \ myapp:latest docker exec -it <container_id> bash touch /etc/test # Permission denied βœ… docker exec -it <container_id> bash touch /etc/test # Permission denied βœ… docker exec -it <container_id> bash touch /etc/test # Permission denied βœ… docker stats docker stats docker stats docker save -o myapp.tar myapp:latest docker save -o myapp.tar myapp:latest docker save -o myapp.tar myapp:latest docker rmi myapp:latest docker rmi myapp:latest docker rmi myapp:latest docker load -i myapp.tar docker load -i myapp.tar docker load -i myapp.tar docker run myapp:latest docker run myapp:latest docker run myapp:latest - pip is never installed - apt-get install is missing the -y flag (hangs waiting for input) - COPY happens before dependency install β€” busting the cache on every change - βœ… Dockerfile debugging & optimization β€” fixing real build errors and shrinking image sizes - βœ… Layer caching strategies β€” speeding up builds without reinstalling dependencies - βœ… Volume persistence β€” understanding ephemeral vs. persistent storage - βœ… Compose healthchecks β€” preventing race conditions between services - βœ… Image vulnerability scanning β€” catching CVEs before they reach production - βœ… Runtime security hardening β€” non-root users, read-only filesystems, resource limits - βœ… Offline container portability β€” shipping containers without a registry