Try   HackMD

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

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More β†’

Podman : Pre-Requisite

Podman Local Instalation πŸ§‘β€πŸ’»

  1. Download and configure podman
    Image Not Showing Possible Reasons
    • The image was uploaded to a note which you don't have access to
    • The note which the image was originally uploaded to has been deleted
    Learn More β†’

Podman : Basic Command

Running Container πŸŽ‰

  1. Playing with Image Repository

    • Pull nginx docker images

      Image Not Showing Possible Reasons
      • The image was uploaded to a note which you don't have access to
      • The note which the image was originally uploaded to has been deleted
      Learn More β†’

      As you can see from here, we've created the linux namespace.

    • Listing podman images

      Image Not Showing Possible Reasons
      • The image was uploaded to a note which you don't have access to
      • The note which the image was originally uploaded to has been deleted
      Learn More β†’

      As you can see from here, we've created the linux namespace.

    • Run the nginx container

      Image Not Showing Possible Reasons
      • The image was uploaded to a note which you don't have access to
      • The note which the image was originally uploaded to has been deleted
      Learn More β†’

      Image Not Showing Possible Reasons
      • The image was uploaded to a note which you don't have access to
      • The note which the image was originally uploaded to has been deleted
      Learn More β†’

    • Listing podman container

      Image Not Showing Possible Reasons
      • The image was uploaded to a note which you don't have access to
      • The note which the image was originally uploaded to has been deleted
      Learn More β†’

      As you can see from here, we've created the linux namespace.

Image Creation πŸŽ‰

  1. Setup Local Repository

    • Set Local Repo (With Volume)

      ​​​​​​​​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.

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

      ​​​​​​​​[
      ​​​​​​​​    {
      ​​​​​​​​        "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

      ​​​​​​​​podman image pull docker.io/library/alpine
      
      ​​​​​​​​[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

      ​​​​​​​​podman image tag docker.io/library/alpine:latest localhost:5000/alpine:latest
      
      ​​​​​​​​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

      ​​​​​​​​podman image push localhost:5000/alpine:latest --tls-verify=false
      
      ​​​​​​​​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

      ​​​​​​​​git clone https://github.com/Sameerk22/City-Weather-App
      ​​​​​​​​cd City-Weather-App
      
    • Create a Containerfile

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

      ​​​​​​​​podman build -t localhost:5000/wheather-app:1.0 .
      
    • Push the image to the local registry

      ​​​​​​​​podman image push localhost:5000/wheather-app:1.0 --tls-verify=false
      
    • Verify if the image is being uploaded to local registry

      ​​​​​​​​podman image search localhost:5000/
      
      ​​​​​​​​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

        ​​​​​​​​​​​​sudo mkdir /bindhost
        ​​​​​​​​​​​​sudo sh -c "echo Hello from the HOST! > /bindhost/hello"
        
      • Create a container with bind mount to the /bindhost

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

        ​​​​​​​​​​​​podman exec -it bindtest cat /shared/hello
        
      • Host Storage related with Container Storage

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

        ​​​​​​​​​​​​podman run -d -it --name bindtest-2 --mount type=bind,source=/bindhost,target=/bersama nginx
        
        ​​​​​​​​​​​​docker inspect bindtest-2 -f '{{json .Mounts }}'| python3 -m json.tool
        
        ​​​​​​​​​​​​docker exec -it bindtest-2 ls -l /bersama
        
    2. Using podman - volumes

      • Create Volume with custom name

        ​​​​​​​​​​​​​​​​podman volume create volume-1
        
      • Build the Container with Docker Volume RO Configuration

        ​​​​​​​​​​​​​​​​podman run -d -it --name volumetest-2 --mount source=volume-1,target=/app,readonly nginx
        
      • Inspect if the configuration is done

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

        ​​​​​​​​​​​​podman run fedora mount  | grep /proc.*tmpfs
        
        ​​​​​​​​​​​​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

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

        ​​​​​​​​​​​​podman run -d fedora sleep 100
        ​​​​​​​​​​​​podman top -l capeff
        
        ​​​​​​​​​​​​EFFECTIVE CAPS
        ​​​​​​​​​​​​CHOWN,DAC_OVERRIDE,FOWNER,FSETID,KILL,NET_BIND_SERVICE,SETFCAP,SETGID,SETPCAP,SETUID,SYS_CHR
        

        With Priviledge

        ​​​​​​​​​​​​podman run --privileged -d fedora sleep 100
        
        ​​​​​​​​​​​​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

        ​​​​​​​​​​​podman run -d fedora sleep 100
        ​​​​​​​​​​​podman top -l seccomp
        
        ​​​​​​​​​​​​SECCOMP
        ​​​​​​​​​​​​filter
        

        With Priviledge

        ​​​​​​​​​​​​podman run --privileged -d fedora sleep 100
        ​​​​​​​​​​​podman top -l seccomp
        
        ​​​​​​​​​​​​SECCOMP
        ​​​​​​​​​​​​disabled
        
  5. Container with Proxy Access

    • Configuring and deploying Example Webapp

      ​​​​​​​​podman pull docker.io/library/httpd
      ​​​​​​​​podman pull docker.io/library/nginx
      ​​​​​​​​mkdir syscom sysorg
      
    • Configuring index.html

      ​​​​​​​​$ 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

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

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

      image

    • Validation time with the browser

      image

Container Networking πŸŽ‰

  1. Access your Nginx container on VM 1 from Host Machine via browser

    image

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

    image