Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 50 additions & 15 deletions .devcontainer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ This directory contains the optimized dev container configuration for the Azure

## 🎯 Overview

This repository provides three prebuilt dev container configurations, one for each current Python version: 3.12, 3.13, and 3.14. When creating a new Codespace, select the variant you prefer — all variants are functionally equivalent for this project and differ only by Python runtime version.

The dev container uses a **three-stage optimization approach** to minimize startup time:

1. **Build Stage** (Dockerfile): Base system setup, Azure CLI configuration, and VS Code extension pre-installation
Expand All @@ -29,36 +31,60 @@ This approach ensures that time-consuming operations happen during container pre

| File | Purpose | Stage |
|------|---------|-------|
| `devcontainer.json` | Main dev container configuration | All |
| `Dockerfile` | Container image definition | Build |
| `post-start-setup.sh` | Runtime verification script | Runtime |
| `python312/devcontainer.json` | Dev container configuration (Python 3.12) | All |
| `python312/Dockerfile` | Container image definition (Python 3.12) | Build |
| `python313/devcontainer.json` | Dev container configuration (Python 3.13) | All |
| `python313/Dockerfile` | Container image definition (Python 3.13) | Build |
| `python314/devcontainer.json` | Dev container configuration (Python 3.14) | All |
| `python314/Dockerfile` | Container image definition (Python 3.14) | Build |
| `post-start-setup.sh` | Shared runtime verification script | Runtime |
| `README.md` | This documentation | - |

### Configuration Details

#### `devcontainer.json`
#### `devcontainer.json` (per Python version folder)
- **Features**: Azure CLI, common utilities, Git, Docker-in-Docker
- **Extensions**: Python, Jupyter, Bicep, GitHub Copilot, and more
- **Lifecycle Commands**: Optimized three-stage setup
- **Port Forwarding**: Common development ports (3000, 5000, 8000, 8080)

#### `Dockerfile`
- **Base Image**: Microsoft's Python 3.12 dev container
#### `Dockerfile` (per Python version folder)
- **Base Image**: Microsoft's Python 3.12/3.13/3.14 dev container (depending on folder)
- **System Dependencies**: Essential packages and tools
- **Azure CLI Setup**: Extensions and configuration for Codespaces
- **Virtual Environment**: Auto-activation configuration

#### `post-start-setup.sh`
#### `post-start-setup.sh` (shared behavior)
- **Location**: `.devcontainer/post-start-setup.sh` is invoked by each Python variant's `post-start-setup.sh` wrapper
- **Environment Verification**: Quick checks and status reporting
- **Fallback Installation**: Safety net for missing components
- **User Guidance**: Next steps and helpful information

## 🧭 Choosing a Dev Container in Codespaces

When creating a new Codespace, GitHub will present multiple dev container options derived from the `.devcontainer` subfolders:

- **APIM Samples – Python 3.12** ✅ (folder: `python312`)
- **APIM Samples – Python 3.13** ✅ (folder: `python313`)
- **APIM Samples – Python 3.14** ✅ (folder: `python314`)

All three are supported and prebuilt; choose the Python runtime that best matches your needs or local environment.

### ⚠️ About the "Default" Option

GitHub Codespaces will also display a generic **"Default"** dev container option. **Do not use this option** — it will result in:
- Significantly slower startup times (5-10 minutes vs. ~30 seconds)
- Missing tools, extensions, and optimizations
- Suboptimal development experience

**Always select one of the three Python-specific configurations above.** Unfortunately, GitHub does not currently provide a way to remove the default option from the Codespace creation dialog. This is a GitHub limitation, and we recommend always selecting one of the optimized Python variants.

## 🚀 Setup Stages

### Stage 1: Container Build (Dockerfile)
**When it runs**: During initial container build
**What it does**:
- Installs Python 3.12 and system dependencies
- Installs the selected Python version (3.12, 3.13, or 3.14) and system dependencies
- Configures Azure CLI for Codespaces (device code authentication)
- Installs Azure CLI extensions (`containerapp`, `front-door`)
- Sets up shell auto-activation for virtual environment
Expand Down Expand Up @@ -160,11 +186,12 @@ Our devcontainer uses two key lifecycle commands optimized for prebuild:
#### `onCreateCommand` (Container Creation)
```bash
# Creates Python virtual environment and registers Jupyter kernel
# Note: The Python path varies by selected variant (3.12/3.13/3.14)
echo '🚀 Creating Python virtual environment in workspace...' &&
/usr/local/bin/python3.12 -m venv /workspaces/Apim-Samples/.venv --copies &&
/usr/local/bin/python3.<version> -m venv /workspaces/Apim-Samples/.venv --copies &&
source /workspaces/Apim-Samples/.venv/bin/activate &&
pip install --upgrade pip setuptools wheel ipykernel &&
python -m ipykernel install --user --name=apim-samples --display-name='APIM Samples Python 3.12'
python -m ipykernel install --user --name=python-venv --display-name='Python (.venv)'
```

#### `updateContentCommand` (Content Updates)
Expand All @@ -187,6 +214,14 @@ Prebuild automatically occurs when you push changes to:
- `requirements.txt` (when referenced in `updateContentCommand`)
- Any other files referenced in lifecycle commands

### Caching Strategy

This project relies on GitHub Codespaces Prebuilds for fast startup and predictable environments:

- Main branch: Prebuilds are automatically triggered and cached when `.devcontainer/**` or `requirements.txt` changes. Opening a Codespace on main pulls the prebuilt image, typically starting in ~30 seconds.
- Feature branches: If prebuilds are not enabled, the first Codespace startup builds from the Dockerfile (usually a few minutes with the optimized images). Subsequent starts reuse Codespaces' transient cache.
- Registry images (optional): If you later need deterministic, versioned images across many branches or forks, you can publish images to GHCR and reference the tags directly in `devcontainer.json`. For now, prebuilds on main are sufficient.

### Monitoring Prebuild Status

You can monitor prebuild status in several ways:
Expand Down Expand Up @@ -249,16 +284,16 @@ To refresh the prebuilt container (recommended periodically):

## 🔧 Jupyter Kernel Configuration

The dev container is configured with a custom Jupyter kernel for optimal Python development experience:
The dev container is configured with a standardized Jupyter kernel for optimal Python development experience:

- **Kernel Name**: `apim-samples`
- **Display Name**: "APIM Samples Python 3.12"
- **Kernel Name**: `python-venv`
- **Display Name**: "Python (.venv)"
- **Python Path**: `/workspaces/Apim-Samples/.venv/bin/python`

### Kernel Registration Details
The kernel is automatically registered during the prebuild stage using:
```bash
python -m ipykernel install --user --name=apim-samples --display-name="APIM Samples Python 3.12"
python -m ipykernel install --user --name=python-venv --display-name="Python (.venv)"
```

### VS Code Kernel Configuration
Expand Down Expand Up @@ -300,7 +335,7 @@ az extension add --name front-door
**Symptom**: Kernel not visible in VS Code
**Solution**: Re-register the kernel:
```bash
python -m ipykernel install --user --name=apim-samples --display-name="APIM Samples Python 3.12"
python -m ipykernel install --user --name=python-venv --display-name="Python (.venv)"
```

#### Environment Variables Not Set
Expand Down
86 changes: 86 additions & 0 deletions .devcontainer/post-start-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/bin/bash

# ------------------------------
# APIM SAMPLES INSTANT VERIFICATION
# ------------------------------

start=$(date +%s.%N)

# Make terminal output more prominent
clear
echo "============================================================================"
echo " 🚀 APIM SAMPLES - INSTANT VERIFICATION "
echo "============================================================================"
echo ""
echo "⚡ All heavy setup was completed during prebuild - verifying environment..."
echo ""

# ------------------------------
# LIGHTNING FAST VERIFICATION
# ------------------------------

WORKSPACE_ROOT="/workspaces/Apim-Samples"
VENV_PATH="$WORKSPACE_ROOT/.venv"
PY_VERSION=$(python --version 2>/dev/null | awk '{print $2}' | cut -d'.' -f1,2)
PY_VERSION_DISPLAY=${PY_VERSION:-"unknown"}

echo -e "Environment Status:\n"

# Ultra-fast file system checks (no command execution)
if [ -d "$VENV_PATH" ]; then
echo " ✅ Virtual environment"
else
echo " ❌ Virtual environment missing"
fi

if [ -f "$WORKSPACE_ROOT/.env" ]; then
echo " ✅ Environment file"
else
echo " ❌ Environment file missing"
fi

# Quick command availability checks (fast)
if command -v az >/dev/null 2>&1; then
echo " ✅ Azure CLI"
else
echo " ❌ Azure CLI missing"
fi

if command -v python >/dev/null 2>&1; then
echo " ✅ Python (${PY_VERSION_DISPLAY})"
else
echo " ❌ Python missing"
fi

# Calculate total duration
end=$(date +%s.%N)
duration=$(python3 -c "print(f'{float('$end') - float('$start'):.1f}')" 2>/dev/null || echo "0.1")

echo ""
echo "============================================================================"
echo " ⚡ INSTANT VERIFICATION COMPLETE! "
echo "============================================================================"
echo ""
printf "⏱️ Verification time: %s seconds\n" "$duration"
echo ""
echo "🎉 Your APIM Samples environment is ready to use!"
echo -e "\n"
echo " Next Steps:"
echo ""
echo " 1. Open a new terminal and log in via the Azure CLI with either command."
echo " See TROUBLESHOOTING.md in the root for details."
echo ""
echo " - az login"
echo " - az login --tenant <your-tenant-id>"
echo ""
echo " 2. Wait until Codespace is fully started (it's fairly quick):"
echo " - Watch progress indicators in status bar"
echo " - Wait for all extensions to install"
echo " --> ✅ (.venv) prefix will appear when you open a new terminal"
echo ""
echo " 3. Start using the infrastructures and samples!"
echo " - You may initially need to select the kernel (top-right above the"
echo " Jupyter notebook). If so, select the '.venv' Python environment."
echo ""
echo "============================================================================"
echo -e "\n\n"
38 changes: 9 additions & 29 deletions .devcontainer/python312/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,14 @@ ENV PYTHONUNBUFFERED=1 \
PYTHONPATH=/workspaces/Apim-Samples/shared/python:/workspaces/Apim-Samples \
DEBIAN_FRONTEND=noninteractive

# Install system dependencies as root
# Install minimal system dependencies as root
USER root
RUN --mount=type=cache,target=/var/cache/apt \
--mount=type=cache,target=/var/lib/apt/lists \
apt-get update && \
# Remove Python 3.11 and other versions if they exist
apt-get remove -y python3.11* python3-minimal python3.11-minimal || true && \
apt-get autoremove -y && \
# Install essential packages
apt-get install -y --no-install-recommends curl wget jq tree git-lfs vim nano htop && \
apt-get install -y --no-install-recommends curl git-lfs && \
apt-get clean && \
# Create symbolic links to ensure python3 points to Python 3.12
ln -sf /usr/local/bin/python3.12 /usr/bin/python3 && \
ln -sf /usr/local/bin/python3.12 /usr/bin/python && \
# Ensure latest pip is installed for Python 3.12
rm -rf /var/lib/apt/lists/* && \
/usr/local/bin/python3.12 -m pip install --upgrade pip setuptools wheel

# Switch to vscode user
Expand All @@ -41,30 +34,17 @@ RUN az config set core.login_experience_v2=off 2>/dev/null || true && \
az extension add --name containerapp --only-show-errors 2>/dev/null || true && \
az extension add --name front-door --only-show-errors 2>/dev/null || true

# Configure shell aliases and helpful commands (venv handled by devcontainer)
RUN echo "# APIM Samples helpful aliases" >> ~/.bashrc && \
echo "alias ll='ls -alF'" >> ~/.bashrc && \
echo "alias la='ls -A'" >> ~/.bashrc && \
echo "alias l='ls -CF'" >> ~/.bashrc && \
echo "alias pytest-cov='python -m pytest --cov=. --cov-report=html'" >> ~/.bashrc && \
echo "" >> ~/.zshrc && \
echo "# APIM Samples helpful aliases" >> ~/.zshrc && \
echo "alias ll='ls -alF'" >> ~/.zshrc && \
echo "alias la='ls -A'" >> ~/.zshrc && \
echo "alias l='ls -CF'" >> ~/.zshrc && \
echo "alias pytest-cov='python -m pytest --cov=. --cov-report=html'" >> ~/.zshrc

# Set final working directory
WORKDIR /workspaces/Apim-Samples

# Add health check for the virtual environment
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD . /workspaces/Apim-Samples/.venv/bin/activate && python -c "import sys, pip; print(f'Python {sys.version}'); print(f'Pip {pip.__version__}'); import requests, jwt; print('Core packages OK')" || exit 1
CMD . /workspaces/Apim-Samples/.venv/bin/activate && python -c "import sys, pip; print(f'Python {sys.version}'); print(f'Pip {pip.__version__}')" || exit 1

# Add labels for maintainability
LABEL maintainer="APIM Samples Team" \
description="Simplified dev container for Azure API Management samples with Codespaces prebuild optimization" \
version="2.1" \
python.version="3.12" \
debian.version="bookworm" \
venv.location="/workspaces/Apim-Samples/.venv"
description="Optimized dev container for Azure API Management samples with Codespaces prebuild support" \
version="2.2" \
python.version="3.12" \
debian.version="bookworm" \
venv.location="/workspaces/Apim-Samples/.venv"
Loading
Loading