Complete walkthrough for building a minimal Python container with pip packages.
This example demonstrates:
- Creating a minimal Python environment with pip packages
- Building and testing locally
- Pushing to a container registry
- Running the container
Use case: Lightweight Python applications with PyPI-only dependencies.
- Docker installed and running
- Absconda installed (
pip install absconda) - Container registry access (GitHub Container Registry in this example)
Create minimal-env.yaml:
name: minimal-python
channels:
- conda-forge
dependencies:
- python=3.11
- pip
- pip:
- requests==2.31.0
- click==8.1.7
labels:
org.opencontainers.image.title: "Minimal Python Environment"
org.opencontainers.image.description: "Lightweight Python with requests and click"
org.opencontainers.image.authors: "your-email@example.com"Package breakdown:
- python=3.11: Python interpreter from Conda
- pip: Pip package manager
- requests: HTTP library for API calls
- click: CLI framework
Check the environment file for issues:
absconda validate --file minimal-env.yamlExpected output:
Using policy profile default from built-in defaults.
Environment minimal-python is valid with 2 dependency entries.
Preview the generated Dockerfile:
absconda generate --file minimal-env.yaml --output Dockerfile.previewGenerated Dockerfile (excerpt):
# Builder stage
FROM mambaorg/micromamba:latest AS builder
COPY minimal-env.yaml /tmp/env.yaml
RUN micromamba create -y -n minimal-python -f /tmp/env.yaml && \
micromamba clean -afy
# Runtime stage
FROM mambaorg/micromamba:latest
COPY --from=builder /opt/conda/envs/minimal-python /opt/conda/envs/minimal-python
ENV PATH=/opt/conda/envs/minimal-python/bin:$PATH
LABEL org.opencontainers.image.title="Minimal Python Environment"
LABEL org.opencontainers.image.description="Lightweight Python with requests and click"Build the container image:
absconda build \
--file minimal-env.yaml \
--repository ghcr.io/yourusername/minimal-python \
--tag v1.0Build output:
Using policy profile default from built-in defaults.
[+] Building 45.2s (12/12) FINISHED
=> [builder 1/3] FROM docker.io/mambaorg/micromamba:latest
=> [builder 2/3] COPY minimal-env.yaml /tmp/env.yaml
=> [builder 3/3] RUN micromamba create -y -n minimal-python -f /tmp/env.yaml
=> [stage-1 1/1] COPY --from=builder /opt/conda/envs/minimal-python ...
=> exporting to image
Image built: ghcr.io/yourusername/minimal-python:v1.0
Image size: ~200 MB (Python + requests + click)
docker run --rm ghcr.io/yourusername/minimal-python:v1.0 python --versionOutput: Python 3.11.7
docker run --rm ghcr.io/yourusername/minimal-python:v1.0 python -c "import requests; print(requests.__version__)"Output: 2.31.0
docker run --rm ghcr.io/yourusername/minimal-python:v1.0 python -c "import click; print(click.__version__)"Output: 8.1.7
docker run --rm ghcr.io/yourusername/minimal-python:v1.0 \
python -c "import requests; r = requests.get('https://api.github.com'); print(r.status_code)"Output: 200
Create a simple CLI application to test in the container.
app.py:
#!/usr/bin/env python3
"""Simple CLI app using click and requests."""
import click
import requests
@click.command()
@click.option('--url', default='https://api.github.com', help='URL to fetch')
def main(url):
"""Fetch URL and display status."""
click.echo(f"Fetching {url}...")
response = requests.get(url)
click.echo(f"Status: {response.status_code}")
click.echo(f"Content-Type: {response.headers.get('content-type')}")
if __name__ == '__main__':
main()# Mount current directory and run app
docker run --rm -v $PWD:/app -w /app \
ghcr.io/yourusername/minimal-python:v1.0 \
python app.py --url https://api.github.com/users/octocatOutput:
Fetching https://api.github.com/users/octocat...
Status: 200
Content-Type: application/json; charset=utf-8
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdinabsconda build \
--file minimal-env.yaml \
--repository ghcr.io/yourusername/minimal-python \
--tag v1.0 \
--pushOutput:
Image built: ghcr.io/yourusername/minimal-python:v1.0
The push refers to repository [ghcr.io/yourusername/minimal-python]
v1.0: digest: sha256:abc123... size: 1234
Image pushed: ghcr.io/yourusername/minimal-python:v1.0
docker tag ghcr.io/yourusername/minimal-python:v1.0 \
ghcr.io/yourusername/minimal-python:latest
docker push ghcr.io/yourusername/minimal-python:latestdocker-compose.yml:
version: '3.8'
services:
app:
image: ghcr.io/yourusername/minimal-python:v1.0
volumes:
- ./app:/app
working_dir: /app
command: python app.py --url https://api.example.comRun:
docker-compose updeployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: minimal-python-app
spec:
replicas: 3
selector:
matchLabels:
app: minimal-python
template:
metadata:
labels:
app: minimal-python
spec:
containers:
- name: app
image: ghcr.io/yourusername/minimal-python:v1.0
command: ["python", "app.py"]
volumeMounts:
- name: app-code
mountPath: /app
volumes:
- name: app-code
configMap:
name: app-codeFor even smaller images, use pure pip:
requirements.txt:
requests==2.31.0
click==8.1.7
Build:
absconda build \
--requirements requirements.txt \
--repository ghcr.io/yourusername/minimal-python-pure \
--tag v1.0 \
--pushResult: ~120 MB image (vs ~200 MB with Conda)
minimal-dev.yaml:
name: minimal-python-dev
channels:
- conda-forge
dependencies:
- python=3.11
- pip
- pip:
- requests==2.31.0
- click==8.1.7
- pytest==7.4.3
- black==23.12.0
- mypy==1.7.1
labels:
org.opencontainers.image.title: "Minimal Python Dev Environment"Build for multiple platforms:
docker buildx create --use
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t ghcr.io/yourusername/minimal-python:v1.0 \
-f Dockerfile \
--push \
.Error: ModuleNotFoundError: No module named 'requests'
Solution: Verify pip is in conda dependencies and packages are in pip: section:
dependencies:
- pip # ← Must be here
- pip:
- requestsError: docker: permission denied
Solution: Add user to docker group or use sudo:
sudo usermod -aG docker $USER
# Log out and back inSolution 1: Use multi-stage build (default)
Solution 2: Use requirements mode instead of Conda
Solution 3: Use alpine base:
absconda generate \
--requirements requirements.txt \
--base-image python:3.11-alpine \
--output Dockerfile- Data Science Example - NumPy, pandas, scikit-learn
- Requirements Mode Guide - Pure pip workflow
- Building Images Guide - Advanced build options
- CI/CD Integration - Automate builds
Project structure:
minimal-python/
├── minimal-env.yaml
├── app.py
├── requirements.txt (optional)
└── Dockerfile.preview
Download: All files available in examples/ directory.