Skip to content

Commit ddb543d

Browse files
committed
CH-216 dev container image and configuration working WIP
1 parent ecfc86a commit ddb543d

8 files changed

Lines changed: 294 additions & 0 deletions

File tree

.devcontainer/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
home

.devcontainer/devcontainer.json

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"name": "CloudHarness Development",
3+
"dockerComposeFile": "../docker-compose.yml",
4+
"service": "cloudharness",
5+
"workspaceFolder": "/workspace",
6+
"shutdownAction": "none",
7+
"postCreateCommand": "chmod +x /workspace/dev-scripts/vscode-setup.sh && /workspace/dev-scripts/vscode-setup.sh && touch ~/.bashrc && echo 'source /workspace/dev-scripts/use-venv' >> ~/.bashrc && echo 'CloudHarness development environment ready! Virtual environment will auto-activate in new terminals.'",
8+
"postStartCommand": "source /workspace/dev-scripts/use-venv && echo 'Runtime virtual environment activated'",
9+
"customizations": {
10+
"vscode": {
11+
"settings": {
12+
"terminal.integrated.defaultProfile.linux": "bash",
13+
"python.defaultInterpreterPath": "/root/.local/venv/bin/python",
14+
"python.terminal.activateEnvironment": true,
15+
"python.terminal.activateEnvInCurrentTerminal": true,
16+
"terminal.integrated.shellIntegration.enabled": true,
17+
"extensions.autoUpdate": false,
18+
"extensions.autoCheckUpdates": false,
19+
"python.analysis.extraPaths": [
20+
"/root/.local/venv/lib/python3.12/site-packages",
21+
"/workspace/libraries/models",
22+
"/workspace/libraries/cloudharness-utils",
23+
"/workspace/libraries/cloudharness-common",
24+
"/workspace/libraries/client/cloudharness_cli",
25+
"/workspace/tools/deployment-cli-tools"
26+
]
27+
},
28+
"extensions": [
29+
"ms-python.python",
30+
"ms-python.autopep8",
31+
"ms-python.pylint",
32+
"ms-python.python-extension-pack",
33+
"KevinRose.vsc-python-indent",
34+
"dbaeumer.vscode-eslint",
35+
"github.copilot",
36+
"redhat.vscode-yaml",
37+
"ms-vscode.vscode-json"
38+
]
39+
}
40+
},
41+
"remoteUser": "root",
42+
"mounts": [
43+
"source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached"
44+
],
45+
"forwardPorts": [],
46+
"updateContentCommand": "echo 'Container updated'"
47+
}

Dockerfile

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
FROM python:3.12
2+
3+
# Install Node.js 20, OpenJDK and other system dependencies
4+
5+
RUN apt-get update && apt-get install -y \
6+
curl \
7+
git \
8+
build-essential \
9+
nfs-common \
10+
default-jdk \
11+
apt-transport-https \
12+
ca-certificates \
13+
gnupg \
14+
lsb-release \
15+
iputils-ping \
16+
net-tools \
17+
vim \
18+
wget \
19+
&& rm -rf /var/lib/apt/lists/*
20+
21+
# Install Node.js 20.x
22+
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
23+
apt-get install -y nodejs
24+
25+
# Upgrade system pip (separate for clearer error logs)
26+
RUN python -m pip install --upgrade pip
27+
28+
# Update npm globally
29+
RUN npm install -g npm@latest
30+
31+
# Enable corepack if present (Node 20 ships it); ignore if missing
32+
RUN (command -v corepack >/dev/null 2>&1 && corepack enable || echo "corepack not available, continuing")
33+
34+
# Install yarn (try npm classic install first, fallback to corepack prepare)
35+
RUN (npm install -g yarn@latest || (command -v corepack >/dev/null 2>&1 && corepack prepare yarn@stable --activate) || echo "Yarn installation fallback used")
36+
37+
# Set working directory
38+
WORKDIR /cloudharness
39+
40+
# Copy all requirements files first for better Docker layer caching
41+
COPY libraries/models/requirements.txt ./libraries/models/
42+
COPY libraries/cloudharness-utils/requirements.txt ./libraries/cloudharness-utils/
43+
COPY libraries/cloudharness-common/requirements.txt ./libraries/cloudharness-common/
44+
COPY libraries/client/cloudharness_cli/requirements.txt ./libraries/client/cloudharness_cli/
45+
COPY tools/deployment-cli-tools/requirements.txt ./tools/deployment-cli-tools/
46+
47+
# Install all external dependencies with caching
48+
RUN --mount=type=cache,target=/root/.cache \
49+
pip install -r libraries/models/requirements.txt --prefer-binary && \
50+
pip install -r libraries/cloudharness-utils/requirements.txt --prefer-binary && \
51+
pip install -r libraries/cloudharness-common/requirements.txt --prefer-binary && \
52+
pip install -r libraries/client/cloudharness_cli/requirements.txt --prefer-binary && \
53+
pip install -r tools/deployment-cli-tools/requirements.txt --prefer-binary
54+
55+
# Copy requirements files for common framework libraries
56+
COPY infrastructure/common-images/cloudharness-fastapi/libraries/fastapi/requirements.txt ./infrastructure/fastapi-requirements.txt
57+
COPY infrastructure/common-images/cloudharness-flask/requirements.txt ./infrastructure/flask-requirements.txt
58+
59+
# Install additional tools and common framework libraries
60+
RUN --mount=type=cache,target=/root/.cache \
61+
pip install pytest debugpy --prefer-binary && \
62+
pip install -r infrastructure/fastapi-requirements.txt --prefer-binary && \
63+
pip install -r infrastructure/flask-requirements.txt --prefer-binary
64+
65+
# Copy and install libraries one by one
66+
COPY libraries/models ./libraries/models
67+
RUN pip install -e libraries/models --no-cache-dir
68+
69+
COPY libraries/cloudharness-utils ./libraries/cloudharness-utils
70+
RUN pip install -e libraries/cloudharness-utils --no-cache-dir
71+
72+
COPY libraries/cloudharness-common ./libraries/cloudharness-common
73+
RUN pip install -e libraries/cloudharness-common --no-cache-dir
74+
75+
COPY libraries/client/cloudharness_cli ./libraries/client/cloudharness_cli
76+
RUN pip install -e libraries/client/cloudharness_cli --no-cache-dir
77+
78+
COPY tools/deployment-cli-tools ./tools/deployment-cli-tools
79+
RUN pip install -e tools/deployment-cli-tools --no-cache-dir
80+
81+
82+
# Copy and install cloudharness framework libraries (last to ensure they override any conflicts)
83+
COPY infrastructure/common-images/cloudharness-django/libraries/cloudharness-django infrastructure/cloudharness-django
84+
RUN pip install -e infrastructure/cloudharness-django --no-cache-dir || echo "cloudharness-django not installable"
85+
86+
# Ensure latest npm & yarn still available after project copy (optional refresh)
87+
RUN npm install -g npm@latest yarn@latest || true
88+
89+
# Copy dev scripts for runtime virtual environment
90+
COPY dev-scripts ./dev-scripts
91+
RUN chmod +x ./dev-scripts/runtime-venv.sh ./dev-scripts/use-venv ./dev-scripts/vscode-setup.sh
92+
93+
# Add the cloudharness CLI tools to PATH
94+
ENV PATH="/cloudharness/tools/deployment-cli-tools:${PATH}"
95+
96+
# Set the default working directory
97+
WORKDIR /workspace
98+
99+
# Default command
100+
CMD ["/bin/bash"]

dev-scripts/README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Development Scripts
2+
3+
This directory contains scripts to help with the CloudHarness development environment.
4+
5+
## Runtime Virtual Environment
6+
7+
The CloudHarness development container comes with all CloudHarness libraries and common dependencies pre-installed globally. However, if you need to install additional packages for development or testing, you should use the runtime virtual environment to avoid conflicts.
8+
9+
## VS Code Integration
10+
11+
When using VS Code with dev containers, the virtual environment is automatically configured:
12+
13+
- The Python interpreter is set to `/root/.local/venv/bin/python`
14+
- New terminals automatically activate the virtual environment
15+
- The Python analysis paths include both the virtual environment and CloudHarness libraries
16+
- All Python extensions work seamlessly with the virtual environment
17+
18+
### Usage
19+
20+
1. **Set up and activate the runtime virtual environment:**
21+
```bash
22+
/workspace/dev-scripts/runtime-venv.sh
23+
```
24+
25+
2. **Activate an existing runtime virtual environment:**
26+
```bash
27+
source /workspace/dev-scripts/use-venv
28+
```
29+
30+
3. **VS Code setup (automatically runs in dev container):**
31+
```bash
32+
/workspace/dev-scripts/vscode-setup.sh
33+
```
34+
35+
4. **Install additional packages (while venv is active):**
36+
```bash
37+
pip install <package-name>
38+
```
39+
40+
5. **Deactivate the virtual environment:**
41+
```bash
42+
deactivate
43+
```
44+
45+
### How it works
46+
47+
- The runtime virtual environment is created in `$HOME/.local/venv` inside the container
48+
- This location is persisted if you mount a home directory volume
49+
- Global CloudHarness libraries remain accessible due to the PYTHONPATH configuration
50+
- Additional packages installed in the virtual environment take precedence when there are conflicts
51+
- The virtual environment inherits from the global site-packages, so you still have access to all pre-installed libraries
52+
- VS Code dev container automatically configures the Python interpreter and analysis paths
53+
54+
### Best Practices
55+
56+
- Use the runtime virtual environment for experimental packages or project-specific dependencies
57+
- Keep the global environment clean by not installing additional packages directly with pip outside the venv
58+
- Document any additional dependencies in your project's requirements.txt file
59+
- The virtual environment is automatically activated in new VS Code terminals when using dev containers

dev-scripts/runtime-venv.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/bash
2+
3+
# Script to set up and activate a runtime virtual environment
4+
# This allows users to install additional packages at runtime without affecting the global environment
5+
6+
VENV_DIR="$HOME/.local/venv"
7+
8+
# Create virtual environment if it doesn't exist
9+
if [ ! -d "$VENV_DIR" ]; then
10+
echo "Creating runtime virtual environment at $VENV_DIR..."
11+
python -m venv "$VENV_DIR"
12+
fi
13+
14+
# Activate the virtual environment
15+
echo "Activating runtime virtual environment..."
16+
source "$VENV_DIR/bin/activate"
17+
18+
# Ensure pip is up to date in the virtual environment
19+
pip install --upgrade pip
20+
21+
echo "Runtime virtual environment is now active."
22+
echo "You can install additional packages with 'pip install <package>'"
23+
echo "To deactivate, run 'deactivate'"

dev-scripts/use-venv

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/bash
2+
3+
# Wrapper script to source the runtime virtual environment
4+
# Usage: source /workspace/dev-scripts/use-venv
5+
6+
VENV_DIR="$HOME/.local/venv"
7+
8+
if [ -d "$VENV_DIR" ]; then
9+
# Check if we're already in the virtual environment
10+
if [[ "$VIRTUAL_ENV" != "$VENV_DIR" ]]; then
11+
source "$VENV_DIR/bin/activate"
12+
echo "Runtime virtual environment activated."
13+
fi
14+
else
15+
echo "No runtime virtual environment found. Run '/workspace/dev-scripts/runtime-venv.sh' first."
16+
fi

dev-scripts/vscode-setup.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/bash
2+
3+
# VS Code Python environment setup script
4+
# This script ensures the virtual environment is properly set up for VS Code integration
5+
echo "Running VS Code Python environment setup..."
6+
VENV_DIR="$HOME/.local/venv"
7+
8+
# Create the virtual environment if it doesn't exist
9+
if [ ! -d "$VENV_DIR" ]; then
10+
echo "Creating Python virtual environment for VS Code..."
11+
/workspace/dev-scripts/runtime-venv.sh
12+
fi
13+
14+
# Create a Python interpreter symlink that VS Code can reliably find
15+
mkdir -p "$HOME/.local/bin"
16+
ln -sf "$VENV_DIR/bin/python" "$HOME/.local/bin/python-venv"
17+
18+
# Ensure the virtual environment has necessary development packages
19+
source "$VENV_DIR/bin/activate"
20+
pip install --upgrade pip setuptools wheel
21+
22+
echo "Python virtual environment ready for VS Code integration."
23+
echo "Python interpreter: $VENV_DIR/bin/python"

docker-compose.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
version: '3.8'
2+
3+
services:
4+
cloudharness:
5+
build:
6+
context: .
7+
dockerfile: Dockerfile
8+
image: cloudharness-cli:latest
9+
container_name: cloudharness-dev
10+
ports:
11+
- "5000:5000"
12+
- "9000:9000"
13+
volumes:
14+
- .:/workspace
15+
- /var/run/docker.sock:/var/run/docker.sock # For Docker-in-Docker capabilities
16+
- ~/.docker:/root/.docker:ro # Docker client configuration and credentials
17+
- ./.devcontainer/home/:/root # Map local .devcontainer/home to container root
18+
working_dir: /workspace
19+
stdin_open: true
20+
tty: true
21+
environment:
22+
- PYTHONPATH=/cloudharness:/workspace/libraries/models:/workspace/libraries/cloudharness-utils:/workspace/libraries/cloudharness-common:/workspace/libraries/client/cloudharness_cli:/workspace/tools/deployment-cli-tools
23+
- DOCKER_HOST=unix:///var/run/docker.sock
24+
user: "root"
25+
command: tail -f /dev/null # Keep container running infinitely

0 commit comments

Comments
 (0)