- Posted on
- • Artificial Intelligence
Artificial Intelligence DevOps Pipelines
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
Bash-first AI DevOps Pipelines on Linux: A Practical Guide
AI models don’t fail because of math—they fail because of messy handoffs, missing data lineage, and “it worked on my machine” deployments. If you’re a Linux user who prefers Bash and reproducible builds, this guide shows you how to build an Artificial Intelligence DevOps pipeline you can trust: versioned data, automated training, containerized serving, and CI hooks—all with simple shell commands.
What you’ll get:
Why AI DevOps pipelines matter and what they solve
A Bash-first, portable toolkit: Git, Python, DVC, MLflow, Podman/Docker, Make
3–5 actionable steps to stand up a real, reproducible pipeline
Copy-pasteable commands for apt, dnf, and zypper
Why AI DevOps Pipelines Matter
Reproducibility: Same data, same environment, same result. Pipelines formalize every step and dependency.
Speed and safety: Automate training, testing, and packaging so you can move fast without breaking prod.
Observability: Track metrics and artifacts (models, datasets) with traceability for audits and rollbacks.
Portability: Containerized workflows run anywhere—your laptop, CI, or the cloud.
Prerequisites: Install the Basics
Install these once. They’re available from standard repos across major distros.
Packages:
git, python3, python3-venv, python3-pip, make
curl, jq
podman, buildah, skopeo (rootless containers; Docker users can swap commands)
git-lfs (for large files in Git)
shellcheck (for Bash linting)
Debian/Ubuntu (apt):
sudo apt update
sudo apt install -y \
git python3 python3-venv python3-pip make \
curl jq \
podman buildah skopeo \
git-lfs shellcheck
Fedora/RHEL/CentOS Stream (dnf):
sudo dnf install -y \
git python3 python3-venv python3-pip make \
curl jq \
podman buildah skopeo \
git-lfs shellcheck
openSUSE (zypper):
sudo zypper refresh
sudo zypper install -y \
git python3 python3-venv python3-pip make \
curl jq \
podman buildah skopeo \
git-lfs ShellCheck
Note for Docker users:
- Docker isn’t in all default repos. If you prefer Docker, follow Docker’s official repo install docs, then replace
podmanwithdockerin the commands below.
Step 1: Scaffold a Minimal, Reproducible Project
Initialize a repository and Python environment.
mkdir -p ai-pipeline/{scripts,data,models}
cd ai-pipeline
git init
python3 -m venv venv
. venv/bin/activate
python -m pip install --upgrade pip
pip install \
scikit-learn numpy pandas \
dvc mlflow \
fastapi uvicorn[standard] \
black isort flake8 pytest pre-commit
Enable Git LFS and pre-commit:
git lfs install
cat > .pre-commit-config.yaml << 'EOF'
repos:
- repo: https://github.com/psf/black
rev: 24.3.0
hooks: [{id: black}]
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks: [{id: isort}]
- repo: https://github.com/pycqa/flake8
rev: 7.0.0
hooks: [{id: flake8}]
- repo: https://github.com/koalaman/shellcheck-precommit
rev: v0.10.0
hooks: [{id: shellcheck}]
EOF
pre-commit install
Create a simple data fetch script:
cat > scripts/fetch_data.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail
out="${1:-data/raw.csv}"
mkdir -p "$(dirname "$out")"
# Synthetic dataset for demo
python - <<PY > "$out"
import numpy as np, pandas as pd
from sklearn.datasets import make_classification
X,y = make_classification(n_samples=1000, n_features=20, random_state=42)
cols = [f"f{i}" for i in range(X.shape[1])]
df = pd.DataFrame(X, columns=cols)
df["target"] = y
df.to_csv("$out", index=False)
print(f"Wrote {out}")
PY
echo "OK: $out"
EOF
chmod +x scripts/fetch_data.sh
Training script:
cat > scripts/train.py << 'EOF'
import argparse, joblib, os
import mlflow
import numpy as np, pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
def main():
p = argparse.ArgumentParser()
p.add_argument("--data", required=True)
p.add_argument("--model", required=True)
args = p.parse_args()
df = pd.read_csv(args.data)
X = df.drop(columns=["target"]).values
y = df["target"].values
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.2, random_state=42)
mlflow.set_tracking_uri("file://" + os.path.abspath("mlruns"))
with mlflow.start_run():
clf = LogisticRegression(max_iter=1000, n_jobs=-1)
clf.fit(Xtr, ytr)
acc = clf.score(Xte, yte)
mlflow.log_metric("accuracy", acc)
os.makedirs(os.path.dirname(args.model), exist_ok=True)
joblib.dump(clf, args.model)
mlflow.log_artifact(args.model)
print(f"Trained model saved to {args.model}")
if __name__ == "__main__":
main()
EOF
Evaluation script:
cat > scripts/evaluate.py << 'EOF'
import argparse, json
import joblib, pandas as pd
from sklearn.metrics import accuracy_score
p = argparse.ArgumentParser()
p.add_argument("--data", required=True)
p.add_argument("--model", required=True)
p.add_argument("--metrics", required=True)
args = p.parse_args()
df = pd.read_csv(args.data)
X = df.drop(columns=["target"]).values
y = df["target"].values
clf = joblib.load(args.model)
pred = clf.predict(X)
acc = accuracy_score(y, pred)
metrics = {"accuracy_full_dataset": float(acc)}
with open(args.metrics, "w") as f:
json.dump(metrics, f)
print(json.dumps(metrics, indent=2))
EOF
Step 2: Track Data and Models with DVC
Initialize DVC and define a pipeline. DVC treats data, models, and metrics as first-class versioned citizens.
dvc init
git add .dvc .gitignore
git commit -m "Initialize DVC"
Create dvc.yaml:
cat > dvc.yaml << 'EOF'
stages:
data:
cmd: bash scripts/fetch_data.sh data/raw.csv
deps:
- scripts/fetch_data.sh
outs:
- data/raw.csv
train:
cmd: venv/bin/python scripts/train.py --data data/raw.csv --model models/model.pkl
deps:
- scripts/train.py
- data/raw.csv
outs:
- models/model.pkl
eval:
cmd: venv/bin/python scripts/evaluate.py --data data/raw.csv --model models/model.pkl --metrics metrics.json
deps:
- scripts/evaluate.py
- data/raw.csv
- models/model.pkl
metrics:
- metrics.json
EOF
Reproduce the pipeline end-to-end:
. venv/bin/activate
dvc repro
Optional: Configure a remote (S3, SSH, etc.) to store data/models outside Git:
dvc remote add -d storage s3://my-bucket/ai-pipeline
dvc push
Step 3: Orchestrate with Make (Bash-friendly)
A Makefile gives you one-liners for setup, training, testing, and packaging.
cat > Makefile << 'EOF'
SHELL := /usr/bin/env bash
CONTAINER ?= podman
.PHONY: help
help:
@echo "Targets:"
@echo " venv - Create Python venv and install deps"
@echo " fmt - Format Python code"
@echo " lint - Lint Python and shell scripts"
@echo " repro - Run full DVC pipeline"
@echo " build - Build container image"
@echo " run - Run API server container"
@echo " test - Run unit tests"
venv:
python3 -m venv venv
venv/bin/pip install --upgrade pip
venv/bin/pip install -r requirements.txt || true
fmt:
venv/bin/black .
venv/bin/isort .
lint:
venv/bin/flake8 .
find scripts -type f -name "*.sh" -print0 | xargs -0 -r shellcheck
repro:
. venv/bin/activate && dvc repro
build:
$(CONTAINER) build -t ai-pipeline:latest -f Dockerfile .
run:
$(CONTAINER) run --rm -p 8000:8000 ai-pipeline:latest
test:
venv/bin/pytest -q
EOF
Lock your Python dependencies:
cat > requirements.txt << 'EOF'
scikit-learn
numpy
pandas
dvc
mlflow
fastapi
uvicorn[standard]
black
isort
flake8
pytest
joblib
EOF
Step 4: Containerize a Minimal Inference API
Add a small FastAPI app to serve predictions. This allows CI/CD to ship a runnable artifact.
cat > app.py << 'EOF'
import joblib
import numpy as np
from fastapi import FastAPI
from pydantic import BaseModel
class Features(BaseModel):
values: list[float]
app = FastAPI()
model = joblib.load("models/model.pkl")
@app.get("/healthz")
def healthz():
return {"status": "ok"}
@app.post("/predict")
def predict(f: Features):
x = np.array([f.values])
y = model.predict(x).tolist()
return {"prediction": y[0]}
EOF
Containerfile (works with Podman or Docker):
cat > Dockerfile << 'EOF'
FROM python:3.11-slim
RUN useradd -m app
WORKDIR /app
COPY requirements.txt /app/
RUN pip install --no-cache-dir -r requirements.txt
COPY . /app
USER app
EXPOSE 8000
CMD ["uvicorn", "app:app", "--host=0.0.0.0", "--port=8000"]
EOF
Build and run (Podman; swap to docker if you prefer):
podman build -t ai-pipeline:latest .
podman run --rm -p 8000:8000 ai-pipeline:latest
Test:
curl -s http://localhost:8000/healthz
curl -s -X POST http://localhost:8000/predict \
-H 'Content-Type: application/json' \
-d '{"values":[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2.0]}'
Step 5: Automate with CI (GitHub Actions Example)
Add a CI workflow that formats, lints, reproduces the pipeline, and builds the container image on each push.
mkdir -p .github/workflows
cat > .github/workflows/ci.yml << 'EOF'
name: ci
on:
push:
pull_request:
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: System deps
run: |
sudo apt-get update
sudo apt-get install -y python3-venv python3-pip git-lfs shellcheck podman
git lfs install
- name: Python deps
run: |
python3 -m venv venv
venv/bin/pip install --upgrade pip
venv/bin/pip install -r requirements.txt
- name: Lint & Format
run: |
venv/bin/black --check .
venv/bin/isort --check-only .
venv/bin/flake8 .
find scripts -type f -name "*.sh" -print0 | xargs -0 -r shellcheck
- name: Reproduce pipeline
run: |
. venv/bin/activate
dvc repro
- name: Build container
run: |
podman build -t ai-pipeline:ci .
EOF
Real-World Patterns You Can Reuse Today
Nightly retraining with artifact retention:
- Use DVC with an S3/SSH remote. Schedule a nightly
dvc repro && dvc pushin CI. Keep N best models by metric using a simple script that readsmetrics.json.
- Use DVC with an S3/SSH remote. Schedule a nightly
Governance and auditability:
- Tie MLflow runs to Git SHA and DVC data version. You’ll always know which data/model/code produced which metric.
Fast rollback:
- Tag container images with both
latestand a version (YYYYMMDD.sha). If metrics degrade, deploy the prior tag.
- Tag container images with both
Local-to-prod parity:
- Podman rootless builds and runs mimic production containers without extra daemon complexity.
Putting It All Together (Quickstart Recap)
Install prerequisites (apt/dnf/zypper commands above).
Create venv, install Python deps, and initialize DVC.
Add scripts for data, train, and evaluate. Reproduce with
dvc repro.Containerize the app and run via
podman run -p 8000:8000.Wire up CI to lint, test, repro, and build on every push.
If you want a single-shot run locally:
. venv/bin/activate
dvc repro
podman build -t ai-pipeline:latest .
podman run --rm -p 8000:8000 ai-pipeline:latest
Conclusion and Call to Action
You now have a Bash-first AI DevOps pipeline: versioned data and models (DVC), tracked metrics (MLflow), reproducible orchestration (Make), and portable deployment (Podman/Docker). This foundation scales from your laptop to CI and production with minimal changes.
Your next steps:
Add real datasets and connect a DVC remote (S3/SSH).
Expand tests and add monitoring (drift alerts, latency SLOs).
Automate promotion: only ship models that beat baseline metrics.
Clone this pattern into your next AI project and ship models you can trust—confidently, repeatedly, and with a single command.