# How to run a Java program in DevContainer on the LIS Cluster

## Getting started

*Prerequisite: Ubuntu Terminal*

Tutorial source: 
- “Manuals.” Docker Documentation. https://docs.docker.com/manuals/. Published March 5, 2025. Accessed March 18, 2025.
- Fabrice Daian. "Create, manage and deploy DevContainers | DevContainer Formation." LIS GitLab. https://gitlab.lis-lab.fr/sicomp/devcontainer_formation. Published December 5, 2024. Accessed March 18, 2025.

## Step by step

### Installation

#### Install Docker

1. Uninstalling any potential conflicting packages already installed on your computer:
    ```bash
    for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done
    ```

2. Set up Docker's apt repository:
    ```bash
    # Add Docker's official GPG key:    
    sudo apt-get update
    sudo apt-get install ca-certificates curl
    sudo install -m 0755 -d /etc/apt/keyrings
    sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
    sudo chmod a+r /etc/apt/keyrings/docker.asc

    # Add the repository to Apt sources:
    echo \
        "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
        $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
        sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    sudo apt-get update
    ```

3. Install the Docker packages:
    ```bash
    sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    ```

4. Configure docker in rootless mode
    ```bash
    sudo groupadd docker
    sudo usermod -aG docker $USER
    ```

5. Verify that the installation is successful by running the hello-world image:
    ```bash
    docker run hello-world
    ```
    This command downloads a test image and runs it in a container. When the container runs, it prints a confirmation message and exits.
    ```txt
    Hello from Docker!
    This message shows that your installation appears to be working correctly.
    ...
    ```

#### Install Squashfs tools

```bash
sudo apt-get update && sudo apt-get install squashfs-tools
```

#### Install Devcontainer Command Line Interface (DCLI)
DCLI is a tool which will help you manage DevContainers (https://gitlab.lis-lab.fr/sicomp/dcli)

1. If you don't already have git installed, type:
    ```bash
    sudo apt install git
    ```

2. Once done clone the DCLI directory:
    ```bash
    git clone https://gitlab.lis-lab.fr/sicomp/dcli
    ```

3. Proceed to the install:
    ```bash
    cd dcli
    chmod +x install.sh
    ./install.sh
    ```

4. Once installation is complete, you have to source your bashrc:
    ```bash
    source ~/.bashrc
    ```

5. Check that dcli is working properly by typing:
    ```bash
    dcli --version
    ```

### Create Java project and Write dockerfile

Now, we will start with a simple Java program: Hello World.
The file structure and content are organized as follows:

```css
hello-world/
│── src/
│   └── main.java
└── Dockerfile
```

#### main.java
```java
public class main {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
```

#### Dockerfile
Create a `Dockerfile` in the hello-world directory:

```dockerfile
FROM openjdk
COPY src hello-world/src
WORKDIR hello-world
RUN mkdir -p bin
RUN javac -d bin ./src/main.java
WORKDIR bin
CMD ["java", "main"]
```

**Note**: Make sure that the scripts is named exactly as `Dockerfile` or `dockerfile`.

### Create docker image

To create a Docker image from the Dockerfile, run the following command in the `hello-world` directory:

```bash
docker build -t hello:test .    
```

with `hello:test` assigns the image a name `hello` and a tag `test`.

### Run the Docker Container

Once the image is built, you can run the container using:


```bash   
docker run -it hello:test
```

### Initialize a project using a customized Devcontainer configuration

On Terminal, type:

```bash
dcli init
```

Insert image name of docker created:

```bash
Image Name: hello:test
```

### Test running the DevContainer

Type : 

```bash
dcli start
```

You will see the VSCode workspace opened. Test running the java program inside the DevContainer, type:

```bash
java main.java
```

Stop the container: 

```bash 
dcli stop 
```

### Push DevContainer to the LIS Cluster

#### 1. Export the DevContainer

Type: 

```bash
dcli export
```

Once finished, you should see a squashfs file created.

**Note:** Ignore the error on permission denied, or type: 

```bash
dcli export | chmod -R 777 tmp
```

#### 2. Push your Devcontainer on LIS Cluster

On the first teminal window, connect to the cluster:

```bash
ssh thi-phuong.kieu@sms
```

Then create new folders:

```bash 
mkdir devcontainer_images # for the squashfs file
mkdir hello-world       # for your soucre code
```

On the second window, type:

```bash
dcli config
```

```txt
Please provide the following information to create the .cluster_config file.
Cluster server name/address [sms]: sms
LIS cluster username []: thi-phuong.kieu
Devcontainer workspace directory path [/workspace]: /workspace
Project directory (absolute path) to mount inside the devcontainer located on the cluster []: /home/thi-phuong.kieu/hello-world/
Directory containing squashfs images (absolute path) located on the cluster []: /home/thi-phuong.kieu/devcontainer_images/

.cluster_config file created successfully in the .devcontainer directory.
```

Now, push the squashfs file to the cluster
push your squashfs fil inside the cluster:

```bash
dcli push
```

Then, push your source code to the cluster. E.g: 

```bash
scp -r -o ProxyJump="thi-phuong.kieu@139.124.22.4" ./src/main.java thi-phuong.kieu@sms:/home/thi-phuong.kieu/hello-world/src/main.java
```

### Run your DevContainer on LIS Cluster

On the termianl, type:

```bash
dcli irun
```

Once connect successfully, type:

```bash
java main.java
```

**Note:** To run manually, connect to the cluster first, then type:

```bash
srun --container-image=/home/thi-phuong.kieu/devcontainer_images//dcli_hello-world.squashfs --container-mounts=/home/thi-phuong.kieu/hello-world/:/workspace --container-workdir=/workspace --cpus-per-task=12 --pty bash
```

## Appendix

With the [DEv-CF project](~/code/devs-dclitest.zip), the dockerfile is written as follow:

```dockerfile
FROM openjdk:17

# Copy all necessary project folders into the container
COPY src/ /devs-dclitest/src/      
COPY lib/ /devs-dclitest/lib/
COPY input/ /devs-dclitest/input/
COPY output/ /devs-dclitest/output/

WORKDIR /devs-dclitest
RUN mkdir -p /devs-dclitest/bin

# Compile Java source files with the required library
RUN javac -cp "/devs-dclitest/lib/fwkdevs-v0.7" -d /devs-dclitest/bin /devs-dclitest/src/*.java

# Run the Java application with the bin and lib path
CMD ["java", "-cp", "/devs-dclitest/bin:/devs-dclitest/lib/fwkdevs-v0.7", "Simulator"]
```