---
# System prepended metadata

title: 'Servers:'

---

# A Simple Guide to Docker

<p style="text-align: justify;">It may help to think of the Docker image as an operating system you can choose to install. When you install such an image on a computer, you create an instance of this operating system. In this analogy, creating the container is precisely the process of transforming the generic operating system description into a concrete OS running on your specific laptop. This is why you specify details like mounted folders when creating the container, rather than in the image, which remains more generic.</p>

You can also briefly skim through this [guide](https://docs.docker.com/get-started/).

<details>
<summary><b>Create a Container Based on the Container Image "pytorch"</b></summary>

1. **SSH to the Servers**
    - It is advisable to use Visual Studio Code and install [Visual Studio Code Remote - SSH](https://code.visualstudio.com/docs/remote/ssh).

2. **Create a Docker Container:**
   ```bash
   nvidia-docker run -p 0.0.0.0:6559:6559 -i -t --name pytorchGu --hostname GuInsideDocker -v /home/riccardo/:/riccardo/ pytorch/pytorch /bin/bash
   ```
   - This command generates a Docker container. To exit, simply type `exit`.
   - If you exit the Docker container, it will stop. To access it again, follow these steps:
     - `docker start <DOCKER-ID>`
     - `docker attach <DOCKER-ID>`
     - You can find all the functions [here](https://docs.docker.com/engine/reference/commandline/container_ls/).
   - You can install Conda environments within the Docker.
     - Use a script to standardize environment installations. Modify the script at your convenience.

   ```bash
   #!/bin/bash

   if [[ $- != *i* ]]; then
       echo "Please run in interactive mode, i.e., bash -i ...; aborting."
       exit 1
   }

   print_usage () {
       echo "Usage:"
       echo -e "\tbash -i $0 -n environment_name"
       echo -e "\tbash -i $0 -p path_to_env"
   }

   if [[ $# -lt 2 ]]; then
       print_usage
       exit 1
   }

   if [[ "$1" != "-n" ]] && [[ "$1" != "-p" ]]; then
       print_usage
       exit 1
   }

   if [[ $# -ge 3 ]]; then
       print_usage
       exit 1
   }

   flag=$1
   env_path=$2

   # Exit when any command fails
   set -e

   # Create and activate Conda environment
   conda create $flag $env_path
   conda activate $env_path

   # Setup channels
   conda config --prepend channels pytorch

   # Install PyTorch
   conda install pytorch=1.12 torchvision cudatoolkit=11.6 -c pytorch

   # Install other Conda packages
   # ...  

   # Install pip packages
   # ... 
   
   echo -e "Created environment ${env_path}; to activate it, use:\n\tconda activate ${env_path}"
   ```
   
   - If desired, install Nano or Vim. For example, to install Nano, use: `apt-get install nano -y`

3. **Useful `docker` Commands**:
    - To list existing Docker containers, use: `docker ps -a`
4. **Useful GitHub Integration Commands**:
    - You can use Git config to enable credential storage in Git. This is often needed when accessing servers for the first time, like so:
    ```git config --global credential.helper store```
    **Note**: The first time you pull or push from the remote repository, you'll be prompted for the username and password. Afterward, for subsequent interactions with the remote repository, you won't need to provide the username and password.
</details>

<details>
<summary><b>Our Optimal Strategy: Is It?</b>
</summary>

This is a strategy that we identified. Please update or suggest alternative ones if you believe that the one outlined here is sub-optimal.

The idea is to have a `.devcontainer` folder within the GitHub repository. That implies that the Docker image is part of the GitHub repository.

1. Within the GitHub repository, create a folder `mkdir .devcontainer`. Inside the folder, add: 
    - A simple Dockerfile: do `nano Dockerfile`
``` 
   # syntax=docker/dockerfile:1

    FROM pytorch/pytorch
    RUN apt-get update && apt-get install -y git screen

    WORKDIR /app
    SHELL ["/bin/bash", "--login", "-c"]
    
    # Create the environment
    COPY env.yml . 
    RUN conda env create -f env.yml
    CMD ["/bin/bash"]
```
and a  `devcontainer.json` file:
```
    {
    "name": "pytorch-base-rb",
    "image": "base-rb/base-rb:funcoords",
    "initializeCommand": "nvidia-docker build -f .devcontainer/Dockerfile -t base-rb/base-rb:funcoords .",
    "customizations": {
      "vscode": {
        "extensions": [
          "eamodio.gitlens",
          "ms-python.python"
        ]
      }
    },
    "mounts": [
      "type=bind,source=/home/riccardo/,target=/riccardo/",
      "type=bind,source=/media/,target=/media/",
      "type=bind,source=/srv/,target=/srv/"
    ],
    "runArgs": [
      "--runtime=nvidia",
      "--name=pytorch-base-rb",
      "--memory=64g",
      "--cpus=16",
      "--shm-size=64g"],
    "shutdownAction": "none",
    "forwardPorts": [3000]
}
```
Note that the Dockerfile constructs a Docker image with the Conda environment specified by `env.yml`. Place an `env.yml` file one level outside the `.devcontainer` folder. 
    
This is a sample one: 
```
    name: bayes
    channels:
      - pytorch
      - nvidia
      - defaults
      - gpytorch
    dependencies:
      - pytorch==2.0.1
      - pytorch-cuda
      - torchvision
      - gpytorch
      - tensorboard
      - pytest
      - pip
```
To activate the env do: ``` conda activate /opt/conda/envs/bayes ```
    

</details>
