Cross-platform, reproducible Python environment for AI, machine learning, and data science work.
The goal of this repository is to provide a general-purpose research environment that can be used consistently across local machines, remote compute environments, and Docker.
The repository uses:
environment.ymlas the human-edited environment specificationconda-lockto generate a single deterministic, multi-platform lockfile- GitHub Actions to validate the environment across supported platforms
- Docker to provide a portable prebuilt environment
- GitHub Container Registry (GHCR) to distribute multi-architecture Docker images
The general workflow is:
environment.yml
│
▼
conda-lock.yml
│
├── native installation
│ ├── Linux x86-64
│ ├── Linux ARM64
│ ├── macOS Intel
│ ├── macOS Apple Silicon
│ └── Windows x86-64
│
└── Docker
├── linux/amd64
└── linux/arm64
For most users, the Docker image is the simplest way to use the environment. Native installation from conda-lock.yml is available when direct access to the environment is preferable.
The primary human-edited environment specification.
This file defines:
- package dependencies
- version constraints
- conda channels
- pip-installed dependencies
- supported platforms
The environment name is:
ai-research-env
Normally, dependency changes should be made in environment.yml, not directly in conda-lock.yml.
The canonical generated lockfile.
It contains exact package versions and package hashes for all supported platforms:
linux-64linux-aarch64osx-64osx-arm64win-64
The same conda-lock.yml file is used on every supported platform. conda-lock selects the appropriate platform-specific packages during installation.
Do not edit this file manually.
Builds the Docker image from the canonical conda-lock.yml.
The image contains the complete environment, including both conda and PyPI dependencies.
The default container command starts JupyterLab on port 8888.
Generates the canonical multi-platform conda-lock.yml from environment.yml.
The CI workflows use this script so that lockfile generation is implemented in one place.
Performs runtime validation of the installed environment.
The smoke test verifies important package imports, command-line tools, and representative computations from the AI and scientific Python stack.
The same smoke test is used by the native environment validation workflow and the Docker image workflow.
Checks whether the current environment specification can be successfully resolved into a candidate lockfile.
This workflow runs:
- on relevant pull requests
- manually through
workflow_dispatch
It does not modify the repository.
Maintains the canonical conda-lock.yml.
It runs:
- when relevant environment-definition files change on
main - weekly as a dependency-resolution and lockfile-drift check
- manually through
workflow_dispatch
When run after an environment change:
- A fresh candidate lockfile is generated.
- The candidate is compared with the committed
conda-lock.yml. - If the lockfile changed, the new canonical lockfile is committed automatically.
- The Docker image workflow is then dispatched.
Scheduled runs report dependency-resolution failures or lockfile drift but do not commit changes.
Manual runs can optionally commit a changed lockfile.
Performs full installation and runtime validation of the environment.
The workflow:
- Generates a fresh candidate lockfile.
- Installs the complete locked environment.
- Runs
pip check. - Runs the repository smoke test.
The environment is tested on:
- Linux x86-64
- Linux ARM64
- macOS Intel
- macOS Apple Silicon
- Windows x86-64
This workflow runs on relevant pull requests, relevant pushes to main, on a periodic schedule, and manually.
Builds and tests the Docker image.
Before publication, the image is independently built and tested on:
linux/amd64linux/arm64
Each architecture must pass:
- image build
pip check- the environment smoke test
- JupyterLab validation
After both architectures pass, a multi-architecture image can be published to GHCR.
Validates the repository's CI/CD code.
It checks:
- GitHub Actions workflows with
actionlint - shell scripts with
shellcheck - Python script syntax
Configures automated dependency update pull requests for:
- GitHub Actions
- the Docker base image
A prebuilt multi-architecture Docker image is published to GitHub Container Registry:
ghcr.io/eotles/ai-research-env:latest
Docker automatically selects the appropriate image architecture for supported systems.
docker pull ghcr.io/eotles/ai-research-env:latestMount a local working directory into /work:
docker run -it --rm \
-p 8888:8888 \
-v /path/to/your/workspace:/work \
ghcr.io/eotles/ai-research-env:latestFor example, to use the current directory:
docker run -it --rm \
-p 8888:8888 \
-v "$PWD":/work \
ghcr.io/eotles/ai-research-env:latestThe container starts JupyterLab by default.
Open the URL printed in the terminal. It will look similar to:
http://127.0.0.1:8888/lab?token=...
Stop the container with Ctrl+C.
The default JupyterLab command can be overridden:
docker run --rm \
-v "$PWD":/work \
ghcr.io/eotles/ai-research-env:latest \
python your_script.pydocker run -it --rm \
-v "$PWD":/work \
ghcr.io/eotles/ai-research-env:latest \
bashCheck installed Python package consistency:
docker run --rm \
ghcr.io/eotles/ai-research-env:latest \
python -m pip checkRun the full environment smoke test:
docker run --rm \
ghcr.io/eotles/ai-research-env:latest \
python /opt/ai-research-env/smoke_test.pyFor a native environment without Docker, install from the canonical:
conda-lock.yml
The same lockfile is used for every supported platform. conda-lock automatically selects the packages for the current platform.
Supported platforms are:
| System | conda-lock platform |
|---|---|
| Linux x86-64 | linux-64 |
| Linux ARM64 | linux-aarch64 |
| macOS Intel | osx-64 |
| macOS Apple Silicon | osx-arm64 |
| Windows x86-64 | win-64 |
git clone https://github.com/eotles/ai-research-env.git
cd ai-research-envYou need a conda-compatible package manager and conda-lock.
The same commands apply to both x86-64 and ARM64 Linux systems.
Install conda-lock:
conda install -y \
-n base \
-c conda-forge \
"conda-lock=3.*"Install the locked environment:
conda-lock install \
--name ai-research-env \
conda-lock.ymlActivate it:
conda activate ai-research-envStart JupyterLab:
jupyter labThe same commands apply to both Intel Macs and Apple Silicon Macs.
Install conda-lock:
conda install -y \
-n base \
-c conda-forge \
"conda-lock=3.*"Install the locked environment:
conda-lock install \
--name ai-research-env \
conda-lock.ymlActivate it:
conda activate ai-research-envStart JupyterLab:
jupyter labFrom Anaconda Prompt or another shell with conda available:
conda install -y `
-n base `
-c conda-forge `
"conda-lock=3.*"Install the locked environment:
conda-lock install `
--name ai-research-env `
conda-lock.ymlActivate it:
conda activate ai-research-envStart JupyterLab:
jupyter labThe repository also supports micromamba.
Install conda-lock into the base environment:
micromamba install -y \
-n base \
-c conda-forge \
"conda-lock=3.*"Install the locked environment using micromamba as the conda-compatible installer:
micromamba run -n base \
conda-lock install \
--conda "$(command -v micromamba)" \
--name ai-research-env \
conda-lock.ymlActivate the environment:
micromamba activate ai-research-envThe normal dependency update workflow starts with environment.yml.
- Edit
environment.yml. - Commit and push the change to
main. lockfile-updategenerates a fresh candidate lockfile.- If the resolved environment changed, the workflow updates and commits
conda-lock.yml. - A changed canonical lockfile triggers the Docker image workflow.
- Docker images are built and tested for both
linux/amd64andlinux/arm64. - After both image tests pass, the multi-architecture image is published to GHCR.
At the same time, environment-install-check validates that the complete environment can be installed and executed across all five supported native platforms.
Conceptually:
edit environment.yml
│
├─────────────────────────────────────┐
│ │
▼ ▼
lockfile-update environment-install-check
│ │
generate candidate generate candidate
│ │
compare with canonical install on 5 platforms
│ │
update conda-lock.yml pip check
│ │
│ smoke test
│ │
▼ ▼
docker-image validation
│
├── test linux/amd64
├── test linux/arm64
└── publish multi-architecture image
For proposed environment changes:
lockfile-checkverifies that a candidate lockfile can be generated.environment-install-checkinstalls and tests the environment across supported platforms.workflow-lintvalidates workflow and script changes when relevant.
The lockfile-check workflow can be run manually from the GitHub Actions interface.
It generates a candidate lockfile and uploads it as a workflow artifact without changing the repository.
The lockfile-update workflow can also be run manually.
The workflow provides an option to:
Commit the regenerated lockfile if it changed
When disabled, the workflow performs a check-only run.
When enabled, a changed lockfile is committed to the repository and the Docker image workflow is dispatched.
The repository performs periodic automated checks.
lockfile-update periodically:
- performs a fresh dependency solve
- reports dependency-resolution failures
- reports lockfile drift
- does not commit changes during scheduled runs
environment-install-check periodically:
- generates a fresh candidate lockfile
- installs the complete environment
- runs dependency consistency checks
- runs the environment smoke test across all supported platforms
The docker-image workflow can be run manually.
A manual run can test both Docker architectures without publishing an image.
The workflow also provides an option to publish the image to GHCR after all tests pass.
environment.ymlis the human-edited source of truth for dependencies.conda-lock.ymlis the generated source of truth for reproducible installation.- Do not edit
conda-lock.ymlmanually. - The Docker image is the simplest way to get a consistent environment on a machine with Docker.
- Native installation from
conda-lock.ymlprovides a reproducible local environment for supported platforms. - Docker images are validated on both
linux/amd64andlinux/arm64before publication. - Native environments are validated on Linux x86-64, Linux ARM64, Intel macOS, Apple Silicon, and Windows.