Skip to content

Commit 808449e

Browse files
committed
Initial commit
0 parents  commit 808449e

8 files changed

Lines changed: 362 additions & 0 deletions

File tree

.github/workflows/docker-build.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Build and Push Docker Images
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
jobs:
8+
build-and-push:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v4
12+
13+
- name: Extract Python version from release
14+
id: extract_version
15+
run: |
16+
# Extract version from GitHub release tag (assuming format like "3.10" or "v3.10")
17+
VERSION="${{ github.event.release.tag_name }}"
18+
# Remove 'v' prefix if present
19+
PYTHON_VERSION="${VERSION#v}"
20+
echo "python_version=${PYTHON_VERSION}" >> $GITHUB_OUTPUT
21+
22+
- name: Set up Docker Buildx
23+
uses: docker/setup-buildx-action@v3
24+
25+
- name: Login to DockerHub
26+
uses: docker/login-action@v3
27+
with:
28+
username: ${{ secrets.DOCKERHUB_USER }}
29+
password: ${{ secrets.DOCKERHUB_PASS }}
30+
31+
- name: Build and push regular variant
32+
uses: docker/build-push-action@v5
33+
with:
34+
context: .
35+
file: ./Dockerfile-regular
36+
push: true
37+
tags: mantissoftware/python-runner:${{ steps.extract_version.outputs.python_version }}
38+
build-args: |
39+
PYTHON_VERSION=${{ steps.extract_version.outputs.python_version }}
40+
platforms: linux/amd64,linux/arm64
41+
42+
- name: Build and push slim variant
43+
uses: docker/build-push-action@v5
44+
with:
45+
context: .
46+
file: ./Dockerfile-slim
47+
push: true
48+
tags: mantissoftware/python-runner:${{ steps.extract_version.outputs.python_version }}-slim
49+
build-args: |
50+
PYTHON_VERSION=${{ steps.extract_version.outputs.python_version }}
51+
platforms: linux/amd64,linux/arm64
52+
53+
- name: Build and push lite variant
54+
uses: docker/build-push-action@v5
55+
with:
56+
context: .
57+
file: ./Dockerfile-lite
58+
push: true
59+
tags: mantissoftware/python-runner:${{ steps.extract_version.outputs.python_version }}-lite
60+
build-args: |
61+
PYTHON_VERSION=${{ steps.extract_version.outputs.python_version }}
62+
platforms: linux/amd64,linux/arm64
63+
64+
- name: Update release
65+
uses: softprops/action-gh-release@v1
66+
with:
67+
token: ${{ secrets.GITHUB_TOKEN }}
68+
tag_name: ${{ github.event.release.tag_name }}
69+
body: |
70+
Docker images available at: https://hub.docker.com/r/mantissoftware/python-runner/tags
71+
- mantissoftware/python-runner:${{ steps.extract_version.outputs.python_version }}
72+
- mantissoftware/python-runner:${{ steps.extract_version.outputs.python_version }}-slim
73+
- mantissoftware/python-runner:${{ steps.extract_version.outputs.python_version }}-lite

.gitignore

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

Dockerfile-lite

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
ARG PYTHON_VERSION
2+
FROM python:${PYTHON_VERSION}-alpine
3+
4+
# Install dependencies
5+
RUN apk add --no-cache bash
6+
7+
# Create app directory
8+
WORKDIR /app
9+
10+
# Copy entrypoint script
11+
COPY entrypoint.sh /app/entrypoint.sh
12+
RUN chmod +x /app/entrypoint.sh
13+
14+
# Set entrypoint
15+
ENTRYPOINT ["/app/entrypoint.sh"]

Dockerfile-regular

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
ARG PYTHON_VERSION
2+
FROM python:${PYTHON_VERSION}
3+
4+
# Install dependencies
5+
RUN apt-get update && apt-get install -y --no-install-recommends \
6+
bash \
7+
&& rm -rf /var/lib/apt/lists/*
8+
9+
# Create app directory
10+
WORKDIR /app
11+
12+
# Copy entrypoint script
13+
COPY entrypoint.sh /app/entrypoint.sh
14+
RUN chmod +x /app/entrypoint.sh
15+
16+
# Set entrypoint
17+
ENTRYPOINT ["/app/entrypoint.sh"]

Dockerfile-slim

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
ARG PYTHON_VERSION
2+
FROM python:${PYTHON_VERSION}-slim
3+
4+
# Install dependencies
5+
RUN apt-get update && apt-get install -y --no-install-recommends \
6+
bash \
7+
&& rm -rf /var/lib/apt/lists/*
8+
9+
# Create app directory
10+
WORKDIR /app
11+
12+
# Copy entrypoint script
13+
COPY entrypoint.sh /app/entrypoint.sh
14+
RUN chmod +x /app/entrypoint.sh
15+
16+
# Set entrypoint
17+
ENTRYPOINT ["/app/entrypoint.sh"]

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Mantis Software Company
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# Python Runner
2+
3+
A flexible Docker-based Python runner that simplifies deployment and execution of Python applications with configurable environments.
4+
5+
## Available Images
6+
7+
Three variants are provided to suit different needs:
8+
9+
- **Regular** (`mantissoftware/python-runner:[version]`): Based on the official Python image, includes typical packages for general use.
10+
- **Slim** (`mantissoftware/python-runner:[version]-slim`): Based on python:[version]-slim, smaller size with minimal dependencies.
11+
- **Lite** (`mantissoftware/python-runner:[version]-lite`): Based on python:[version]-alpine, ultra-lightweight for minimal deployments.
12+
13+
Replace `[version]` with a Python version like `3.12`.
14+
15+
## Features
16+
17+
- Creates a Python virtual environment automatically
18+
- Supports installation of packages from custom repositories
19+
- Installs OS-level dependencies on demand
20+
- Provides development tools when needed
21+
- Configurable startup commands
22+
- Support for pre-start and post-start scripts
23+
24+
## Environment Variables
25+
26+
### Package Installation
27+
28+
| Variable | Description | Example |
29+
|----------|-------------|---------|
30+
| `REQUIREMENTS_PACKAGES` | Space-separated list of packages to install. Usable when third party tools/libraries is required but they're not dependency of main package. | `"numpy pandas requests"` |
31+
| `PACKAGE_NAME` | Main package to install | `"flask"` |
32+
| `PACKAGE_VERSION` | Version of the main package (Optional). Latest available version will install when not specified. | `"2.0.1"` |
33+
| `UPDATE_PIP` | Update pip before run (default: true) | `"false"` |
34+
35+
### Repository Configuration
36+
37+
| Variable | Description | Example |
38+
|----------|-------------|---------|
39+
| `REPOSITORY_URL` | URL of custom PyPI repository | `"https://pypi.mycompany.com"` |
40+
| `REPOSITORY_HOST` | Host of custom PyPI repository | `"pypi.mycompany.com"` |
41+
42+
### System Configuration
43+
44+
| Variable | Description | Example |
45+
|----------|-------------|---------|
46+
| `OS_DEPENDENCIES` | Space-separated list of system packages to install. | `"curl git"` |
47+
| `INSTALL_DEV_TOOLS` | Whether to install build tools. Use it (default: false) | `"true"` |
48+
49+
### Execution Control
50+
51+
| Variable | Description | Example |
52+
|----------|-------------|---------|
53+
| `STARTUP_COMMAND` | Command to execute | `"flask"` or `"python app.py"` |
54+
| `PRE_START_SCRIPT` | Path to script to run before startup | `"/app/pre_start.sh"` |
55+
| `POST_START_SCRIPT` | Path to script to run after startup | `"/app/post_start.sh"` |
56+
57+
## Usage Examples
58+
59+
### Simple Run
60+
```bash
61+
docker run -it --rm mantissoftware/python-runner:3.12 \
62+
-e REQUIREMENTS_PACKAGES="requests" \
63+
-e STARTUP_COMMAND="python"
64+
```
65+
66+
### Run a Flask Application
67+
```yaml
68+
version: '3'
69+
70+
services:
71+
web:
72+
image: mantissoftware/python-runner:3.12-slim
73+
environment:
74+
- REQUIREMENTS_PACKAGES=flask gunicorn
75+
- STARTUP_COMMAND=gunicorn -b 0.0.0.0:5000 app:app
76+
ports:
77+
- "5000:5000"
78+
volumes:
79+
- ./:/app/src
80+
working_dir: /app/src
81+
```
82+
83+
### Data Science Environment
84+
```yaml
85+
version: '3'
86+
87+
services:
88+
jupyter:
89+
image: mantissoftware/python-runner:3.12
90+
environment:
91+
- REQUIREMENTS_PACKAGES=jupyter pandas matplotlib scikit-learn
92+
- STARTUP_COMMAND=jupyter notebook --ip=0.0.0.0 --no-browser --allow-root
93+
- INSTALL_DEV_TOOLS=true
94+
ports:
95+
- "8888:8888"
96+
volumes:
97+
- ./notebooks:/app/notebooks
98+
working_dir: /app/notebooks
99+
```
100+
## Building Locally
101+
To build the images locally:
102+
```bash
103+
# Set Python version
104+
PYTHON_VERSION=3.12
105+
106+
# Regular image
107+
docker build -t python-runner:${PYTHON_VERSION} \
108+
-f Dockerfile-regular \
109+
--build-arg PYTHON_VERSION=${PYTHON_VERSION} .
110+
111+
# Slim image
112+
docker build -t python-runner:${PYTHON_VERSION}-slim \
113+
-f Dockerfile-slim \
114+
--build-arg PYTHON_VERSION=${PYTHON_VERSION} .
115+
116+
# Lite image
117+
docker build -t python-runner:${PYTHON_VERSION}-lite \
118+
-f Dockerfile-lite \
119+
--build-arg PYTHON_VERSION=${PYTHON_VERSION} .
120+
```
121+
122+
## How It Works
123+
124+
The container starts and installs any requested OS dependencies
125+
126+
1. A virtual environment is created in /app/venv
127+
2. Pip is configured for custom repositories if needed
128+
3. Required packages are installed
129+
4. Pre-start script is executed (if specified)
130+
5. The startup command or package is executed
131+
6. Post-start script is executed (if specified)
132+
133+
## License
134+
135+
This project is licensed under the MIT License - see the LICENSE file for details.

entrypoint.sh

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Detect OS type for package installation
5+
if [ -f /etc/os-release ]; then
6+
. /etc/os-release
7+
OS_TYPE=$ID
8+
else
9+
# Default to debian if can't detect
10+
OS_TYPE="debian"
11+
fi
12+
13+
# Install OS dependencies if specified
14+
if [[ -n "$OS_DEPENDENCIES" ]]; then
15+
echo "Installing OS dependencies: $OS_DEPENDENCIES"
16+
if [[ "$OS_TYPE" == "alpine" ]]; then
17+
apk add --no-cache $OS_DEPENDENCIES
18+
else
19+
apt-get update && apt-get install -y --no-install-recommends $OS_DEPENDENCIES && rm -rf /var/lib/apt/lists/*
20+
fi
21+
fi
22+
23+
# Install development tools if requested
24+
if [[ "${INSTALL_DEV_TOOLS}" == "true" ]]; then
25+
echo "Installing development tools"
26+
if [[ "$OS_TYPE" == "alpine" ]]; then
27+
apk add --no-cache build-base linux-headers
28+
else
29+
apt-get update && apt-get install -y --no-install-recommends build-essential && rm -rf /var/lib/apt/lists/*
30+
fi
31+
fi
32+
33+
# Create virtualenv
34+
python -m venv /app/venv
35+
36+
# Configure pip if repository info provided
37+
if [[ -n "$REPOSITORY_URL" && -n "$REPOSITORY_HOST" ]]; then
38+
cat > /app/venv/pip.conf << EOF
39+
[global]
40+
index = ${REPOSITORY_URL}/
41+
index-url = ${REPOSITORY_URL}/simple
42+
trusted-host = ${REPOSITORY_HOST}
43+
EOF
44+
fi
45+
46+
# Update pip if needed (default is true)
47+
if [[ "${UPDATE_PIP:-true}" != "false" ]]; then
48+
/app/venv/bin/pip install --upgrade pip
49+
fi
50+
51+
# Install requirements packages if specified
52+
if [[ -n "$REQUIREMENTS_PACKAGES" ]]; then
53+
/app/venv/bin/pip install $REQUIREMENTS_PACKAGES
54+
fi
55+
56+
# Install specified package
57+
if [[ -n "$PACKAGE_NAME" ]]; then
58+
if [[ -n "$PACKAGE_VERSION" ]]; then
59+
/app/venv/bin/pip install "${PACKAGE_NAME}==${PACKAGE_VERSION}"
60+
else
61+
/app/venv/bin/pip install "${PACKAGE_NAME}"
62+
fi
63+
fi
64+
65+
# Run pre-start script if specified
66+
if [[ -n "$PRE_START_SCRIPT" ]]; then
67+
source "$PRE_START_SCRIPT"
68+
fi
69+
70+
# Run startup command or package
71+
if [[ -n "$STARTUP_COMMAND" ]]; then
72+
exec /app/venv/bin/$STARTUP_COMMAND
73+
elif [[ -n "$PACKAGE_NAME" ]]; then
74+
exec /app/venv/bin/$PACKAGE_NAME
75+
else
76+
echo "Error: Neither STARTUP_COMMAND nor PACKAGE_NAME specified"
77+
exit 1
78+
fi
79+
80+
# Run post-start script if specified
81+
if [[ -n "$POST_START_SCRIPT" ]]; then
82+
source "$POST_START_SCRIPT"
83+
fi

0 commit comments

Comments
 (0)