# Container & Vitualization
## Task 3 Description
In this task, you will learn about container and virtualization in Linux Enterprise.
**What you should learn are in below:**
* Setup docker or podman to your environment
* Learn about basic command in podman or docker
* Try to setup example container in your environment
* Create container image using Dockerfile (setup any application container as you wish
* Create local repository and upload your image to it
* Give privilege to your application container
* Try to manage storage in your container
* Try to run your container in systemd
* Create 2 container in different bridge interface and different IP Segment that can access each other
* Learn about the distinction between System Container and Application Container
`Write your learning activity to HackMD`
## System Design

## Podman : [Pre-Requisite](https://medium.com/@amazingandyyy/introduction-to-network-namespaces-and-virtual-ethernet-veth-devices-304e0c02d084)
### Podman Local Instalation 🧑💻
1. Download and configure podman

## Podman : [Basic Command](https://medium.com/@amazingandyyy/introduction-to-network-namespaces-and-virtual-ethernet-veth-devices-304e0c02d084)
### Running Container 🎉
1. **Playing with Image Repository**
* Pull nginx docker images

As you can see from here, we've created the linux namespace.
* Listing podman images

As you can see from here, we've created the linux namespace.
* Run the nginx container


* Listing podman container

As you can see from here, we've created the linux namespace.
### Image Creation 🎉
1. **Setup Local Repository**
* Set Local Repo (With Volume)
```=bash
podman container run -dt -p 5000:5000 --name rafli-regis --volume rafli-volume:/var/lib/registry:Z docker.io/library/registry:2
```
As you can see from here the output from the creation.
```=output
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
01c9b2bfa441 docker.io/library/registry:2 /etc/docker/regis... 37 seconds ago Up 37 seconds ago 0.0.0.0:5000->5000/tcp rafli-regis
```
Check The volume inspect output
```=output
[
{
"Name": "rafli-volume",
"Driver": "local",
"Mountpoint": "/var/lib/containers/storage/volumes/rafli-volume/_data",
"CreatedAt": "2023-12-05T06:40:56.539301178Z",
"Labels": {},
"Scope": "local",
"Options": {}
}
]
```
* Test if the local repo is properly configured
**Test with the alpine image**
```=bash
podman image pull docker.io/library/alpine
```
```=output
[root@rafli]# podman image pull docker.io/library/alpine
Trying to pull docker.io/library/alpine:latest...
Getting image source signatures
Copying blob c926b61bad3b skipped: already exists
Copying config b541f20801 done
Writing manifest to image destination
Storing signatures
b541f2080109ab7b6bf2c06b28184fb750cdd17836c809211127717f48809858
```
**Change the label name to the local repo with the port**
```=bash
podman image tag docker.io/library/alpine:latest localhost:5000/alpine:latest
```
```=output
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/registry 2 909c3ff012b7 4 days ago 26 MB
docker.io/library/alpine latest b541f2080109 4 days ago 7.63 MB
localhost:5000/alpine latest b541f2080109 4 days ago 7.63 MB
```
**Upload to the local registry**
```=bash
podman image push localhost:5000/alpine:latest --tls-verify=false
```
```=output
Getting image source signatures
Copying blob 9fe9a137fd00 done
Copying config b541f20801 done
Writing manifest to image destination
Storing signatures
```
2. **Containerized Existing App with Dockerfile**
* Clone the repository in my case `wheater app`
```=bash
git clone https://github.com/Sameerk22/City-Weather-App
cd City-Weather-App
```
* Create a Containerfile
```=bash
#Build a weather app
FROM node:lts-alpine
WORKDIR /usr/local/app
COPY package.json package-lock.json ./
RUN npm install
COPY public ./public
COPY src ./src
# RUN npm run build
CMD ["npm", "run"]
```
* Build the Containerfile with custom name
```=bash
podman build -t localhost:5000/wheather-app:1.0 .
```
* Push the image to the local registry
```=bash
podman image push localhost:5000/wheather-app:1.0 --tls-verify=false
```
* Verify if the image is being uploaded to local registry
```=bash
podman image search localhost:5000/
```
```=output
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
localhost:5000 localhost:5000/alpine 0
localhost:5000 localhost:5000/wheather-app 0
```
3. **Managed Storage**
By default all files created inside a container are stored on a writable container layer. This means that:
* The data doesn't persist when that container no longer exists, and it can be difficult to get the data out of the container if another process needs it.
* There are two options for containers to store files in the host machine so that the files are persisted even after the container stops: **volumes** and **bind mounts**.
1. Using podman - **bind mounts**
* Create a directory with files innit
```=bash
sudo mkdir /bindhost
sudo sh -c "echo Hello from the HOST! > /bindhost/hello"
```
* Create a container with bind mount to the `/bindhost`
```=bash
podman run -d -it --name bindtest --mount type=bind,source=/bindhost,target=/shared nginx
```
* Checks whether the contents of the container are the same as the bind mount path of the host
```=bash
podman exec -it bindtest cat /shared/hello
```
* Host Storage related with Container Storage
```=bash
sudo sh -c "echo Hello from the HOST the second time! > /bindhost/hello2"
docker exec -it bindtest cat /shared/hello2
```
* Share the Host Storage to Other Container Storage
```=bash
podman run -d -it --name bindtest-2 --mount type=bind,source=/bindhost,target=/bersama nginx
```
```=bash
docker inspect bindtest-2 -f '{{json .Mounts }}'| python3 -m json.tool
```
```=bash
docker exec -it bindtest-2 ls -l /bersama
```
2. Using podman - **volumes**
* Create Volume with custom name
```=bash
podman volume create volume-1
```
* Build the Container with Docker Volume RO Configuration
```=bash
podman run -d -it --name volumetest-2 --mount source=volume-1,target=/app,readonly nginx
```
* Inspect if the configuration is done
```=bash
docker inspect voltest3 -f '{{json .Mounts }}' | python3 -m json.tool
```
4. **Priviledge Container**
Executing container engines with the --privileged flag tells the engine to launch the container process without any further "security" lockdown. But it comes with the risk:
* **Container Escalation**: Privileged containers can escalate their access to the host system, potentially gaining unauthorized control.
* **Resource Exhaustion**: Privileged containers can consume host resources without any restrictions, potentially causing resource exhaustion or denial-of-service attacks.
* **Data Exposure**: Privileged containers can access sensitive data on the host system, potentially leading to data breaches or exposure.
There are serveral impact to the list down system:
* Read-only kernel file systems
`Without Priviledge`
```=bash
podman run fedora mount | grep /proc.*tmpfs
```
```=output
Resolved "fedora" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
Trying to pull registry.fedoraproject.org/fedora:latest...
Getting image source signatures
Copying blob 718a00fe3212 done
Copying config 368a084ba1 done
Writing manifest to image destination
Storing signatures
sysfs on /sys type sysfs (ro,nosuid,nodev,noexec,relatime)
cgroup2 on /sys/fs/cgroup type cgroup2 (ro,nosuid,nodev,noexec,relatime)
tmpfs on /proc/acpi type tmpfs (ro,relatime,size=0k,uid=1002,gid=1002,inode64)
tmpfs on /proc/scsi type tmpfs (ro,relatime,size=0k,uid=1002,gid=1002,inode64)
tmpfs on /sys/firmware type tmpfs (ro,relatime,size=0k,uid=1002,gid=1002,inode64)
tmpfs on /sys/dev/block type tmpfs (ro,relatime,size=0k,uid=1002,gid=1002,inode64)
proc on /proc/bus type proc (ro,relatime)
proc on /proc/fs type proc (ro,relatime)
proc on /proc/irq type proc (ro,relatime)
proc on /proc/sys type proc (ro,relatime)
proc on /proc/sysrq-trigger type proc (ro,relatime)
```
`With Priviledge`
```=bash
podman run --privileged fedora mount | grep /proc.*tmpfs
```
None of the kernel file systems are mounted read-only in --privileged mode. Usually, this is required to allow processes inside of the container to actually modify the kernel through the kernel file system.
* Linux capabilities
`Without Priviledge`
```=bash
podman run -d fedora sleep 100
podman top -l capeff
```
```=output
EFFECTIVE CAPS
CHOWN,DAC_OVERRIDE,FOWNER,FSETID,KILL,NET_BIND_SERVICE,SETFCAP,SETGID,SETPCAP,SETUID,SYS_CHR
```
`With Priviledge`
```=bash
podman run --privileged -d fedora sleep 100
```
```=output
EFFECTIVE CAPS
AUDIT_CONTROL,AUDIT_READ,AUDIT_WRITE,BLOCK_SUSPEND,CHOWN,DAC_OVERRIDE,DAC_READ_SEARCH,FOWNER,FSETID,IPC_LOCK,IPC_OWNER,KILL,LEASE,LINUX_IMMUTABLE,MAC_ADMIN,MAC_OVERRIDE,MKNOD,NET_ADMIN,NET_BIND_SERVICE,NET_BROADCAST,NET_RAW,SETFCAP,SETGID,SETPCAP,SETUID,SYSLOG,SYS_ADMIN,SYS_BOOT,SYS_CHROOT,SYS_MODULE,SYS_NICE,SYS_PACCT,SYS_PTRACE,SYS_RAWIO,SYS_RESOURCE,SYS_TIME,SYS_TTY_CONFIG,WAKE_ALARM,unknown,unknown,unknown
```
When you launch a container with --privileged mode, the container launches with almost of full list capabilities.
* Syscall filtering - SECCOMP
`Without Priviledge`
```=bash
podman run -d fedora sleep 100
podman top -l seccomp
```
```=output
SECCOMP
filter
```
`With Priviledge`
```=bash
podman run --privileged -d fedora sleep 100
podman top -l seccomp
```
```=output
SECCOMP
disabled
```
5. **Container with Proxy Access**
* Configuring and deploying Example Webapp
```=bash
podman pull docker.io/library/httpd
podman pull docker.io/library/nginx
mkdir syscom sysorg
```
* Configuring `index.html`
```=bash
$ cat << EOF > ./syscom/index.html
<html>
<header>
<title>SysAdmin.com</title>
</header>
<body>
<p>This is the SysAdmin website hosted on the .com domain</p>
</body>
</html>
EOF
$ cat << EOF > ./sysorg/index.html
<html>
<header>
<title>SysAdmin.org</title>
</header>
<body>
<p>This is the SysAdmin website hosted on the .org domain</p>
</body>
</html>
EOF
```
* Configure the proxy
```=bash
mkdir nginx
touch nginx/default.conf nginx/syscom.conf nginx/sysorg.conf
```
`default.conf`
```=
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
```
`syscom.conf`
```=
server {
listen 80;
server_name sysadmin.com;
location / {
proxy_pass http://192.168.1.53:8080;
}
}
```
`sysorg.conf`
```=
server {
listen 80;
server_name sysadmin.org;
location / {
proxy_pass http://192.168.1.53:8081;
}
}
```
* Run in proxy configuration in podman
```=bash
podman run --name=nginx --privileged -p 80:80 -v /home/analyst/nginx:/etc/nginx/conf.d:Z -d docker.io/library/nginx
```
* Validation time with `curl` to the domain

* Validation time with the browser

### Container Networking 🎉
1. **Access your Nginx container on VM 1 from Host Machine via browser**

2. **Access your Nginx container from Namespace of VM 2 using `curl`**
