Skip to main content

Introduction

Docker allows you to package your ML applications with all dependencies into portable containers. This ensures consistency across development, testing, and production environments.
Containers are lightweight, isolated environments that share the host OS kernel, making them more efficient than virtual machines.

Getting Started

Hello World

Test your Docker installation by running the official hello-world image:
docker pull hello-world
docker run hello-world
This confirms Docker is properly configured on your system.

Building ML Containers

Module 1 includes two sample applications that demonstrate different containerization patterns.

ML Training Application

The app-ml container simulates a machine learning training job:
FROM python:3.12
CMD python -c "import time; time.sleep(5); print(f'AUC = {0.9999}')"
Build the image:
docker build --tag app-ml:latest ./app-ml
Run the container:
docker run -it --rm --name app-ml-test-run app-ml:latest
Run with custom command:
docker run -it --rm --name app-ml-test-run app-ml:latest \
  python -c "import time; time.sleep(5); print(f'AUC = {0.0001}')"
The -it flag provides an interactive terminal, --rm automatically removes the container after exit, and --name assigns a friendly identifier.

Web Application

The app-web container runs a simple HTTP server for serving models:
FROM python:3.12
CMD python -m http.server 8080
Build the image:
docker build --tag app-web:latest ./app-web
Run with port mapping:
docker run -it --rm -p 8080:8080 --name app-web-test-run app-web:latest
Test the endpoint: In a separate terminal, verify the server is running:
curl http://0.0.0.0:8080/
The -p 8080:8080 flag maps port 8080 from the container to your host machine. Without this, the service won’t be accessible externally.

Multi-Stage Builds

For projects with multiple applications, use multi-stage Dockerfiles to share common dependencies:
# Base layer with all dependencies
FROM python:3.12 as base

WORKDIR /app

RUN pip install --upgrade pip


# Take models and create deployment
FROM base AS app-web
CMD python -m http.server 8080


# Take models and create training
FROM base AS app-ml
CMD python -c "import time; time.sleep(5); print(f'AUC = {0.9999}')"
Build specific targets:
docker build --tag app-web:latest --target app-web ./app-multi-build

Benefits of Multi-Stage Builds

  • Shared dependencies: Install common packages once in the base layer
  • Smaller images: Only include what’s needed for each target
  • Single source: Maintain one Dockerfile for multiple applications
  • Consistent environments: Ensure all apps use identical base configurations

Sharing Images

To deploy containers to production, push them to a container registry.

GitHub Container Registry

1

Authenticate

Set up credentials for GitHub Container Registry (ghcr.io):
export GITHUB_TOKEN=your_token_here
export GITHUB_USER=your_username
echo $GITHUB_TOKEN | docker login ghcr.io -u $GITHUB_USER --password-stdin
2

Tag Images

Tag your images with the registry URL:
docker tag app-ml:latest ghcr.io/your-username/app-ml:latest
docker tag app-web:latest ghcr.io/your-username/app-web:latest
3

Push to Registry

Upload images to the registry:
docker push ghcr.io/your-username/app-ml:latest
docker push ghcr.io/your-username/app-web:latest
GitHub Container Registry (ghcr.io) provides free storage for public images and is tightly integrated with GitHub Actions for automated CI/CD workflows.

Container Registry Options

Choose a registry that fits your infrastructure and requirements:
RegistryBest ForNotes
GitHub Container RegistryGitHub users, CI/CD integrationFree for public images
Docker HubPublic images, community sharingMost popular registry
Amazon ECRAWS deploymentsIntegrates with ECS/EKS
Google Container RegistryGCP deploymentsIntegrates with GKE

Best Practices

Image Optimization

  1. Use specific base images: python:3.12-slim instead of python:3.12 for smaller images
  2. Leverage build cache: Order Dockerfile commands from least to most frequently changing
  3. Multi-stage builds: Separate build and runtime dependencies
  4. Minimize layers: Combine RUN commands with &&

Security

Never hardcode secrets in Dockerfiles. Use environment variables or secret management tools like Docker secrets or Kubernetes secrets.
  • Scan images for vulnerabilities with docker scan
  • Use official base images from trusted sources
  • Run containers as non-root users when possible
  • Keep base images updated

Development Workflow

# Build
docker build -t my-app:dev .

# Test locally
docker run --rm my-app:dev pytest

# Tag for production
docker tag my-app:dev my-app:v1.0.0

# Push to registry
docker push my-app:v1.0.0

Debugging Containers

Inspecting Running Containers

# List running containers
docker ps

# View logs
docker logs container-name

# Execute commands in running container
docker exec -it container-name bash

# Inspect container details
docker inspect container-name

Common Issues

# Find process using port 8080
lsof -i :8080

# Use a different host port
docker run -p 8081:8080 app-web:latest

Resources

Essential Reading

Documentation

Next Steps

Now that you understand containerization, learn how to orchestrate these containers at scale with Kubernetes.

Build docs developers (and LLMs) love