After an image repository has been configured, you can start building your own image. The basis is always its blueprint: The Dockerfile. It is created on the local computer (e.g. a developer notebook) and serves as input for the so-called build process, which generates the final image. The Docker documentation contains extensive introductions to the topic.
In the first step, the base image is selected and defined in the Dockerfile as the base of the own image using the FROM command. The “Name” column shows the path to the images we have stored at Docker Hub.
Afterwards, the image can be designed by arbitrary Dockerfile commands along the own requirements and e.g. additional packages can be installed via RUN command. Especially important is the process that starts the container at runtime and is defined as CMD in the Dockerfile. The /run.sh script of the selected ExaMesh base image can serve as inspiration. To check its content, the instance is first started with one of our base images and then observed via SSH login:
# inside an examesh instance (ssh session in your console)
# examesh container are started by running /run.sh
# the last /run.sh command starts the openssh server
instance0$ cat /run.sh
exec /usr/sbin/sshd -D -e -f /etc/ssh/sshd_config
# listing of container processes shows this openssh server
instance0$ ps ax -o command=
sshd -D -e -f /etc/ssh/sshd_config
# this image includes also the nvidia module
instance0$ cat /proc/driver/nvidia/version
NVRM version: NVIDIA UNIX x86_64 Kernel Module 440.33.01 ...
GCC version: gcc version 8.3.0 (Debian 8.3.0-6)
In the following specific example, the examesh/cuda-base:10.2-0.1.0 image available for AI instances in September 2021 is used as the FROM base and the run.sh script shown is defined as a CMD. It starts the desired processes in the container at runtime and thus fills the available endpoints of the instance with life.
# using developer notebook (local console)
notebook$ cd ~/my_image_build_folder
# this run.sh will be copied to image and start container processes
notebook$ cat run.sh
# an example for a command that starts your container application:
# - this must be a process that runs in the background,
# e.g. by using shell's "&" builtin
# - if you start a webservice (e.g. python flask or jupyter) it must
# listen on tcp port 80 and use the http (not https) protocol
#python /app/main.py & # start a python app
# command that starts the ssh daemon included in the image:
# - this is the last command, so it MUST run in the foreground
# or container will terminate immediately after startup
# - sshd must listen on tcp port 22 (what is the default)
exec /usr/sbin/sshd -D -e -f /etc/ssh/sshd_config # man sshd
notebook$ cat Dockerfile
# examesh image as base that includes cuda and python
# (docker build process will download the image from docker-hub)
# use COPY, RUN etc. to install your data and packages
# copy run.sh into image and define it as container entry command
COPY run.sh /usr/local/bin/run.sh
CMD ["bash", "/usr/local/bin/run.sh"]
After creating Dockerfile and run.sh, the build process can be started. Important for the later required storage in Docker Hub (or another registry) is the naming (tagging) of the image. In this example, the username foo already used in the image repository section is used. The new image is tagged with this prefix during the build call and then uploaded to Docker Hub.
# developer notebook
notebook$ cd ~/my_image_build_folder
# build image named "cuda" for docker hub user "foo"
notebook$ docker build --tag foo/cuda:latest ./
# push image to docker hub
notebook$ docker image push foo/cuda:latest
The image is now stored in a (private or public) Docker Hub repository. Assuming the previous registry setup, it can now be used to launch an ExaMesh instance.