Skip to main content

Docker Commands for MLOps: Essential Commands for ML Engineers

Calculating read time…

Think of Docker like a vending machine for software. You press a button (run a command) and out pops exactly what you need — a perfectly packaged, ready-to-run application.

But just like a vending machine has buttons for different items, Docker has commands for different jobs — building, running, stopping, inspecting, cleaning, and shipping containers.




💡 Why Docker Commands Matter in MLOps:

Every ML model deployment involves Docker commands. When you train a model, package it, push it to Oracle Container Registry (OCIR), or deploy it to OCI Container Instances — you're typing Docker commands.


📚 Commands We'll Cover

  • 🔹 Group 1: Image Commands — build, images, pull, push, tag, rmi, history, inspect
  • 🔹 Group 2: Container Commands — run, ps, start, stop, rm, exec, logs, stats
  • 🔹 Group 3: Registry Commands — login, logout, search
  • 🔹 Group 4: System Commands — info, version, system prune, network, volume
  • 🔹 Group 5: Compose Commands — up, down, scale, logs
  • 🔹 Real MLOps Workflows — chained command sequences for production

🗺️ The Docker Command Universe — One Diagram to Rule Them All

YOUR LAPTOP REGISTRY (OCIR) OCI CLOUD

Dockerfile
    ↓ docker build
Local Image ──── docker push ────▶ OCIR Image ──── docker pull ────▶ OCI Instance
    ↓ docker run                                                      ↓ docker run
Container                                                            Container
    ↓ docker logs / exec / stats
Monitor & Debug

docker stop → docker rm → docker rmi → docker system prune

🖼️ Group 1: Image Commands

Images are the blueprints for your containers. These commands let you create, list, tag, push, pull, and delete them. Think of images as the recipe — containers are the meal you cook from it.


1. docker build — Create an Image from a Dockerfile

Syntax: docker build [OPTIONS] PATH

What it does: Reads your Dockerfile line by line and builds a Docker image. Like following a recipe step by step until the dish is ready.

# Most common — build from current directory, give it a name and version tag
docker build -t fraud-model:1.0 .

# Build with a build argument (e.g. specify environment)
docker build -t fraud-model:1.0 --build-arg environment=production .

# Build from a specific Dockerfile (not the default)
docker build -t fraud-model:1.0 -f docker/Dockerfile.prod .

# Build without using any cached layers (fresh build from scratch)
docker build -t fraud-model:1.0 --no-cache .

# Build and see detailed output for each layer
docker build -t fraud-model:1.0 --progress=plain .
💡 The dot . at the end means: "Use the current folder as the build context." Docker sends all files in this folder to the Docker engine. That's why .dockerignore matters — to exclude large unnecessary files!

2. docker images — List All Local Images

Syntax: docker images [OPTIONS] [REPOSITORY[:TAG]]

What it does: Shows every Docker image stored on your machine — like opening your fridge and seeing all the meal-prep containers.

# List all images
docker images

# REPOSITORY           TAG       IMAGE ID       CREATED        SIZE
# fraud-model          1.0       a9f3b2c1d8e4   2 hours ago    612MB
# fraud-model          2.0       b8d4e7f2c3a1   5 days ago     598MB
# python               3.10-slim-buster  c2e8f1b4...  2 weeks ago  125MB

# List images for a specific repository only
docker images fraud-model

# Show only image IDs (useful for scripting)
docker images -q

# Show all images including intermediate layers
docker images -a

# Filter images by label
docker images --filter "label=team=ml-engineering"

# Show images with custom format
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
✅ Run docker images regularly to track how many images are accumulating on your machine. ML images are large (500 MB – 5 GB each). Old unused ones quietly eat up your disk.

3. docker pull — Download an Image from a Registry

Syntax: docker pull [OPTIONS] NAME[:TAG]

What it does: Downloads a Docker image from a registry to your local machine. Like downloading an app from an app store — but for containers.

# Pull a specific Python base image
docker pull python:3.10-slim-buster

# Pull from Oracle Container Registry (OCIR)
docker pull ap-mumbai-1.ocir.io/mytenancy/fraud-model:2.0

# Pull the latest tag (NOT recommended for production — always pin versions!)
docker pull python:latest

# Pull a specific digest (most precise — guaranteed exact image)
docker pull python@sha256:a3f7b2c19d4e8f6a1b2c3d4e5f6789ab...

# Pull all tags of a repository
docker pull --all-tags python
❌ Never use :latest in production! docker pull python:latest gives you whatever is "latest" today — which changes without warning and will break your ML model. Always pin exact versions: python:3.10.12-slim-buster

4. docker push — Upload an Image to a Registry

Syntax: docker push [OPTIONS] NAME[:TAG]

What it does: Uploads your locally-built image to a registry (like OCIR) so it can be pulled and run on OCI servers. Like uploading a file to the cloud so others can download it.

# Push to Oracle Container Registry (OCIR)
docker push ap-mumbai-1.ocir.io/mytenancy/fraud-model:2.0

# Push all tags of an image
docker push --all-tags ap-mumbai-1.ocir.io/mytenancy/fraud-model

# Practical full push sequence:
# Step 1 — Build
docker build -t fraud-model:2.0 .

# Step 2 — Tag with full OCIR path
docker tag fraud-model:2.0 ap-mumbai-1.ocir.io/mytenancy/fraud-model:2.0

# Step 3 — Push
docker push ap-mumbai-1.ocir.io/mytenancy/fraud-model:2.0

5. docker tag — Give an Image a New Name/Label

Syntax: docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

What it does: Creates a new alias (tag) for an existing image. Like putting a different label on the same jar of jam — the contents are identical, only the label changes. No data is duplicated. Just a new pointer.

# Tag local image with full OCIR registry path (required before push!)
docker tag fraud-model:2.0 \
    ap-mumbai-1.ocir.io/mytenancy/fraud-model:2.0

# Add a 'latest' alias alongside the versioned tag
docker tag fraud-model:2.0 fraud-model:latest

# Tag with git commit hash (great for traceability in CI/CD)
docker tag fraud-model:2.0 fraud-model:$(git rev-parse --short HEAD)

# Tag for promotion: dev → staging → production
docker tag fraud-model:2.0-dev  fraud-model:2.0-staging
docker tag fraud-model:2.0-staging  fraud-model:2.0-prod
💡 Tagging Strategy for MLOps:
Use version + commit hash for full traceability. Example: fraud-model:2.0-a9f3b2c
This tells you the model version AND exactly which code commit produced it. In 6 months you can reproduce the exact image.

6. docker rmi — Delete a Local Image

Syntax: docker rmi [OPTIONS] IMAGE [IMAGE...]

What it does: Removes one or more images from your local machine. Like deleting a recipe book you no longer need — frees up disk space immediately.

# Remove a specific image by name and tag
docker rmi fraud-model:1.0

# Remove by image ID
docker rmi a9f3b2c1d8e4

# Force remove (even if a stopped container still references it)
docker rmi -f fraud-model:1.0

# Remove multiple images at once
docker rmi fraud-model:1.0 fraud-model:1.1 python:3.9-slim

# Remove ALL dangling images (untagged intermediate layers — safe to delete)
docker rmi $(docker images -f "dangling=true" -q)

# Remove ALL local images (nuclear option — use with caution!)
docker rmi $(docker images -q)

7. docker history — See Every Layer in an Image

Syntax: docker history [OPTIONS] IMAGE

What it does: Shows every layer that makes up a Docker image — what command created it, when, and how big it is. Like an X-ray that shows all the internal layers of your image.

# Show full image history
docker history fraud-model:2.0

# IMAGE          CREATED        CREATED BY                                SIZE
# a9f3b2c1d8e4   2 hours ago    ENTRYPOINT ["/app/entrypoint.sh"]         0B
# b8d4e7f2c3a1   2 hours ago    RUN chmod +x /app/entrypoint.sh           0B
# c9e5f8a3b2d1   2 hours ago    COPY . /app                               18.4MB
# d7f1e4b9c3a2   3 hours ago    RUN pip3 install -r requirements.txt      412MB ← biggest!
# e6c2f7a8b4d3   3 hours ago    COPY requirements.txt /app/               1.2kB
# f5b8e3c9d1a4   3 hours ago    RUN apt-get install build-essential       52MB
# a4c7f2b6e8d5   3 hours ago    WORKDIR /app                              0B
# python:3.10    2 weeks ago    ...                                       125MB

# Show full command (don't truncate long commands)
docker history --no-trunc fraud-model:2.0

# Show only sizes — great for optimizing your image
docker history --format "{{.Size}}\t{{.CreatedBy}}" fraud-model:2.0
✅ Use docker history to find which layer is bloating your image. The pip install layer is almost always the largest. If it's over 1 GB, consider multi-stage builds or a slimmer base image.

8. docker inspect — Get Full Metadata of an Image or Container

Syntax: docker inspect [OPTIONS] NAME|ID [NAME|ID...]

What it does: Returns full JSON metadata about an image or container — every environment variable, port, volume mount, layer digest, and configuration setting. The most detailed view Docker offers.

# Inspect an image
docker inspect fraud-model:2.0

# Inspect a running container
docker inspect fraud-api-prod

# Extract just one field using --format (saves hunting through JSON)
# Get the exposed port
docker inspect --format='{{.Config.ExposedPorts}}' fraud-model:2.0

# Get the ENTRYPOINT command
docker inspect --format='{{.Config.Entrypoint}}' fraud-model:2.0

# Get ALL environment variables
docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' fraud-api-prod

# Get container IP address (useful for debugging networking)
docker inspect --format='{{.NetworkSettings.IPAddress}}' fraud-api-prod

# Get when the container was started
docker inspect --format='{{.State.StartedAt}}' fraud-api-prod

📦 Group 2: Container Commands

Containers are the running instances of images. These commands control the lifecycle of containers — from start to stop, from monitoring to debugging.


9. docker run — Create and Start a Container

Syntax: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

What it does: This is the most important Docker command. It creates a brand new container from an image AND starts it immediately. Like pressing "Start" on a video game — the image is the game disc, the container is the game session that begins. 🎮

# ── BASIC ─────────────────────────────────────────────────────────────

# Run and see output in terminal (foreground — Ctrl+C to stop)
docker run fraud-model:2.0

# Run in the background (detached mode — returns container ID)
docker run -d fraud-model:2.0

# Run with a friendly name (easier than using container IDs)
docker run -d --name fraud-api fraud-model:2.0


# ── PORT MAPPING ───────────────────────────────────────────────────────
# Format: -p HOST_PORT:CONTAINER_PORT

# Map container port 8083 to your laptop's port 8083
docker run -d -p 8083:8083 --name fraud-api fraud-model:2.0

# Map to a different host port (useful when 8083 is already in use)
docker run -d -p 9090:8083 --name fraud-api-v2 fraud-model:2.0

# Map multiple ports
docker run -d -p 8083:8083 -p 9229:9229 fraud-model:2.0


# ── ENVIRONMENT VARIABLES ──────────────────────────────────────────────

# Pass a single environment variable
docker run -d -p 8083:8083 \
    -e ENVIRONMENT=production \
    fraud-model:2.0

# Pass multiple environment variables
docker run -d -p 8083:8083 \
    -e ENVIRONMENT=production \
    -e LOG_LEVEL=INFO \
    -e OCI_REGION=ap-mumbai-1 \
    -e MODEL_PATH=/app/models/fraud_model.pkl \
    --name fraud-api \
    fraud-model:2.0

# Load env vars from a file (BEST PRACTICE — keeps secrets out of CLI history)
docker run -d -p 8083:8083 \
    --env-file .env.production \
    --name fraud-api \
    fraud-model:2.0


# ── VOLUME MOUNTS ──────────────────────────────────────────────────────
# Format: -v HOST_PATH:CONTAINER_PATH[:ro]

# Mount a local folder into the container (for loading models without rebuilding)
docker run -d -p 8083:8083 \
    -v $(pwd)/models:/app/models \
    --name fraud-api \
    fraud-model:2.0

# Mount as READ-ONLY (prevents container from modifying your local files)
docker run -d -p 8083:8083 \
    -v $(pwd)/models:/app/models:ro \
    --name fraud-api \
    fraud-model:2.0


# ── RESOURCE LIMITS ────────────────────────────────────────────────────
# Prevent one container from starving other processes on the machine

docker run -d -p 8083:8083 \
    --memory="2g" \         # max 2 GB RAM
    --cpus="1.5" \          # max 1.5 CPU cores
    --name fraud-api \
    fraud-model:2.0


# ── AUTO-RESTART ───────────────────────────────────────────────────────
# Restart policy for production deployments

docker run -d -p 8083:8083 \
    --restart unless-stopped \    # restart on crash, but not if manually stopped
    --name fraud-api \
    fraud-model:2.0

# Other restart options:
# --restart no              → never restart (default)
# --restart always          → always restart (even after docker daemon restart)
# --restart on-failure:3    → restart up to 3 times on non-zero exit


# ── INTERACTIVE SHELL ──────────────────────────────────────────────────
# Open a shell INSIDE the container (great for debugging!)

docker run -it fraud-model:2.0 /bin/bash
# Now you're inside! Explore files, test Python imports, debug issues.
# Type 'exit' to leave.

# Run a quick one-off command and exit
docker run --rm fraud-model:2.0 python -c "import torch; print(torch.__version__)"
# --rm = automatically remove the container when it exits (keeps things tidy)
💡 The most important docker run flags to memorize:
-d = run in background (detached)
-p = map ports (host:container)
-e = set environment variable
--name = give it a friendly name
-v = mount a folder
--rm = auto-delete when done
-it = interactive terminal (for debugging)

10. docker ps — List Running Containers

Syntax: docker ps [OPTIONS]

What it does: Shows all currently running containers. Like the Activity Monitor on your laptop — it shows you what's alive and consuming resources right now.

# List only RUNNING containers
docker ps

# CONTAINER ID   IMAGE              COMMAND                STATUS         PORTS                    NAMES
# c4f8a2b3d9e1   fraud-model:2.0    "/app/entrypoint.sh"   Up 3 hours     0.0.0.0:8083->8083/tcp   fraud-api
# d5e7b3c1f8a2   redis:7.2-alpine   "docker-entrypoint…"   Up 3 hours     6379/tcp                 redis-cache


# List ALL containers (including stopped ones)
docker ps -a

# Show only container IDs (for scripting)
docker ps -q

# Show only IDs of ALL containers (including stopped)
docker ps -aq

# Filter by name
docker ps --filter "name=fraud-api"

# Filter by status
docker ps --filter "status=exited"    # show only stopped containers
docker ps --filter "status=running"   # show only running

# Custom format (cleaner output)
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

# Names           Status         Ports
# fraud-api       Up 3 hours     0.0.0.0:8083->8083/tcp
# redis-cache     Up 3 hours     6379/tcp

11. docker start & docker stop — Resume or Pause a Container

Syntax: docker start|stop [OPTIONS] CONTAINER [CONTAINER...]

What they do: stop gracefully shuts down a running container (sends SIGTERM signal, waits 10 seconds, then forces kill). start restarts a stopped container — like pressing pause and play on a video. The container state is preserved.

# Stop a container gracefully (waits up to 10 seconds for clean shutdown)
docker stop fraud-api

# Stop with custom wait timeout (useful for models that take time to shut down)
docker stop --time 30 fraud-api      # wait up to 30 seconds

# Force-kill immediately (no graceful shutdown — use only when stop hangs!)
docker kill fraud-api

# Restart a stopped container (keeps same config — ports, env vars, volumes)
docker start fraud-api

# Restart a RUNNING container (stop + start in one command)
docker restart fraud-api

# Stop multiple containers at once
docker stop fraud-api redis-cache postgres-db

# Stop ALL running containers
docker stop $(docker ps -q)
✅ Always prefer docker stop over docker kill. stop gives your ML API time to finish processing in-flight requests before shutting down. kill cuts the power immediately — requests get dropped and data can corrupt.

12. docker rm — Delete a Stopped Container

Syntax: docker rm [OPTIONS] CONTAINER [CONTAINER...]

What it does: Permanently removes a stopped container. Note: this does NOT delete the image. Like throwing away a used meal container — the recipe is still in your cookbook.

# Remove a stopped container
docker rm fraud-api

# Force-remove a RUNNING container (stop + remove in one command)
docker rm -f fraud-api

# Remove multiple containers
docker rm fraud-api redis-cache

# Remove ALL stopped containers (safe cleanup)
docker rm $(docker ps -aq -f status=exited)

# One-liner: stop and remove a running container
docker stop fraud-api && docker rm fraud-api

# Better: use --rm in docker run to auto-delete when it stops
docker run --rm fraud-model:2.0

13. docker exec — Run a Command Inside a Running Container

Syntax: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

What it does: Executes a command inside a container that is already running. Like teleporting into a car that's already driving — you can interact with everything inside without stopping or restarting it. This is the #1 debugging tool for ML container problems. 🔧

# Open an interactive bash shell INSIDE a running container
docker exec -it fraud-api bash
# You are now INSIDE the container!
# → ls /app               (see your files)
# → python                (test Python)
# → env | grep MODEL      (check env variables)
# → exit                  (leave the container)

# Run a single command and exit (non-interactive)
docker exec fraud-api ls /app/models

# Check Python version inside the container
docker exec fraud-api python --version

# Test if your model loads correctly
docker exec fraud-api python -c "
import joblib
model = joblib.load('/app/models/fraud_model.pkl')
print('Model type:', type(model))
print('Model loaded successfully ✅')
"

# Check environment variables inside the container
docker exec fraud-api env | grep -E "MODEL|ENVIRONMENT|OCI"

# Check disk usage inside the container
docker exec fraud-api df -h

# Run as a specific user (for permission debugging)
docker exec -u root -it fraud-api bash
✅ docker exec -it CONTAINER bash is your most powerful debugging command. When your ML model isn't behaving in production, SSH into the container and investigate directly. Check files, test imports, print environment variables — all without stopping the live service.

14. docker logs — View Container Output

Syntax: docker logs [OPTIONS] CONTAINER

What it does: Shows everything the container has printed to the terminal (stdout + stderr) since it started. Like reading the diary of your container — every print statement, every error, every API request logged. 📖

# Show ALL logs since container started
docker logs fraud-api

# Follow logs in real-time (like tail -f — most useful!)
docker logs -f fraud-api

# Show only the last 50 lines
docker logs --tail 50 fraud-api

# Follow AND show only last 50 lines (most common combo)
docker logs -f --tail 50 fraud-api

# Show logs with timestamps
docker logs --timestamps fraud-api

# Show logs since a specific time
docker logs --since "2025-03-10T10:00:00" fraud-api

# Show logs between two times
docker logs --since "1h" --until "30m" fraud-api   # between 1h and 30min ago

# Example output you'd see:
# 2025-03-10T10:23:01.123Z  INFO:     Loading model from /app/models/fraud_model.pkl
# 2025-03-10T10:23:04.456Z  INFO:     ✅ Model loaded in 3.3 seconds
# 2025-03-10T10:23:04.789Z  INFO:     Application startup complete
# 2025-03-10T10:23:05.012Z  INFO:     Uvicorn running on http://0.0.0.0:8083
# 2025-03-10T10:25:12.345Z  INFO:     POST /predict - user=12345 score=0.92 BLOCK 1.8ms

15. docker stats — Real-Time Resource Usage

Syntax: docker stats [OPTIONS] [CONTAINER...]

What it does: Shows a live dashboard of CPU, RAM, network, and disk usage for your running containers. Like the Activity Monitor — but for containers specifically.

# Live dashboard for ALL running containers (refreshes every second)
docker stats

# CONTAINER ID   NAME          CPU %    MEM USAGE / LIMIT    NET I/O          BLOCK I/O
# c4f8a2b3d9e1   fraud-api     12.3%    1.2GB / 4GB          45.2MB / 8.1MB   0B / 0B
# d5e7b3c1f8a2   redis-cache   0.1%     12.4MB / 512MB       1.2MB / 800kB    0B / 0B

# Monitor only specific containers
docker stats fraud-api redis-cache

# Single snapshot (no live update — useful for scripts)
docker stats --no-stream

# Custom format showing only what matters
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
💡 Watch MEM USAGE closely for ML models! If RAM usage keeps climbing and never drops, your model has a memory leak — likely loading the model inside the endpoint function instead of once at startup. Memory should stay constant once the model is loaded.

🔐 Group 3: Registry Commands

Registry commands control your connection to container registries like Oracle Container Registry (OCIR) — where your ML images live in the cloud.


16. docker login — Authenticate with a Registry

Syntax: docker login [OPTIONS] [SERVER]

What it does: Logs in to a container registry so you can push and pull images. Like logging into an app before you can download anything.

# Login to Oracle Container Registry (OCIR)
# Username format: tenancy-namespace/oci-username (or federated user email)
docker login ap-mumbai-1.ocir.io \
    --username "mytenancy/alice@company.com" \
    --password "OCI-Auth-Token-here"
# Login Succeeded ✅

# SECURE: Pass password via stdin (avoids it appearing in shell history!)
echo "$OCI_AUTH_TOKEN" | docker login ap-mumbai-1.ocir.io \
    --username "mytenancy/alice@company.com" \
    --password-stdin

# Login to Docker Hub (for pulling public base images)
docker login

# Login to a different OCI region registry
docker login eu-frankfurt-1.ocir.io \
    --username "mytenancy/alice@company.com" \
    --password-stdin
❌ Never type your OCI Auth Token directly in the command! It gets saved in your shell history (~/.bash_history) in plain text. Always use --password-stdin or environment variables: echo "$OCI_AUTH_TOKEN" | docker login ... --password-stdin

17. docker logout — Sign Out from a Registry

# Logout from OCIR (removes stored credentials from ~/.docker/config.json)
docker logout ap-mumbai-1.ocir.io

# Logout from Docker Hub
docker logout

18. docker search — Find Public Images

# Search Docker Hub for official Python images
docker search python

# Search for PyTorch images
docker search pytorch

# Filter to only official images
docker search --filter "is-official=true" python

# Show at most 5 results
docker search --limit 5 pytorch

🔧 Group 4: System Commands

System commands give you information about Docker itself and help you keep your machine clean and healthy.


19. docker version & docker info — System Information

# Show Docker version (Client + Server)
docker version

# Client: Docker Engine - Community
#  Version: 26.0.0
#  API version: 1.45
# Server: Docker Engine - Community
#  Version: 26.0.0

# Show detailed system info (storage, number of containers/images, etc.)
docker info

# Useful fields in docker info:
# Containers: 3 (Running: 2, Stopped: 1)
# Images: 8
# Docker Root Dir: /var/lib/docker
# Total Memory: 15.54 GiB
# CPUs: 8

20. docker system prune — The Master Cleanup Command

Syntax: docker system prune [OPTIONS]

What it does: Removes all stopped containers, unused networks, dangling images, and optionally unused volumes — in one sweep. Like running a full disk cleanup on your machine. 🧹

# Remove all stopped containers + dangling images + unused networks
# (asks for confirmation first)
docker system prune

# WARNING! This will remove:
#   3 stopped containers
#   2 networks not used by at least one container
#   1 dangling image
#   Total reclaimed space: 1.42 GB
# Are you sure you want to continue? [y/N] y

# Skip confirmation prompt (for CI/CD pipelines)
docker system prune -f

# NUCLEAR: Also remove ALL unused images (not just dangling ones)
# This frees MUCH more space but means re-downloading base images
docker system prune -a

# MOST NUCLEAR: Remove everything including volumes (CAREFUL — deletes data!)
docker system prune -a --volumes

# See what's taking up space before pruning
docker system df

# TYPE            TOTAL   ACTIVE   SIZE       RECLAIMABLE
# Images          8       2        4.521GB    3.108GB (68%)
# Containers      3       2        18.4MB     12.2MB (66%)
# Local Volumes   2       1        890.2MB    445.1MB (50%)
# Build Cache     15      0        2.1GB      2.1GB
✅ Run docker system df first to see exactly how much space you'll reclaim before committing to prune. Run docker system prune -a monthly on your dev machine to prevent Docker from eating your entire hard drive.

21. docker network — Manage Container Networking

# List all Docker networks
docker network ls

# NETWORK ID     NAME              DRIVER    SCOPE
# a1b2c3d4e5f6   bridge            bridge    local   ← default
# b2c3d4e5f6a7   host              host      local
# c3d4e5f6a7b8   ml-network        bridge    local   ← custom (from compose)

# Create a custom network (containers on same network can talk by name)
docker network create ml-network

# Inspect a network (see which containers are connected)
docker network inspect ml-network

# Connect a running container to a network
docker network connect ml-network fraud-api

# Disconnect from a network
docker network disconnect ml-network fraud-api

# Remove unused networks
docker network prune

22. docker volume — Manage Persistent Storage

# List all volumes
docker volume ls

# DRIVER    VOLUME NAME
# local     fraud_postgres-data
# local     fraud_redis-data

# Create a named volume
docker volume create ml-model-storage

# Inspect a volume (see where data is stored on disk)
docker volume inspect ml-model-storage

# Use a named volume in docker run
docker run -d -p 8083:8083 \
    -v ml-model-storage:/app/models \
    fraud-model:2.0

# Remove a specific volume (WARNING: permanent data loss!)
docker volume rm ml-model-storage

# Remove all unused volumes
docker volume prune

🐙 Group 5: Docker Compose Commands

Docker Compose manages multi-container applications defined in a docker-compose.yaml file. Instead of running 4 separate docker run commands, you use one Compose command to orchestrate everything.


23. Core Compose Commands

# ── START ──────────────────────────────────────────────────────────────

# Start all services in background (builds images if they don't exist)
docker compose up -d

# Start and force rebuild ALL images (even if they haven't changed)
docker compose up -d --build

# Start only specific services
docker compose up -d fraud-api redis-cache

# ── STOP ───────────────────────────────────────────────────────────────

# Stop all services (keeps containers and volumes — fast restart)
docker compose stop

# Stop AND remove containers + networks (clean slate — volumes preserved)
docker compose down

# Stop AND remove containers + networks + volumes (CAREFUL: deletes data!)
docker compose down -v

# ── MONITORING ─────────────────────────────────────────────────────────

# Check status of all services
docker compose ps

# NAME           SERVICE      STATUS    PORTS
# fraud-api      fraud-api    running   0.0.0.0:8083->8083/tcp
# redis-cache    redis-cache  running   6379/tcp
# postgres-db    postgres-db  running   5432/tcp

# Follow logs from ALL services
docker compose logs -f

# Follow logs from one service only
docker compose logs -f fraud-api

# Show last 100 lines from all services
docker compose logs --tail 100

# ── SCALING ────────────────────────────────────────────────────────────

# Scale the API to 3 instances (load testing!)
docker compose up -d --scale fraud-api=3

# ── MAINTENANCE ────────────────────────────────────────────────────────

# Execute a command inside a Compose service container
docker compose exec fraud-api bash
docker compose exec fraud-api python -c "import sklearn; print(sklearn.__version__)"

# Restart one service without affecting others
docker compose restart fraud-api

# Pull latest images for all services (for updates)
docker compose pull

# See resource usage for all compose services
docker compose top

🔄 Real MLOps Workflows — Chained Command Sequences

In production, Docker commands are always chained together. Here are the exact sequences you'll use every day as an MLOps engineer.

Workflow 1: Build & Deploy a New Model Version to OCI

#!/bin/bash
# deploy_to_oci.sh — Full build → push → deploy sequence

set -e  # Exit on any error

MODEL_VERSION="2.1.0"
OCI_REGION="ap-mumbai-1"
TENANCY="mytenancy"
OCIR_IMAGE="${OCI_REGION}.ocir.io/${TENANCY}/fraud-model:${MODEL_VERSION}"

echo "🏗️  Step 1: Build Docker image..."
docker build \
    -t fraud-model:${MODEL_VERSION} \
    --build-arg environment=production \
    .

echo "📊 Step 2: Check image size..."
docker images fraud-model:${MODEL_VERSION}

echo "🔐 Step 3: Login to OCIR..."
echo "$OCI_AUTH_TOKEN" | docker login ${OCI_REGION}.ocir.io \
    --username "${TENANCY}/${OCI_USERNAME}" \
    --password-stdin

echo "🏷️  Step 4: Tag with OCIR path..."
docker tag fraud-model:${MODEL_VERSION} ${OCIR_IMAGE}

echo "📤 Step 5: Push to OCIR..."
docker push ${OCIR_IMAGE}

echo "🔄 Step 6: Pull and restart on OCI Compute..."
ssh opc@${OCI_INSTANCE_IP} "
    docker pull ${OCIR_IMAGE} &&
    docker stop fraud-api || true &&
    docker rm fraud-api || true &&
    docker run -d \
        --name fraud-api \
        --restart unless-stopped \
        -p 8083:8083 \
        --env-file /home/opc/.env.production \
        ${OCIR_IMAGE}
"

echo "✅ Deployment complete! Testing health endpoint..."
sleep 5
curl -f http://${OCI_INSTANCE_IP}:8083/health

echo "🎉 Fraud model v${MODEL_VERSION} deployed successfully!"

Workflow 2: Debug a Broken Container

# Container is crashing — investigate!

# Step 1: Check if it's running (or if it crashed)
docker ps -a | grep fraud-api

# Step 2: Read the logs to find the error
docker logs --tail 100 fraud-api

# Step 3: Check resource usage (is it out of memory?)
docker stats --no-stream fraud-api

# Step 4: Try to run it interactively to reproduce the issue
docker run -it \
    -e ENVIRONMENT=production \
    --env-file .env.production \
    fraud-model:2.0 bash
    # Inside container: try to manually start the app
    # → python src/api/main.py
    # → check error messages directly

# Step 5: Inspect the container's environment variables
docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' fraud-api

# Step 6: Check if model file exists inside the container
docker exec fraud-api ls -lh /app/models/

# Step 7: Test model loading directly
docker exec fraud-api python -c "
import joblib
try:
    m = joblib.load('/app/models/fraud_model.pkl')
    print('✅ Model loaded OK:', type(m))
except Exception as e:
    print('❌ Model load failed:', e)
"

Workflow 3: Monthly Cleanup Routine

# Run this monthly to keep your machine healthy

echo "📊 Current Docker disk usage:"
docker system df

echo ""
echo "🔍 Stopped containers to remove:"
docker ps -a --filter status=exited --format "table {{.Names}}\t{{.Status}}"

echo ""
echo "🗑️  Removing stopped containers..."
docker container prune -f

echo ""
echo "🖼️  Removing dangling images (untagged)..."
docker image prune -f

echo ""
echo "🌐 Removing unused networks..."
docker network prune -f

echo ""
echo "📊 Docker disk usage AFTER cleanup:"
docker system df

echo ""
echo "✅ Cleanup complete!"

📌 The Ultimate Docker Commands Quick Reference Card

Command What It Does Most Used Flag
docker build -t name:tag . Build image from Dockerfile --no-cache
docker images List all local images -a
docker pull image:tag Download image from registry —
docker push image:tag Upload image to registry —
docker tag src dst Alias/rename an image —
docker rmi image:tag Delete a local image -f
docker history image Show image layers + sizes --no-trunc
docker inspect name Full JSON metadata --format
docker run -d -p 8083:8083 Create & start container --name --env-file
docker ps List running containers -a
docker stop name Graceful shutdown --time 30
docker start name Resume stopped container —
docker restart name Stop + start —
docker rm name Delete stopped container -f
docker exec -it name bash Shell inside container -it
docker logs -f name Stream live logs --tail 50
docker stats name Live CPU/RAM usage --no-stream
docker login registry Authenticate with registry --password-stdin
docker system df Show disk usage —
docker system prune -a Clean up everything unused -f
docker compose up -d Start all Compose services --build
docker compose down Stop & remove Compose services -v

✅ Best Practices & Common Mistakes

✅ DOs:
  • ✅ Always use --name in docker run — IDs are hard to remember
  • ✅ Use --env-file instead of multiple -e flags for cleaner commands
  • ✅ Use --password-stdin for docker login — keeps credentials out of shell history
  • ✅ Use --restart unless-stopped for production ML APIs
  • ✅ Run docker system df monthly and docker system prune -a to reclaim space
  • ✅ Always tag images with a version AND a git hash for full traceability
  • ✅ Use docker exec -it container bash as your first debugging step
  • ✅ Use docker logs -f --tail 50 to follow live logs during deployment
❌ DON'Ts:
  • ❌ Never use :latest tags in production — always pin exact versions
  • ❌ Never type credentials directly in docker login — use stdin or env vars
  • ❌ Never use docker kill on production — use docker stop for graceful shutdown
  • ❌ Don't forget to docker rm after docker stop — stopped containers still consume disk
  • ❌ Don't run docker system prune -a --volumes on a production server — it deletes database data!
  • ❌ Don't use --no-cache in every build — it defeats the entire point of layer caching

🏆 High Level Summary

  • 🔹 Build: docker build -t name:tag . — create image from Dockerfile
  • 🔹 List: docker images — see what's on your machine
  • 🔹 Ship: docker tag + docker push — send to OCIR
  • 🔹 Run: docker run -d -p 8083:8083 --name api image:tag — launch
  • 🔹 Monitor: docker ps, docker logs -f, docker stats — watch it live
  • 🔹 Debug: docker exec -it container bash — go inside and investigate
  • 🔹 Stop: docker stop → docker rm — graceful shutdown + cleanup
  • 🔹 Clean: docker system prune -a — reclaim disk space monthly
  • 🔹 Compose: docker compose up -d — run full ML systems with one command
🎉 You now know every Docker command an MLOps engineer uses daily!

Open a terminal right now. Type docker images. Then docker ps. Then try docker system df. The best way to remember commands is to use them — not just read them.

Practice the build → run → logs → exec → stop → rm cycle once today and it will feel natural forever. 🐳✨

Keep shipping, keep debugging, keep learning Docker! 🐼✨

Comments