Tutorial Docker untuk Data Science & ML: Containerisasi Model

# Tutorial 15: Docker untuk Data Science dan Machine Learning ## Daftar Isi 1. [Pendahuluan](#pendahuluan) 2. [Prasyarat](#prasyarat) 3. [Dasar-Dasar Docker untuk Insinyur ML](#dasar-dasar-docker-un...

By Ruby Abdullah · · tutorial
DockerData ScienceMLContainerizationGPUDocker Compose

Tutorial 15: Docker untuk Data Science dan Machine Learning

Daftar Isi

  • Pendahuluan
  • Prasyarat
  • Dasar-Dasar Docker untuk Insinyur ML
  • Menulis Dockerfile untuk Proyek ML
  • Multi-Stage Build untuk Image yang Dioptimasi
  • Dukungan GPU dengan NVIDIA Docker
  • Docker Compose untuk Stack ML
  • Volume Mount untuk Data dan Model
  • Manajemen Environment dan Dependensi
  • Integrasi CI/CD
  • Praktik Terbaik
  • Kesimpulan

  • Pendahuluan

    Reprodusibilitas adalah salah satu tantangan terbesar dalam data science dan machine learning. Masalah terkenal "berjalan di mesin saya" semakin diperparah ketika proyek bergantung pada versi spesifik Python, CUDA, cuDNN, library sistem, dan puluhan paket Python. Model yang berlatih dengan sempurna di laptop Anda mungkin gagal total di workstation rekan kerja atau di lingkungan cloud.

    Docker menyelesaikan masalah ini dengan mengemas kode, dependensi, dan lingkungan runtime Anda ke dalam unit portabel dan mandiri yang disebut container. Dengan Docker, Anda dapat menjamin bahwa pipeline ML Anda berjalan identik di mana saja — dari pengembangan lokal hingga CI/CD hingga penyajian produksi.

    Tutorial ini mencakup semua yang Anda butuhkan untuk mengontainerisasi alur kerja ML: menulis Dockerfile yang efisien, memanfaatkan multi-stage build, mengaktifkan akselerasi GPU, mengorkestrasi stack multi-layanan dengan Docker Compose, dan mengintegrasikan container ke dalam pipeline CI/CD.


    Prasyarat

    • Docker Engine 24.0 atau lebih baru sudah terinstal
    • Docker Compose v2 sudah terinstal
    • Familiar dengan baris perintah Linux
    • Python 3.9+ dan pip
    • (Opsional) GPU NVIDIA dengan driver terinstal untuk bagian GPU

    # Verifikasi instalasi Docker
    

    docker --version

    docker compose version


    Dasar-Dasar Docker untuk Insinyur ML

    Konsep Utama

    Images adalah template read-only yang mendefinisikan lingkungan. Mereka dibangun dari Dockerfile dan disimpan di registry (Docker Hub, AWS ECR, GCP Artifact Registry). Containers adalah instance yang berjalan dari image. Mereka adalah proses terisolasi dan sementara dengan filesystem, jaringan, dan ruang proses sendiri. Layers adalah blok bangunan dari image. Setiap instruksi di Dockerfile membuat layer baru. Docker meng-cache layer, sehingga layer yang tidak berubah digunakan kembali saat rebuild — ini sangat penting untuk iterasi cepat. Registries menyimpan dan mendistribusikan image Docker. Registry publik termasuk Docker Hub, sementara registry privat digunakan untuk model ML dan kode proprietary.

    Mengapa Docker Penting untuk ML

    | Tantangan | Solusi Docker |

    |-----------|--------------|

    | Konflik dependensi | Lingkungan terisolasi per proyek |

    | Ketidakcocokan versi Python | Tentukan versi Python eksak di image |

    | Kompatibilitas CUDA/cuDNN | Gunakan image dasar NVIDIA dengan versi yang cocok |

    | Pelatihan yang dapat direproduksi | Image yang sama menghasilkan hasil yang sama di mana saja |

    | Konsistensi deployment | Dev, staging, dan produksi menggunakan image yang sama |


    Dockerfile ML Dasar

    # Gunakan runtime Python resmi sebagai image dasar
    

    FROM python:3.11-slim

    Atur variabel lingkungan

    ENV PYTHONDONTWRITEBYTECODE=1 \

    PYTHONUNBUFFERED=1 \

    PIPNOCACHEDIR=1 \

    PIPDISABLEPIPVERSIONCHECK=1

    Atur direktori kerja

    WORKDIR /app

    Instal dependensi sistem (umum untuk library ML)

    RUN apt-get update && apt-get install -y --no-install-recommends \

    build-essential \

    libgomp1 \

    libglib2.0-0 \

    libsm6 \

    libxext6 \

    libxrender-dev \

    libgl1-mesa-glx \

    curl \

    && rm -rf /var/lib/apt/lists/

    Salin dan instal dependensi Python terlebih dahulu (untuk caching layer)

    COPY requirements.txt .

    RUN pip install --no-cache-dir -r requirements.txt

    Salin kode aplikasi

    COPY . .

    Ekspos port untuk API

    EXPOSE 8000

    Perintah default

    CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]

    File Requirements untuk Proyek ML

    # requirements.txt
    

    numpy==1.26.4

    pandas==2.2.0

    scikit-learn==1.4.0

    xgboost==2.0.3

    lightgbm==4.2.0

    fastapi==0.109.0

    uvicorn==0.27.0

    pydantic==2.5.3

    joblib==1.3.2

    mlflow==2.10.0

    Build dan Jalankan

    # Build image
    

    docker build -t ml-inference-api:v1.0 .

    Jalankan container

    docker run -d \

    --name ml-api \

    -p 8000:8000 \

    -v $(pwd)/models:/app/models \

    ml-inference-api:v1.0

    Cek log

    docker logs ml-api

    Tes API

    curl http://localhost:8000/health


    Multi-Stage Build untuk Image yang Dioptimasi

    Multi-stage build memungkinkan Anda memisahkan lingkungan build dari lingkungan runtime, menghasilkan image produksi yang jauh lebih kecil.

    # ============================================
    

    Tahap 1: Builder - instal dependensi

    ============================================

    FROM python:3.11-slim AS builder

    WORKDIR /build

    Instal dependensi build

    RUN apt-get update && apt-get install -y --no-install-recommends \

    build-essential \

    gcc \

    g++ \

    gfortran \

    libopenblas-dev \

    && rm -rf /var/lib/apt/lists/

    Buat virtual environment

    RUN python -m venv /opt/venv

    ENV PATH="/opt/venv/bin:$PATH"

    Instal dependensi Python

    COPY requirements.txt .

    RUN pip install --no-cache-dir -r requirements.txt

    ============================================

    Tahap 2: Pelatihan - jalankan pelatihan model

    ============================================

    FROM builder AS trainer

    WORKDIR /train

    COPY . .

    RUN python train.py --output /train/models/model.pkl

    ============================================

    Tahap 3: Produksi - image runtime minimal

    ============================================

    FROM python:3.11-slim AS production

    Instal hanya dependensi sistem runtime

    RUN apt-get update && apt-get install -y --no-install-recommends \

    libgomp1 \

    libglib2.0-0 \

    curl \

    && rm -rf /var/lib/apt/lists/

    Salin virtual environment dari builder

    COPY --from=builder /opt/venv /opt/venv

    ENV PATH="/opt/venv/bin:$PATH"

    Salin kode aplikasi

    WORKDIR /app

    COPY app.py .

    COPY utils/ ./utils/

    Salin model terlatih dari tahap trainer

    COPY --from=trainer /train/models/model.pkl ./models/model.pkl

    Buat pengguna non-root untuk keamanan

    RUN useradd --create-home --shell /bin/bash mluser

    USER mluser

    Health check

    HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \

    CMD curl -f http://localhost:8000/health || exit 1

    EXPOSE 8000

    CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]

    Perbandingan ukuran image:

    # Build single-stage (biasanya 2-3 GB untuk ML)
    

    docker images ml-api-single

    Build multi-stage (biasanya 500 MB - 1 GB)

    docker images ml-api-multi


    Dukungan GPU dengan NVIDIA Docker

    Menyiapkan NVIDIA Container Toolkit

    # Instal NVIDIA Container Toolkit
    

    distribution=$(. /etc/os-release; echo $ID$VERSIONID)

    curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \

    sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg

    curl -s -L "https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list" | \

    sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \

    sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

    sudo apt-get update

    sudo apt-get install -y nvidia-container-toolkit

    sudo nvidia-ctk runtime configure --runtime=docker

    sudo systemctl restart docker

    Verifikasi akses GPU di dalam container

    docker run --rm --gpus all nvidia/cuda:12.3.1-base-ubuntu22.04 nvidia-smi

    Dockerfile ML dengan GPU

    # Gunakan image dasar NVIDIA CUDA
    

    FROM nvidia/cuda:12.3.1-cudnn9-runtime-ubuntu22.04

    Atur variabel lingkungan

    ENV DEBIANFRONTEND=noninteractive \

    PYTHONDONTWRITEBYTECODE=1 \

    PYTHONUNBUFFERED=1

    Instal Python dan dependensi sistem

    RUN apt-get update && apt-get install -y --no-install-recommends \

    python3.11 \

    python3.11-venv \

    python3-pip \

    && ln -sf /usr/bin/python3.11 /usr/bin/python \

    && rm -rf /var/lib/apt/lists/

    WORKDIR /app

    Instal PyTorch dengan dukungan CUDA

    RUN pip install --no-cache-dir \

    torch==2.2.0 \

    torchvision==0.17.0 \

    --index-url https://download.pytorch.org/whl/cu121

    Instal dependensi ML lainnya

    COPY requirements-gpu.txt .

    RUN pip install --no-cache-dir -r requirements-gpu.txt

    COPY . .

    CMD ["python", "traingpu.py"]

    Menjalankan dengan Akses GPU

    # Jalankan dengan semua GPU
    

    docker run --gpus all -v $(pwd)/data:/app/data ml-gpu-training:v1.0

    Jalankan dengan GPU spesifik

    docker run --gpus '"device=0,1"' ml-gpu-training:v1.0

    Jalankan dengan shared memory yang lebih besar (penting untuk DataLoader PyTorch)

    docker run --gpus all --shm-size=8g ml-gpu-training:v1.0


    Docker Compose untuk Stack ML

    Sistem ML tipikal melibatkan beberapa layanan. Docker Compose mengorkestrasinya bersama-sama.

    version: '3.8'
    
    

    services:

    # Layanan API ML

    ml-api:

    build:

    context: .

    dockerfile: Dockerfile

    target: production

    ports:

    • "8000:8000"
    volumes:

    • model-store:/app/models
    • ./logs:/app/logs
    environment:

    • MODELPATH=/app/models/model.pkl
    • LOGLEVEL=INFO
    • REDISURL=redis://redis:6379/0
    • DBURL=postgresql://mluser:mlpass@postgres:5432/mldb
    dependson:

    redis:

    condition: servicehealthy

    postgres:

    condition: servicehealthy

    deploy:

    resources:

    limits:

    cpus: '4.0'

    memory: 8G

    restart: unless-stopped

    # Redis untuk caching dan feature store

    redis:

    image: redis:7-alpine

    ports:

    • "6379:6379"
    volumes:

    • redis-data:/data
    command: redis-server --maxmemory 2gb --maxmemory-policy allkeys-lru

    healthcheck:

    test: ["CMD", "redis-cli", "ping"]

    interval: 10s

    timeout: 5s

    retries: 3

    # PostgreSQL untuk prediksi dan metadata

    postgres:

    image: postgres:16-alpine

    environment:

    POSTGRESUSER: mluser

    POSTGRESPASSWORD: mlpass

    POSTGRESDB: mldb

    ports:

    • "5432:5432"
    volumes:

    • postgres-data:/var/lib/postgresql/data
    healthcheck:

    test: ["CMD-SHELL", "pgisready -U mluser -d mldb"]

    interval: 10s

    timeout: 5s

    retries: 5

    # MLflow untuk pelacakan eksperimen

    mlflow:

    image: ghcr.io/mlflow/mlflow:v2.10.0

    ports:

    • "5000:5000"
    volumes:

    • mlflow-data:/mlflow
    command: >

    mlflow server

    --backend-store-uri sqlite:///mlflow/mlflow.db

    --default-artifact-root /mlflow/artifacts

    --host 0.0.0.0

    --port 5000

    # Jupyter Notebook untuk eksperimentasi

    jupyter:

    build:

    context: .

    dockerfile: Dockerfile.jupyter

    ports:

    • "8888:8888"
    volumes:

    • ./notebooks:/app/notebooks
    • ./data:/app/data
    • model-store:/app/models
    environment:

    • JUPYTERTOKEN=mlsecret123

    # Grafana untuk dashboard

    grafana:

    image: grafana/grafana:10.2.0

    ports:

    • "3000:3000"
    volumes:

    • grafana-data:/var/lib/grafana
    environment:

    • GFSECURITYADMINPASSWORD=admin123

    volumes:

    model-store:

    redis-data:

    postgres-data:

    mlflow-data:

    grafana-data:

    Menjalankan Stack

    # Mulai semua layanan
    

    docker compose up -d

    Cek status

    docker compose ps

    Lihat log untuk layanan tertentu

    docker compose logs -f ml-api

    Skalakan layanan API

    docker compose up -d --scale ml-api=3

    Hentikan semua

    docker compose down

    Hentikan dan hapus semua data

    docker compose down -v


    Volume Mount untuk Data dan Model

    Manajemen volume yang tepat sangat penting untuk alur kerja ML di mana data dan model harus bertahan di antara restart container.

    Jenis-Jenis Mount

    # Bind mount: petakan direktori host ke path container
    

    Terbaik untuk: pengembangan, kode sumber, dataset

    docker run -v /host/data:/container/data ml-training

    Named volume: penyimpanan persisten yang dikelola Docker

    Terbaik untuk: database, artefak model, cache

    docker volume create model-store

    docker run -v model-store:/app/models ml-api

    tmpfs mount: filesystem di memori

    Terbaik untuk: data sensitif, cache sementara

    docker run --tmpfs /tmp:rw,size=2g ml-training

    Praktik Terbaik untuk Data ML

    # app.py - Menangani pemuatan model dari volume yang di-mount
    

    import os

    import joblib

    from pathlib import Path

    DIREKTORIMODEL = Path(os.getenv('MODELDIR', '/app/models'))

    DIREKTORIDATA = Path(os.getenv('DATADIR', '/app/data'))

    def muatmodelterbaru():

    """Memuat file model yang paling baru dimodifikasi."""

    filemodel = sorted(

    DIREKTORIMODEL.glob('.pkl'),

    key=lambda p: p.stat().stmtime,

    reverse=True

    )

    if not filemodel:

    raise FileNotFoundError(f"Tidak ada file model ditemukan di {DIREKTORIMODEL}")

    pathmodel = filemodel[0]

    print(f"Memuat model: {pathmodel}")

    return joblib.load(pathmodel)

    def simpanmodel(model, versi):

    """Menyimpan model dengan nama file berversi."""

    DIREKTORIMODEL.mkdir(parents=True, existok=True)

    path = DIREKTORIMODEL / f"modelv{versi}.pkl"

    joblib.dump(model, path)

    print(f"Model disimpan ke {path}")

    return path


    Manajemen Environment dan Dependensi

    Menggunakan File .env

    # .env
    

    MODELVERSION=v2.1.0

    MODELPATH=/app/models/modelv2.1.0.pkl

    LOGLEVEL=INFO

    REDISURL=redis://redis:6379/0

    APIWORKERS=4

    MAXBATCHSIZE=64

    Mengelola Beberapa Environment

    # docker-compose.override.yml (otomatis dimuat, untuk pengembangan)
    

    version: '3.8'

    services:

    ml-api:

    build:

    target: builder # Gunakan tahap pengembangan

    volumes:

    • ./src:/app/src # Hot reload kode sumber
    environment:

    • DEBUG=1
    • LOGLEVEL=DEBUG
    command: uvicorn app:app --host 0.0.0.0 --reload

    # Pengembangan (menggunakan docker-compose.yml + docker-compose.override.yml)
    

    docker compose up

    Produksi

    docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d


    Integrasi CI/CD

    Pipeline GitHub Actions

    # .github/workflows/ml-pipeline.yml
    

    name: ML Pipeline CI/CD

    on:

    push:

    branches: [main]

    pullrequest:

    branches: [main]

    jobs:

    test:

    runs-on: ubuntu-latest

    steps:

    • uses: actions/checkout@v4
    • name: Build image pengujian
    run: docker build --target builder -t ml-test .

    • name: Jalankan unit test
    run: |

    docker run --rm ml-test pytest tests/ -v --cov=src --cov-report=xml

    • name: Jalankan validasi model
    run: |

    docker run --rm \

    -v ${{ github.workspace }}/data:/app/data \

    ml-test python validatemodel.py

    build-and-push:

    needs: test

    runs-on: ubuntu-latest

    if: github.ref == 'refs/heads/main'

    steps:

    • uses: actions/checkout@v4
    • name: Login ke Container Registry
    uses: docker/login-action@v3

    with:

    registry: ghcr.io

    username: ${{ github.actor }}

    password: ${{ secrets.GITHUBTOKEN }}

    • name: Build dan push image produksi
    uses: docker/build-push-action@v5

    with:

    context: .

    target: production

    push: true

    tags: |

    ghcr.io/${{ github.repository }}:latest

    ghcr.io/${{ github.repository }}:${{ github.sha }}

    cache-from: type=gha

    cache-to: type=gha,mode=max


    Praktik Terbaik

    1. Urutkan Instruksi Dockerfile Berdasarkan Frekuensi Perubahan

    Tempatkan instruksi yang paling jarang berubah di atas untuk memaksimalkan caching layer:

    # Jarang berubah - di-cache
    

    FROM python:3.11-slim

    RUN apt-get update && apt-get install -y libgomp1

    Berubah kadang-kadang - rebuild dari sini saat dependensi berubah

    COPY requirements.txt .

    RUN pip install -r requirements.txt

    Sering berubah - hanya layer ini yang di-rebuild

    COPY src/ ./src/

    2. Gunakan .dockerignore

    # .dockerignore
    

    .git

    .github

    pycache

    .pyc

    .env

    .venv

    data/raw/

    *.egg-info

    .pytestcache

    notebooks/

    3. Pin Semua Versi Dependensi

    Selalu gunakan versi eksak untuk memastikan reprodusibilitas penuh.

    4. Gunakan Pengguna Non-Root

    RUN useradd --create-home --shell /bin/bash --uid 1000 mluser
    

    USER mluser

    5. Implementasikan Health Check

    HEALTHCHECK --interval=30s --timeout=10s --start-period=15s --retries=3 \
    

    CMD python -c "import requests; requests.get('http://localhost:8000/health').raiseforstatus()"

    6. Jaga Image Tetap Kecil

    • Gunakan image dasar slim atau alpine jika memungkinkan.
    • Gabungkan perintah RUN untuk mengurangi layer.
    • Hapus tools build setelah kompilasi.
    • Gunakan --no-cache-dir dengan pip.
    • Manfaatkan multi-stage build untuk mengecualikan dependensi build-only.


    Kesimpulan

    Docker mengubah cara data scientist dan insinyur ML membangun, berbagi, dan men-deploy pekerjaan mereka. Dalam tutorial ini, Anda telah mempelajari cara:

    • Menulis Dockerfile yang efisien yang disesuaikan untuk proyek ML dengan caching layer yang tepat
    • Menggunakan multi-stage build untuk membuat image produksi yang ramping
    • Mengaktifkan akselerasi GPU dengan NVIDIA Container Toolkit
    • Mengorkestrasi stack ML lengkap menggunakan Docker Compose dengan API, database, cache, monitoring, dan pelacakan eksperimen
    • Mengelola data dan model dengan volume dan bind mount
    • Menangani beberapa environment (pengembangan, staging, produksi)
    • Mengintegrasikan Docker ke dalam pipeline CI/CD untuk pengujian dan deployment otomatis

    Dengan mengontainerisasi alur kerja ML Anda, Anda menghilangkan masalah reprodusibilitas, mempercepat onboarding, dan menciptakan jalur yang jelas dari eksperimentasi ke produksi. Mulailah dengan Dockerfile sederhana, iterasi seiring proyek Anda berkembang, dan investasikan pada Docker Compose ketika sistem Anda melibatkan beberapa layanan.

    Artikel Terkait

    Tutorial Lengkap NVIDIA NIM: Deploy Model AI dengan Performa Maksimal

    Tutorial Lengkap NVIDIA NIM (NVIDIA Inference Microservices) untuk Developer Indonesia Penulis: Ruby Abdullah Tanggal: 2...

    RAGFlow: Bikin RAG Engine yang Ngerti Dokumen Beneran, Lengkap dengan Sitasi

    RAGFlow: Bikin RAG Engine yang Ngerti Dokumen Beneran, Lengkap dengan Sitasi Halo temen-temen, balik lagi sama aku. Kala...

    Tutorial SkyPilot: Menjalankan Workload ML di Cloud Mana Saja

    SkyPilot: Menjalankan Beban Kerja ML dan AI di Cloud Apa Pun Melatih dan menyajikan model machine learning sering kali b...

    Tutorial Marimo: Notebook Python Reaktif dan Reproducible

    Marimo: Notebook Python yang Reaktif dan Reproducible Marimo adalah notebook Python yang menyimpan isinya sebagai berkas...