idmtools-platform-container 0.0.0.dev0__py3-none-any.whl → 0.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- docker_image/BASE_VERSION +1 -0
- docker_image/Dockerfile +48 -0
- docker_image/Dockerfile_buildenv +46 -0
- docker_image/ImageName +1 -0
- docker_image/README.md +78 -0
- docker_image/__init__.py +6 -0
- docker_image/build_docker_image.py +145 -0
- docker_image/debian/BASE_VERSION +1 -0
- docker_image/debian/Dockerfile +40 -0
- docker_image/debian/ImageName +1 -0
- docker_image/debian/README.md +48 -0
- docker_image/debian/pip.conf +3 -0
- docker_image/debian/requirements.txt +1 -0
- docker_image/docker_image_history.py +101 -0
- docker_image/pip.conf +3 -0
- docker_image/push_docker_image.py +62 -0
- docker_image/requirements.txt +1 -0
- docker_image/rocky_meta_runtime.txt +37 -0
- idmtools_platform_container/__init__.py +18 -8
- idmtools_platform_container/cli/__init__.py +5 -0
- idmtools_platform_container/cli/container.py +682 -0
- idmtools_platform_container/container_operations/__init__.py +5 -0
- idmtools_platform_container/container_operations/docker_operations.py +593 -0
- idmtools_platform_container/container_platform.py +375 -0
- idmtools_platform_container/platform_operations/__init__.py +5 -0
- idmtools_platform_container/platform_operations/experiment_operations.py +112 -0
- idmtools_platform_container/platform_operations/simulation_operations.py +58 -0
- idmtools_platform_container/plugin_info.py +79 -0
- idmtools_platform_container/utils/__init__.py +5 -0
- idmtools_platform_container/utils/general.py +136 -0
- idmtools_platform_container/utils/status.py +130 -0
- idmtools_platform_container-0.0.3.dist-info/METADATA +212 -0
- idmtools_platform_container-0.0.3.dist-info/RECORD +69 -0
- idmtools_platform_container-0.0.3.dist-info/entry_points.txt +5 -0
- idmtools_platform_container-0.0.3.dist-info/licenses/LICENSE.TXT +3 -0
- {idmtools_platform_container-0.0.0.dev0.dist-info → idmtools_platform_container-0.0.3.dist-info}/top_level.txt +2 -0
- tests/inputs/Assets/MyLib/functions.py +2 -0
- tests/inputs/__init__.py +0 -0
- tests/inputs/model.py +28 -0
- tests/inputs/model1.py +31 -0
- tests/inputs/model3.py +21 -0
- tests/inputs/model_file.py +18 -0
- tests/inputs/run.sh +1 -0
- tests/inputs/sleep.py +9 -0
- tests/test_container_cli/__init__.py +0 -0
- tests/test_container_cli/helper.py +57 -0
- tests/test_container_cli/test_base.py +14 -0
- tests/test_container_cli/test_cancel.py +96 -0
- tests/test_container_cli/test_clear_results.py +54 -0
- tests/test_container_cli/test_container.py +72 -0
- tests/test_container_cli/test_file_container_cli.py +121 -0
- tests/test_container_cli/test_get_detail.py +60 -0
- tests/test_container_cli/test_history.py +136 -0
- tests/test_container_cli/test_history_count.py +53 -0
- tests/test_container_cli/test_inspect.py +53 -0
- tests/test_container_cli/test_install.py +48 -0
- tests/test_container_cli/test_is_running.py +69 -0
- tests/test_container_cli/test_jobs.py +138 -0
- tests/test_container_cli/test_list_containers.py +99 -0
- tests/test_container_cli/test_packages.py +41 -0
- tests/test_container_cli/test_path.py +96 -0
- tests/test_container_cli/test_ps.py +47 -0
- tests/test_container_cli/test_remove_container.py +78 -0
- tests/test_container_cli/test_status.py +149 -0
- tests/test_container_cli/test_stop_container.py +71 -0
- tests/test_container_cli/test_sync_history.py +98 -0
- tests/test_container_cli/test_verify_docker.py +28 -0
- tests/test_container_cli/test_volume.py +28 -0
- idmtools_platform_container-0.0.0.dev0.dist-info/METADATA +0 -41
- idmtools_platform_container-0.0.0.dev0.dist-info/RECORD +0 -5
- {idmtools_platform_container-0.0.0.dev0.dist-info → idmtools_platform_container-0.0.3.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.0
|
docker_image/Dockerfile
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# FROM docker-production.packages.idmod.org/dtk-rocky-buildenv:0.2-dev
|
|
2
|
+
# Replace the following lines with above line after the offical image is available
|
|
3
|
+
#############################################################
|
|
4
|
+
FROM rockylinux:9.2
|
|
5
|
+
# Set the timezone and the frontend
|
|
6
|
+
ENV TZ=UTC DEBIAN_FRONTEND=noninteractive
|
|
7
|
+
# To suppress warning without altering the installation when pip install with root user
|
|
8
|
+
ENV PIP_ROOT_USER_ACTION=ignore
|
|
9
|
+
# Install the necessary packages
|
|
10
|
+
RUN yum -y install rpm dnf-plugins-core \
|
|
11
|
+
&& yum -y update \
|
|
12
|
+
&& dnf -y install \
|
|
13
|
+
python3 \
|
|
14
|
+
python3-devel \
|
|
15
|
+
mpich \
|
|
16
|
+
snappy \
|
|
17
|
+
glibc-devel \
|
|
18
|
+
epel-release \
|
|
19
|
+
wget \
|
|
20
|
+
nano
|
|
21
|
+
|
|
22
|
+
# Update the system
|
|
23
|
+
RUN yum clean all
|
|
24
|
+
|
|
25
|
+
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone # This is for setting up the timezone
|
|
26
|
+
|
|
27
|
+
# Install pip
|
|
28
|
+
RUN python3 -m pip install pip --upgrade
|
|
29
|
+
# Create a symbolic link to python3
|
|
30
|
+
RUN ln -s /usr/bin/python3 /usr/bin/python
|
|
31
|
+
# Create a directory for pip configurations
|
|
32
|
+
RUN mkdir /root/.pip
|
|
33
|
+
# Copy the pip configuration file
|
|
34
|
+
COPY pip.conf /root/.pip
|
|
35
|
+
|
|
36
|
+
# Set the path and library path
|
|
37
|
+
ENV PATH ${PATH}:/usr/lib64/mpich/bin
|
|
38
|
+
ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:/usr/lib64/mpich/lib
|
|
39
|
+
|
|
40
|
+
# Add the requirements file
|
|
41
|
+
ADD requirements.txt /tmp/
|
|
42
|
+
|
|
43
|
+
# make the PIP index configurable so we can build against staging, production, or a local PyPI server
|
|
44
|
+
ARG CONTAINER_VERSION
|
|
45
|
+
|
|
46
|
+
# Install the packages
|
|
47
|
+
RUN bash -c "pip3 install -r /tmp/requirements.txt"
|
|
48
|
+
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#FROM docker-production.packages.idmod.org/dtk-rocky-buildenv:0.2-dev
|
|
2
|
+
# Replace the following lines with above line after the offical image is available
|
|
3
|
+
#############################################################
|
|
4
|
+
FROM rockylinux:9.2
|
|
5
|
+
ENV TZ=UTC DEBIAN_FRONTEND=noninteractive
|
|
6
|
+
ENV GNUMAKEFLAGS=-j4
|
|
7
|
+
|
|
8
|
+
RUN yum -y install rpm dnf-plugins-core \
|
|
9
|
+
&& yum -y update \
|
|
10
|
+
&& dnf -y install \
|
|
11
|
+
python3 \
|
|
12
|
+
python3-devel \
|
|
13
|
+
snappy \
|
|
14
|
+
mpich \
|
|
15
|
+
sudo \
|
|
16
|
+
epel-release \
|
|
17
|
+
git \
|
|
18
|
+
wget \
|
|
19
|
+
nano
|
|
20
|
+
|
|
21
|
+
RUN yum -y update
|
|
22
|
+
RUN yum -y group install "Development Tools" \
|
|
23
|
+
&& yum clean all
|
|
24
|
+
|
|
25
|
+
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone # This is for setting up the timezone
|
|
26
|
+
|
|
27
|
+
RUN python3 -m pip install pip --upgrade
|
|
28
|
+
RUN ln -s /usr/bin/python3 /usr/bin/python
|
|
29
|
+
RUN mkdir /root/.pip
|
|
30
|
+
COPY pip.conf /root/.pip
|
|
31
|
+
# RUN dnf install -y R
|
|
32
|
+
ENV PATH ${PATH}:/usr/lib64/mpich/bin
|
|
33
|
+
ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:/usr/lib64/mpich/lib
|
|
34
|
+
|
|
35
|
+
#############################################################
|
|
36
|
+
RUN dnf -y install dos2unix
|
|
37
|
+
|
|
38
|
+
# Add the requirements file
|
|
39
|
+
ADD requirements.txt /tmp/
|
|
40
|
+
|
|
41
|
+
# make the PIP index configurable so we can build against staging, production, or a local PyPI server
|
|
42
|
+
ARG CONTAINER_VERSION
|
|
43
|
+
|
|
44
|
+
# Install the packages
|
|
45
|
+
RUN bash -c "pip3 install -r /tmp/requirements.txt"
|
|
46
|
+
|
docker_image/ImageName
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
container-rocky-runtime
|
docker_image/README.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
2
|
+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
3
|
+
**Table of Contents**
|
|
4
|
+
|
|
5
|
+
- [idmtools_platform_container Docker image](#idmtools_platform_container-docker-image)
|
|
6
|
+
- [Introduction](#introduction)
|
|
7
|
+
- [Prerequisites](#prerequisites)
|
|
8
|
+
- [Build Docker image](#build-docker-image)
|
|
9
|
+
- [Docker image versioning](#docker-image-versioning)
|
|
10
|
+
- [Docker image usage](#docker-image-usage)
|
|
11
|
+
- [Publish Docker image](#publish-docker-image)
|
|
12
|
+
- [Extend the Docker image](#extend-the-docker-image)
|
|
13
|
+
|
|
14
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
15
|
+
|
|
16
|
+
# idmtools_platform_container Docker image
|
|
17
|
+
|
|
18
|
+
**Note**: This document is primarily for developers. It is not necessary for users to build and push the Docker image. However, if you wish to use your own Docker image, please follow the instructions below at [Extend the Docker Image](#extend-the-docker-image).
|
|
19
|
+
|
|
20
|
+
## Introduction
|
|
21
|
+
This Docker image is designed to facilitate idmtools_platform_container. It serves as local running platform with all necessary tools and dependencies installed. The image is based on rockylinux 9.2 and includes the following tools:
|
|
22
|
+
- python 3.9
|
|
23
|
+
- mipch 4.1.1
|
|
24
|
+
- emod-api 1.33.3
|
|
25
|
+
- emod-api's dependencies like numpy, pandas, scipy, matplotlib etc.
|
|
26
|
+
|
|
27
|
+
## Prerequisites
|
|
28
|
+
- Docker
|
|
29
|
+
On Windows or Mac, please use Docker Desktop 2.1.0.5 or 2.2.0.1
|
|
30
|
+
|
|
31
|
+
## Build Docker image
|
|
32
|
+
Note, you do not need to build the image locally. The image is auto built in github action and pushed to idmod artifactory.
|
|
33
|
+
|
|
34
|
+
To build Docker image locally, run:
|
|
35
|
+
```bash
|
|
36
|
+
python build_docker_image.py --username <username> --password <password>
|
|
37
|
+
```
|
|
38
|
+
where `<username>` and `<password>` are the username and password for the idmod artifactory account.
|
|
39
|
+
|
|
40
|
+
You can also build the image with different docker file and image name by specifying `--dockerfile` and `--image_name` arguments.
|
|
41
|
+
```bash
|
|
42
|
+
python build_docker_image.py --username <username> --password <password> --dockerfile Dockerfile_buildenv --image_name container-rocky-buildenv
|
|
43
|
+
```
|
|
44
|
+
which will build image name as 'idm-docker-staging.packages.idmod.org/idmtools/container-rocky-buildenv:x.x.x'
|
|
45
|
+
|
|
46
|
+
## Docker image versioning
|
|
47
|
+
The Docker image version is determined by the version in idm docker-staging artifactory. It will advance the version number by 0.0.1 for each new build.
|
|
48
|
+
|
|
49
|
+
## Docker image usage
|
|
50
|
+
By default, you DO NOT need to worry about the image build and how to use image. The image is auto built in github action and pushed to idmod artifactory. The image is used in idmtools_platform_container Platform object. For example,
|
|
51
|
+
```python
|
|
52
|
+
from idmtools.core.platform_factory import Platform
|
|
53
|
+
platform = Platform('CONTAINER', job_directory='any_dir', docker_image='idm-docker-public.packages.idmod.org/idmtools/container-rocky-runtime:x.x.x')
|
|
54
|
+
```
|
|
55
|
+
where docker_image can be your local built image or the image in idmod artifactory.
|
|
56
|
+
If you do not provide docker_image, the default image will be used.
|
|
57
|
+
|
|
58
|
+
## Publish Docker image
|
|
59
|
+
Note, you do not need to push docker image to artifactory. The image is auto built in github action and pushed to idmod artifactory.
|
|
60
|
+
If you want to push the image to artifactory, run:
|
|
61
|
+
```bash
|
|
62
|
+
python push_docker_image.py --username <username> --password <password>
|
|
63
|
+
```
|
|
64
|
+
where `<username>` and `<password>` are the username and password for the idmod artifactory account.
|
|
65
|
+
|
|
66
|
+
## Extend the Docker image
|
|
67
|
+
If you want to build you own Docker image, please use our ``container-rocky-runtime`` as your baseline image and add the following line to the top of your Dockerfile:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
FROM docker-production-public/idmtools/container-rocky-runtime/0.0.3
|
|
71
|
+
```
|
|
72
|
+
You can use general Docker build [command](https://docs.docker.com/reference/cli/docker/buildx/build/) to build your own Docker image.
|
|
73
|
+
Then use that image in the Platform object. For example:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
from idmtools_platform_container import Platform
|
|
77
|
+
platform = Platform('CONTAINER', job_directory='any_dir', docker_image='your_own_image_name:x.x.x')
|
|
78
|
+
```
|
docker_image/__init__.py
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""This script is used to build a docker image for the idmtools_platform_container.
|
|
2
|
+
|
|
3
|
+
Copyright 2024, Bill Gates Foundation. All rights reserved.
|
|
4
|
+
"""
|
|
5
|
+
import argparse
|
|
6
|
+
import os
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
import requests
|
|
10
|
+
import keyring
|
|
11
|
+
from logging import getLogger, basicConfig, DEBUG, INFO
|
|
12
|
+
from getpass import getpass
|
|
13
|
+
from requests.auth import HTTPBasicAuth
|
|
14
|
+
from natsort import natsorted
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
logger = getLogger(__name__)
|
|
18
|
+
# Global Configurations
|
|
19
|
+
KEYRING_NAME = "idmtools_container_docker_builder"
|
|
20
|
+
BASE_REPO = 'packages.idmod.org'
|
|
21
|
+
REPO_KEY = 'idm-docker-staging'
|
|
22
|
+
DOCKER_REPO = f'{REPO_KEY}.{BASE_REPO}'
|
|
23
|
+
BASE_IMAGE_NAME = f'{DOCKER_REPO}/idmtools'
|
|
24
|
+
current_working_directory = os.getcwd()
|
|
25
|
+
BASE_VERSION = open(os.path.join(current_working_directory, 'BASE_VERSION')).read().strip()
|
|
26
|
+
|
|
27
|
+
logger.info("Please be sure you are logged into the docker-production.packages.idmod.org Docker Repo")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_username_and_password(disable_keyring_load=False, disable_keyring_save=False):
|
|
31
|
+
"""
|
|
32
|
+
Try to get username.
|
|
33
|
+
|
|
34
|
+
It first attempts loading from environment vars, then keyring if not disabled, then lastly prompts.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
disable_keyring_load: Disable loading credentials from keyring
|
|
38
|
+
disable_keyring_save: Disable keyring save
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
Username password
|
|
42
|
+
"""
|
|
43
|
+
if 'PYPI_STAGING_USERNAME' in os.environ:
|
|
44
|
+
logger.info("Loading Credentials from environment")
|
|
45
|
+
if 'PYPI_STAGING_PASSWORD' not in os.environ:
|
|
46
|
+
logger.error("When specifying username from environment variable, you must also specify password")
|
|
47
|
+
sys.exit(-1)
|
|
48
|
+
username = os.environ['PYPI_STAGING_USERNAME']
|
|
49
|
+
password = os.environ['PYPI_STAGING_PASSWORD']
|
|
50
|
+
elif not disable_keyring_load and keyring.get_credential(KEYRING_NAME, "username"):
|
|
51
|
+
username = keyring.get_password(KEYRING_NAME, "username")
|
|
52
|
+
password = keyring.get_password(KEYRING_NAME, "password")
|
|
53
|
+
else:
|
|
54
|
+
username = input('Username:')
|
|
55
|
+
password = getpass(prompt='Password:')
|
|
56
|
+
if not disable_keyring_save:
|
|
57
|
+
logger.info("Saving Credentials")
|
|
58
|
+
keyring.set_password(KEYRING_NAME, "username", username)
|
|
59
|
+
keyring.set_password(KEYRING_NAME, "password", password)
|
|
60
|
+
return username, password
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def get_latest_image_version_from_registry(username, password, image_name):
|
|
64
|
+
"""
|
|
65
|
+
Fetch the latest image version from repo.
|
|
66
|
+
Args:
|
|
67
|
+
username: Username to use with registry
|
|
68
|
+
password: Password to use with registry
|
|
69
|
+
image_name: Docker image name to use for building image
|
|
70
|
+
Returns:
|
|
71
|
+
Latest version published in the registry
|
|
72
|
+
"""
|
|
73
|
+
url = f'https://{BASE_REPO}/artifactory/api/docker/{REPO_KEY}/v2/idmtools/{image_name}/tags/list'
|
|
74
|
+
auth = HTTPBasicAuth(username=username, password=password)
|
|
75
|
+
logger.info(f"Loading Credentials from {url}")
|
|
76
|
+
response = requests.get(url, auth=auth)
|
|
77
|
+
logger.debug(f"Return Code: {response.status_code}")
|
|
78
|
+
if response.status_code != 200 and response.status_code != 404:
|
|
79
|
+
print(response.status_code)
|
|
80
|
+
print(response.content)
|
|
81
|
+
raise Exception('Could not load images')
|
|
82
|
+
elif response.status_code == 404:
|
|
83
|
+
logger.info(f"First Version {url}")
|
|
84
|
+
return f'{BASE_VERSION}.0'
|
|
85
|
+
else:
|
|
86
|
+
images = natsorted(response.json()['tags'], reverse=True)
|
|
87
|
+
images = [i for i in images if len(i) >= 5]
|
|
88
|
+
logger.debug(f"Images: {images}")
|
|
89
|
+
last_version = images[0]
|
|
90
|
+
logger.info(f"Last Version {url}")
|
|
91
|
+
version_parts = last_version.split('.')
|
|
92
|
+
base_part = '.'.join(version_parts[:-1])
|
|
93
|
+
if BASE_VERSION in base_part:
|
|
94
|
+
version_parts[-1] = str(int(version_parts[-1]) + 1)
|
|
95
|
+
version = '.'.join(version_parts)
|
|
96
|
+
else:
|
|
97
|
+
version = f'{BASE_VERSION}.0'
|
|
98
|
+
logger.info(f"Next Version: {version}")
|
|
99
|
+
return version
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def build_image(username, password, dockerfile, image_name, disable_keyring_load, disable_keyring_save):
|
|
103
|
+
"""
|
|
104
|
+
Run the docker build command.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
username: Username to use with registry
|
|
108
|
+
password: Password to use with registry
|
|
109
|
+
dockerfile: Dockerfile to use for building image
|
|
110
|
+
image_name: Docker image name to use for building image
|
|
111
|
+
disable_keyring_load: Disable keyring which caches passwords
|
|
112
|
+
disable_keyring_save: Disable caching password to the keyring
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
None
|
|
116
|
+
"""
|
|
117
|
+
if username is None or password is None:
|
|
118
|
+
username, password = get_username_and_password(disable_keyring_load, disable_keyring_save)
|
|
119
|
+
version = get_latest_image_version_from_registry(username, password, image_name)
|
|
120
|
+
cmd = ['docker', 'build', '--network=host', '--build-arg', f'CONTAINER_VERSION={version}', '--tag',
|
|
121
|
+
f'{BASE_IMAGE_NAME}/{image_name}:{version}', '-f', dockerfile, '.']
|
|
122
|
+
logger.info(f'Running: {" ".join(cmd)}')
|
|
123
|
+
p = subprocess.Popen(" ".join(cmd), cwd=current_working_directory, shell=True)
|
|
124
|
+
p.wait()
|
|
125
|
+
|
|
126
|
+
if p.returncode == 0:
|
|
127
|
+
logger.info("Tagging image")
|
|
128
|
+
os.system(f'docker tag {BASE_IMAGE_NAME}/{image_name}:{version} {BASE_IMAGE_NAME}/{image_name}:{version[:-2]}')
|
|
129
|
+
sys.exit(p.returncode)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
if __name__ == "__main__":
|
|
133
|
+
parser = argparse.ArgumentParser("Build Container Image")
|
|
134
|
+
parser.add_argument("--username", default=None, help="Docker Production Username")
|
|
135
|
+
parser.add_argument("--password", default=None, help="Docker Production Password")
|
|
136
|
+
parser.add_argument("--dockerfile", default="Dockerfile", help="Dockerfile to use for building image")
|
|
137
|
+
parser.add_argument("--image_name", default="container-rocky-runtime", help="image name to use for building image")
|
|
138
|
+
parser.add_argument("--disable-keyring-load", default=False, help="Disable loading password from keyring")
|
|
139
|
+
parser.add_argument("--disable-keyring-save", default=False, help="Disable saving password to keyring after user prompts")
|
|
140
|
+
parser.add_argument("--verbose", default=False, help="Enable Debug logging")
|
|
141
|
+
parser.add_argument("--debug", default=False, help="Enable Debug logging")
|
|
142
|
+
args = parser.parse_args()
|
|
143
|
+
|
|
144
|
+
basicConfig(filename="build.log", level=DEBUG if any([args.verbose, args.debug]) else INFO)
|
|
145
|
+
build_image(args.username, args.password, args.dockerfile, args.image_name, args.disable_keyring_load, args.disable_keyring_save)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.0
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
FROM debian:12.6
|
|
2
|
+
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
|
|
3
|
+
|
|
4
|
+
RUN set -x && \
|
|
5
|
+
apt-get update --fix-missing && \
|
|
6
|
+
apt-get install -y --no-install-recommends \
|
|
7
|
+
python3 \
|
|
8
|
+
python3-pip \
|
|
9
|
+
python3-dev \
|
|
10
|
+
python3-venv \
|
|
11
|
+
mpich \
|
|
12
|
+
wget \
|
|
13
|
+
nano \
|
|
14
|
+
&& apt-get clean \
|
|
15
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
16
|
+
|
|
17
|
+
# Update the system
|
|
18
|
+
RUN apt-get clean
|
|
19
|
+
|
|
20
|
+
RUN mkdir /root/.pip
|
|
21
|
+
# Copy the pip configuration file
|
|
22
|
+
COPY pip.conf /root/.pip
|
|
23
|
+
|
|
24
|
+
# Set up a virtual environment
|
|
25
|
+
RUN python3 -m venv /pyenv
|
|
26
|
+
ENV PATH="/pyenv/bin:$PATH"
|
|
27
|
+
|
|
28
|
+
RUN pip3 install --upgrade pip setuptools
|
|
29
|
+
# Add the requirements file
|
|
30
|
+
ADD requirements.txt /tmp/
|
|
31
|
+
# Install the packages
|
|
32
|
+
RUN pip3 install -r /tmp/requirements.txt
|
|
33
|
+
|
|
34
|
+
RUN ln -s /usr/bin/python3 /usr/bin/python
|
|
35
|
+
|
|
36
|
+
ARG CONTAINER_VERSION
|
|
37
|
+
|
|
38
|
+
ENV LD_LIBRARY_PATH /usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH}
|
|
39
|
+
|
|
40
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
container-debian-runtime
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
2
|
+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
3
|
+
**Table of Contents**
|
|
4
|
+
|
|
5
|
+
- [Debian12 Docker Image](#debian12-docker-image)
|
|
6
|
+
- [Introduction](#introduction)
|
|
7
|
+
- [Prerequisites](#prerequisites)
|
|
8
|
+
- [Build Docker Image locally](#build-docker-image-locally)
|
|
9
|
+
- [Use docker image in idmtools](#use-docker-image-in-idmtools)
|
|
10
|
+
- [Build and Publish Debian Docker Image in GitHub Actions](#build-and-publish-debian-docker-image-in-github-actions)
|
|
11
|
+
|
|
12
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
13
|
+
|
|
14
|
+
# Debian12 Docker Image
|
|
15
|
+
|
|
16
|
+
## Introduction
|
|
17
|
+
This Docker image is designed to facilitate idmtools_platform_container. It serves as local running platform with all necessary tools and dependencies installed.
|
|
18
|
+
|
|
19
|
+
The image built from this Dockerfile is based on debian:12 docker image and includes the following packages and utilities:
|
|
20
|
+
- python 3.11
|
|
21
|
+
- mipch 4.0.2
|
|
22
|
+
- emod-api 2.0.1
|
|
23
|
+
|
|
24
|
+
## Prerequisites
|
|
25
|
+
- Docker
|
|
26
|
+
|
|
27
|
+
## Build Docker Image locally
|
|
28
|
+
```bash
|
|
29
|
+
docker build -t debian12-env:0.0.1 .
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Use docker image in idmtools
|
|
33
|
+
```python
|
|
34
|
+
from idmtools.core.platform_factory import Platform
|
|
35
|
+
platform = Platform('CONTAINER', docker_image='debian12-env:0.0.1')
|
|
36
|
+
```
|
|
37
|
+
Note, here `debian12-env:0.0.1` is the image name you built in the previous step.
|
|
38
|
+
|
|
39
|
+
If your script needs extra python packages, you can install with extra_packages argument in Platform at runtime:
|
|
40
|
+
```python
|
|
41
|
+
from idmtools.core.platform_factory import Platform
|
|
42
|
+
platform = Platform('CONTAINER', docker_image='debian12-env', extra_packages=['emodpy~=2.0.0', 'pytest'])
|
|
43
|
+
|
|
44
|
+
# or use idmtools cli command to install before run script: idmtools container install <package>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Build and Publish Debian Docker Image in GitHub Actions
|
|
48
|
+
You can build and publish the docker image to idmod artifactory using GitHub Actions. The script is located at `.github/workflows/build_debian_image.yml`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
emod-api~=2.0.1
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""This script fetches the history of a Docker image and prints it in a tabular format."""
|
|
2
|
+
import argparse
|
|
3
|
+
import re
|
|
4
|
+
import shutil
|
|
5
|
+
import subprocess
|
|
6
|
+
import pandas as pd
|
|
7
|
+
from tabulate import tabulate
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def parse_size(size_str):
|
|
11
|
+
"""
|
|
12
|
+
Parse the size string from Docker and convert to bytes.
|
|
13
|
+
Args:
|
|
14
|
+
size_str:
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
Size in bytes
|
|
18
|
+
"""
|
|
19
|
+
"""Parse the size string from Docker and convert to bytes."""
|
|
20
|
+
units = {'B': 1, 'KB': 1024, 'MB': 1024**2, 'GB': 1024**3}
|
|
21
|
+
size_str = size_str.upper().replace(" ", "")
|
|
22
|
+
num, unit = re.findall(r'([0-9.]+)([A-Z]+)', size_str)[0]
|
|
23
|
+
return float(num) * units.get(unit, 1)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def format_size(size_in_bytes):
|
|
27
|
+
"""
|
|
28
|
+
Convert a size in bytes to a human-readable string of the most appropriate unit.
|
|
29
|
+
Args:
|
|
30
|
+
size_in_bytes:
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
Size in human-readable format
|
|
34
|
+
"""
|
|
35
|
+
if size_in_bytes < 1024:
|
|
36
|
+
return f"{size_in_bytes} B" # Bytes
|
|
37
|
+
elif size_in_bytes < 1024**2:
|
|
38
|
+
return f"{size_in_bytes / 1024:.2f} KB" # Kilobytes
|
|
39
|
+
elif size_in_bytes < 1024**3:
|
|
40
|
+
return f"{size_in_bytes / 1024**2:.2f} MB" # Megabytes
|
|
41
|
+
elif size_in_bytes < 1024**4:
|
|
42
|
+
return f"{size_in_bytes / 1024**3:.2f} GB" # Gigabytes
|
|
43
|
+
else:
|
|
44
|
+
return f"{size_in_bytes / 1024**4:.2f} TB" # Terabytes
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def get_docker_image_history(image_id_or_name):
|
|
48
|
+
"""
|
|
49
|
+
Fetch the history of a Docker image.
|
|
50
|
+
Args:
|
|
51
|
+
image_id_or_name:
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
df
|
|
55
|
+
"""
|
|
56
|
+
result = subprocess.run(
|
|
57
|
+
['docker', 'history', '--no-trunc', image_id_or_name, '--format', '{{.ID}}|{{.CreatedBy}}|{{.Size}}'],
|
|
58
|
+
capture_output=True,
|
|
59
|
+
text=True,
|
|
60
|
+
encoding='utf-8'
|
|
61
|
+
)
|
|
62
|
+
if result.returncode != 0:
|
|
63
|
+
print("Error fetching Docker image history")
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
history_lines = result.stdout.strip().split('\n')
|
|
67
|
+
data = [line.split('|') for line in history_lines]
|
|
68
|
+
for i, line in enumerate(data):
|
|
69
|
+
if len(line) == 4:
|
|
70
|
+
data[i] = [line[0], line[1] + " " + line[2], line[3]]
|
|
71
|
+
df = pd.DataFrame(data, columns=['LAYER ID', 'COMMAND', 'SIZE'])
|
|
72
|
+
df = df.iloc[:, -2:]
|
|
73
|
+
return df
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def main(image_id):
|
|
77
|
+
"""
|
|
78
|
+
This script fetches the history of a Docker image and prints it in a tabular format.
|
|
79
|
+
Returns:
|
|
80
|
+
None
|
|
81
|
+
"""
|
|
82
|
+
df = get_docker_image_history(image_id)
|
|
83
|
+
total_size = sum(parse_size(size) for size in df['SIZE'])
|
|
84
|
+
size = format_size(total_size)
|
|
85
|
+
if df is not None:
|
|
86
|
+
terminal_width = shutil.get_terminal_size().columns
|
|
87
|
+
max_command_width = terminal_width - 10
|
|
88
|
+
table = tabulate(df, headers='keys', tablefmt='fancy_grid', showindex=False,
|
|
89
|
+
maxcolwidths=[None, max_command_width, None])
|
|
90
|
+
print(table)
|
|
91
|
+
with open('rocky_meta_runtime.txt', 'w', encoding='utf-8') as outputfile:
|
|
92
|
+
outputfile.write(f"Total size: {size}\n\n")
|
|
93
|
+
outputfile.write(table)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
if __name__ == "__main__":
|
|
97
|
+
if __name__ == "__main__":
|
|
98
|
+
parser = argparse.ArgumentParser("Get Image Build History")
|
|
99
|
+
parser.add_argument("--image_id", default="10bed3221522", help="Docker image id")
|
|
100
|
+
args = parser.parse_args()
|
|
101
|
+
main(args.image_id)
|
docker_image/pip.conf
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""This is the script to push docker image to idm staging artifactory.
|
|
2
|
+
|
|
3
|
+
Copyright 2024, Bill Gates Foundation. All rights reserved.
|
|
4
|
+
"""
|
|
5
|
+
import argparse
|
|
6
|
+
import os
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
from logging import getLogger, basicConfig, DEBUG, INFO
|
|
10
|
+
current_directory = os.path.dirname(os.path.realpath(__file__))
|
|
11
|
+
sys.path.append(os.path.join(current_directory))
|
|
12
|
+
from build_docker_image import get_username_and_password, get_latest_image_version_from_registry # noqa: E402
|
|
13
|
+
|
|
14
|
+
current_working_directory = os.getcwd()
|
|
15
|
+
BASE_VERSION = open(os.path.join(current_working_directory, 'BASE_VERSION')).read().strip()
|
|
16
|
+
BASE_REPO = 'packages.idmod.org'
|
|
17
|
+
REPO_KEY = 'idm-docker-staging'
|
|
18
|
+
DOCKER_REPO = f'{REPO_KEY}.{BASE_REPO}'
|
|
19
|
+
BASE_IMAGE_NAME = f'{DOCKER_REPO}/idmtools'
|
|
20
|
+
|
|
21
|
+
logger = getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def push_image(username, password, dockerfile, image_name, disable_keyring_load, disable_keyring_save):
|
|
25
|
+
"""
|
|
26
|
+
Push docker image to idm staging artifactory.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
username: Username to use with registry
|
|
30
|
+
password: Password to use with registry
|
|
31
|
+
dockerfile: Dockerfile to use for building image
|
|
32
|
+
image_name: Docker image name to use for building image
|
|
33
|
+
disable_keyring_load: Disable keyring which caches passwords
|
|
34
|
+
disable_keyring_save: Disable caching password to the keyring
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
None
|
|
38
|
+
"""
|
|
39
|
+
if username is None or password is None:
|
|
40
|
+
username, password = get_username_and_password(disable_keyring_load, disable_keyring_save)
|
|
41
|
+
version = get_latest_image_version_from_registry(username, password, image_name)
|
|
42
|
+
cmd = ['docker', 'push', f'{BASE_IMAGE_NAME}/{image_name}:{version}']
|
|
43
|
+
print(f'Running: {" ".join(cmd)}')
|
|
44
|
+
p = subprocess.Popen(" ".join(cmd), cwd=current_working_directory, shell=True)
|
|
45
|
+
p.wait()
|
|
46
|
+
sys.exit(p.returncode)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
if __name__ == "__main__":
|
|
50
|
+
parser = argparse.ArgumentParser("Publish Container Image to Artifactory")
|
|
51
|
+
parser.add_argument("--username", default=None, help="Docker Staging Username")
|
|
52
|
+
parser.add_argument("--password", default=None, help="Docker Staging Password")
|
|
53
|
+
parser.add_argument("--dockerfile", default="Dockerfile", help="Dockerfile to use for building image")
|
|
54
|
+
parser.add_argument("--image_name", default="container-rocky-runtime", help="image name to use for building image")
|
|
55
|
+
parser.add_argument("--disable-keyring-load", default=False, help="Disable loading password from keyring")
|
|
56
|
+
parser.add_argument("--disable-keyring-save", default=False, help="Disable saving password to keyring after user prompts")
|
|
57
|
+
parser.add_argument("--verbose", default=False, help="Enable Debug logging")
|
|
58
|
+
parser.add_argument("--debug", default=False, help="Enable Debug logging")
|
|
59
|
+
args = parser.parse_args()
|
|
60
|
+
|
|
61
|
+
basicConfig(filename="build.log", level=DEBUG if any([args.verbose, args.debug]) else INFO)
|
|
62
|
+
push_image(args.username, args.password, args.dockerfile, args.image_name, args.disable_keyring_load, args.disable_keyring_save)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
emod-api~=1.30
|