# 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>