- Install Docker (Locally, Linux, ...)
- Building a Docker Image
- Docker Image and Singularity
- Development in Remote Docker Containers TBD
Follow the tutorial to install on your machine:
- Linux - https://docs.docker.com/engine/install/ubuntu/,
- Windows Docker Desktop - https://docs.docker.com/desktop/install/windows-install/
- Windows WSL2: https://techcommunity.microsoft.com/t5/windows-11/how-to-install-the-linux-windows-subsystem-in-windows-11/m-p/2701207
- Macintosh: https://docs.docker.com/desktop/install/mac-install/
Use existing installation on one of the servers: bea.zel.lo, or abacus1.zel.lo, or jane.zel.lo, ask system admin for group permissions. For complete server names checkout the department wiki pages http://zel.irb.hr/wiki/tutorials:supercomputers.
At what point are docker and singularity commands applied and what do they create.
Docker images are located online on docker hub repository. After logging in, you can upload your image as well. In order to create an image we use Dockerfile and a set of standard commands.
Docker image is the first step to create your fully reproducible environment. Basic setup is by using Dockerfile
.
- Dockerfile contains procedure/code to build a docker image, minimal dockerfile examples are in repository,
- cuda > 11.3 doesnt work on srce based on documentation (check) and cuda > 11.6 doesn't work on orthus our
- Understanding the Dockerfile syntax and commands:
# # is the comment character
# FROM: Specifies the base image for the Dockerfile.
FROM <image>[:<tag>] [AS <name>] # e.g. rstudio/rstudio-server-pro:1.2.5033-1, or pytorch/pytorch:2.2.2-cuda12.1-cudnn8-devel
# cuda > 11.3 doesnt work on srce based on documentation (check) and cuda > 11.6 doesn't work on orthus
# ARG: Arguments from the "docker build ..." command
# Or some other arguments you need for Dockerfile build
ARG USER_ID
ARG GROUP_ID
# RUN: Executes commands in the Docker image. Makes image snapshot.
RUN <command>
# COPY: Copies files or directories from the host into the Docker image.
COPY <src> <dest>
# WORKDIR: Sets the working directory for subsequent instructions.
WORKDIR /path/to/directory
# CMD: Specifies the default command to run when the container starts.
CMD ["executable", "param1", "param2"]
# ENTRYPOINT: Specifies the command to run when the container starts, which cannot be overridden by CMD.
ENTRYPOINT ["executable", "param1", "param2"]
# ENV: Sets environment variables in the Docker image.
ENV <key> <value>
...
docker build ...
--> change : (:) to something to make the image recognizable, e.g. smith/gpu:ver1, creates builds the image from Dockerfile:
docker build -t <ime>:<verzija> --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g) .
docker run ...
--> creates a container ~ virtual machine, opens linux terminal:
docker run -it --rm --user $(id -u):$(id -g) <ime>:<verzija> /bin/bash
docker exec ...
existing container terminal:
docker exec -u $(id -u) -g $(id -g) -it rm <container_id_or_name> bash
Flags used for this initial example were in docker build ...
flags used:
-t
tag the image with : in thedocker images
table the columns REPOSITORY will display and TAG will display , use something to recognize your images.--build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g)
send your server user id and group id to initialized arguments of the Dockerfile.
Flags used for this initial example were in docker run ...
flags used:
-it
This combines two flags: -i (interactive) and -t (pseudo-TTY). It allows you to interact with the container through the terminal.--rm
This flag tells Docker to automatically remove the container when it exits. It helps in cleaning up after the container stops running, avoiding accumulation of stopped containers.--user $(id -u):$(id -g)
This sets the user inside the container to the same user and group as the user running the docker run command on the host system.\$(id -u)
returns the user ID of the current user, and\$(id -g)
returns the group ID of the current user.
-
docker images:
docker images
- shows table of pulled and built images, -
docker ps:
docker ps
- shows table of active containers (inactive containers are dangling somewhere within the system), -
docker pull download image to docker, the downloaded image will show in table
docker images
with columns REPOSITORY will display namepytorch/pytorch
and column TAG will display1.13.1-cuda11.6-cudnn8-runtime
:
docker pull pytorch/pytorch:1.13.1-cuda11.6-cudnn8-runtime
docker rmi
remove docker image- ...
Show docker images from build command using: docker images
.
Shows docker containers from run command using docker ps
.
- Some more basic operations with images & containers:
-
Delete Image Command:
- Removes a Docker image forcefully:
docker image rm -f f8fcad3b680c
- Removes a Docker image forcefully:
-
Tagging Image with Custom Repository and Tag:
- Description: Tags an existing Docker image with a custom repository name and tag.
docker image tag server:latest <myname/name>:<otherName> docker image tag d583c3ac45fd <myname/name>:<otherName>
Step-by-step guide to creating a basic docker image.
- Step 1: create directory:
/your_path/start-vm-project/
- Step 2: copy Dockerfile, requirements.txt, scriptToRun.py to directory.
- Step 3: build the image
docker build -t ime:naziv --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g) .
- Step 4 What do i need?:
- a) virtual mounts:
-v ~/home/user/directory:/workingDirectory
, /workingDirectory is the directory name you created in the Dockerfile with commandWORKDIR
, - b) GPUs to use for computing
--gpus all
vs--gpus '"device=0,2"'
- select which gpus to use and how many you need, - c) what is my working directory
-w /set/working/dir/in/container
, this command is not necessary if theWORKDIR
was specified in the Dockerfile, only if you want to change the working directory but then you can encounter user premissions errors, - d) shared memory directory is limited to 64MB, but we increase this size since my application depends on this shared memory to 8GB
--shm-size=8g
, - e) port forwarding between container and "host machine":"virtual machine"
-p 8888:8888
, meaning that host machine port will be forwarded to the container virtual machine port. - f)
--group-add users
: Add the host's users group to the container's group list. This allows the container to access resources or permissions assigned to the users group on the host. - g) ...
- a) virtual mounts:
- Step 5: JupyterLab in browser without cuda support:
docker run -it --rm --user $(id -u):$(id -g) --group-add users -p 8888:8888 -v /home/user/WorkDirectory:/remoteWorkDirectory -w /remoteWorkDirectory ime:tag jupyter lab --no-browser --ip=0.0.0.0 --port=8888
Jupyter lab with cuda support for docker images that have cuda installed.
docker run -it --rm --gpus all --user $(id -u):$(id -g) --group-add users --shm-size=8g -p 8888:8888 -v ~/home/user/homeWorkDirectory:/remoteWorkDirectory -w /remoteWorkDirectory ime:tag jupyter lab --no-browser --ip=0.0.0.0 --port=8888
Click on jupyter link to open jupyter lab and develop. ! If jupyter lab is on a server change 127.0.0.1
to <server ip>
or server name
. Flags at the end are jupyter flags: --no-browser --ip=0.0.0.0 --port=8888
in order: do not open a browser there is no browser on the host machine, use the defalut host ip and the port for jupyter lab is the port 8888 that is forwarded from the host 8888 port to the wirtual machine.
- Step 5': Run some script that needs all these flags instead of jupyter lab we can use the python command or r depending on your installed environment:
docker run -it --rm --gpus all --user $(id -u):$(id -g) --group-add users --shm-size=8g -p 8888:8888 -v ~/home/user/homeWorkDirectory:/remoteWorkDirectory -w /remoteWorkDirectory ime:tag python -script_based_flags my_script.py
Path to dockerfile /developmentInContainer/Dockerfile
. How a container environment could be setup for development if you need to use your data in several different environments.
Project
│ README.md
│
├───data
| | some_data.txt
| ├── ...
│
├───code
| | script.py
| ├── ...
| ├── start-docker
| │ | Dockerfile
| | ├── req.txt
| | ...
Docker run jupyter lab for code editing:
docker run -it --rm --user $(id -u):$(id -g) --group-add users && \
-p 8888:8888 && \
-v /home/user/CodeDirectory:/workspace/code && \
-v /home/user/DataDirectory:/workspace/data && \
-w /remoteWorkDirectory ime:tag && \
jupyter lab --no-browser --ip=0.0.0.0 --port=8888
Singularity (S) and docker images are compatible to create a Singularity image (.simg) just save your existing docker image and push it to the Singularity server. Singularity available HPC servers access: (small) https://hybridscale.github.io/orthus/access and (BIG) https://wiki.srce.hr/pages/viewpage.action?pageId=8488260 Singularity basic commands and description: https://wiki.srce.hr/display/RKI/Singularity
How to go about creating docker image and deploy it on the Singularity server.
After you are satisfied with docker image, save docker image to file:
docker save -o pathToFile/py-min.tar fe35d0fd6c24
Sync image to the server with singularity:
rsync -avP <path/to_directory/img-min.tar> <username>@<server>:/home/user/path/to_directory/
Use gzip for large files for transfer between slow connections: gzip img_min.tar
, rsync -avP <path/to_directory/py-min.tar.gz> <user>@<server>:/home/user/path/to_directory/
, or post your docker image to docker hub as well and create the container form there.
- Build the Singularity Container from existing docker image. Replace <img-min.tar> with the desired name for your docker image file. This command does not require sudo to create .simg singularity image:
singularity build singularity_container.simg docker-archive://<img-min.tar>
-
Use the proposed way of job scheduling when running the scripts in the server environment, https://wiki.srce.hr/display/RKI/Pokretanje+i+upravljanje+poslovima.
-
Run the Singularity Container. Follow the rules of job scheduling srce or job scheduling orthus both HPCs use SGE (Sons of Grid Engine) and execute some script from the created .simg:
singularity exec --nv sPyCuda.simg python cnn_mnist.py
or
singularity exec --nv /path/to/your_container.simg python helloworld.py
Replace "/path/to/your_container.simg" with the path to your Singularity container file and your_script.py
with the name of your Python script.
--nv
flag gives singularity premissions to cuda.
Using a Singularity Definition File (e.g., singularityfile.def
, similar to Dockerfile only has different syntax), pull the image from dockerhub repository:
Bootstrap: docker
From: name:tag # e.g. rstudio/rstudio-server-pro:1.2.5033-1, or r-base:4.3.3, or pytorch/pytorch:2.2.2-cuda12.1-cudnn8-devel(doesnt work on orthus or srce)
%post
# Execute your script inside the container
python your_script.py
Create the .simg:
singularity build sPyCuda.simg singularityfile.def
Using singularityfile.def requires singularity group priveleges (sudo).
Detailed descriptions of job scheduling for SGE in Croatian, how to run jobs with CRO Son of Grid Engine and in English, how to run jobs with ENG Son of Grid Engine
Remote docker container development using VSCODE on the fly. Coding in interactive containerized environment.
Step 1. https://code.visualstudio.com/docs/remote/containers-tutorial vscode:extension/ms-vscode-remote.remote-containers
Step 2. https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack Getting started You can launch a new instance of VS Code connected to WSL by opening a WSL terminal, navigating to the folder of your choice, and typing code .: create a folder named .devcontainer in yout development environment.
Step 3. SSH In VS Code, run Remote-SSH: Open Configuration File
... in the Command Palette (F1), select an SSH config file, and add (or modify) a host entry as follows:
Host server.name.hr
HostName server.name.hr
User userName
Create key and transfer to server in cmd administrator privelages:
In Powershell administrator privileges to upload: ssh-keygen -t rsa -b 4096
$USER_AT_HOST="username@server.name.hr"
$PUBKEYPATH="$HOME\.ssh\id_rsa.pub"
$pubKey=(Get-Content "$PUBKEYPATH" | Out-String); ssh "$USER_AT_HOST" "mkdir -p ~/.ssh && chmod 700 ~/.ssh && echo '${pubKey}' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Add to config file: In VS Code, run Remote-SSH: Open Configuration File... use F1 button to open.
Host server.name.hr
HostName server.name.hr
User userName
IdentityFile ~/.ssh/id_rsa
Check if SSH is working in your terminal and in VSCODE should connect you after: ssh @server.name.hr without password.
Make separate directory "start_project" with files req.txt and Dockerfile and a directory "/.devcontainer" containing file devcontainer.json Examples in the GitHub repository.
Documentation for devcontainer.json: https://containers.dev/implementors/json_reference/ Examples vscode: https://code.visualstudio.com/docs/devcontainers/containers#_open-a-folder-on-a-remote-ssh-host-in-a-container Developing on a remote host: https://code.visualstudio.com/docs/remote/troubleshooting#_configuring-key-based-authentication Working Tourtorial and Examples: https://leimao.github.io/blog/VS-Code-Development-Remote-Host-Docker/