Linux Containers without docker and containered services

 Setup a basic Linux


download desired linux oci image to make run as container inside a linux machine.

OCI vs Docker

  • Docker originally created the container format, but OCI ensures that any runtime (not just Docker) can run the same container images.
  • OCI-compliant images work with Docker, Podman, Kubernetes, and other container runtimes.

//go to rocky linux officical page and search for OCI 

//install Skopeo is a command-line utility that can fetch OCI images without requiring Docker.


# yum install skopeo

link - docker hub - https://hub.docker.com/layers/library/rockylinux/9/images/sha256-d644d203142cd5b54ad2a83a203e1dee68af2229f8fe32f52a30c6e1d3c3a9e0?context=explore


[root@docker boobalan]# skopeo copy docker://rockylinux:9 docker-archive:rockylinux-9.tar:rockylinux:9

Getting image source signatures

Copying blob 446f83f14b23 done   |

Copying config 9cc24f05f3 done   |

Writing manifest to image destination

[root@docker boobalan]# ls

k8s-manifest  rockylinux-9.tar



[root@docker boobalan]# ls -lrth rockylinux-9.tar
-rw-r--r-- 1 root root 173M Mar  8 18:22 rockylinux-9.tar

[root@docker boobalan]# pwd
/home/boobalan

[root@docker boobalan]# df -h /home/boobalan/
Filesystem           Size  Used Avail Use% Mounted on
/dev/mapper/rl-root   27G  4.5G   23G  17% /

[root@docker boobalan]# mkdir container_1
[root@docker boobalan]# pwd
/home/boobalan

//now extract the rocky image to the newly created directory

[root@docker boobalan]# tar -xvf /home/boobalan/base_rocky_oci/44343de3ea1d3f71f143967c71a91df76138a17a21ac56642f3c0f2a64b07dce.tar -C /home/boobalan/container_1/

[root@docker boobalan]# ls /home/boobalan/container_1/
afs  bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@docker boobalan]#


/////now let see how we make use of this new linux inside the linux

[root@docker boobalan]# df -h /home/boobalan/container_1/
Filesystem           Size  Used Avail Use% Mounted on
/dev/mapper/rl-root   27G  4.9G   23G  18% /

[root@docker boobalan]# du -sh /home/boobalan/container_1/
183M    /home/boobalan/container_1/

//now use the chroot command to switch the shell into the container machine

[root@docker boobalan]# ls
base_rocky_oci  container_1  k8s-manifest  rockylinux-9.tar
[root@docker boobalan]# chroot container_1 /bin/bash

///here it switched to the container
[root@docker /]# pwd
/
[root@docker /]# whoami
root
[root@docker /]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
tss:x:59:59:Account used for TPM access:/:/usr/sbin/nologin

[root@docker /]# id
uid=0(root) gid=0(root) groups=0(root)
[root@docker /]# hostname
docker.boobi.com


#mount -t proc proc /proc
-t proc → Specifies that the filesystem type is proc.
proc → Refers to the proc virtual filesystem.
/proc → The mount point inside the chroot.
👉 After this, process-related commands (like ps, top, uptime, etc.) will start working inside the chroot.

//following two commands help ful to check whether it was mounted or not and general mount details
[root@docker /]# mount | grep proc
proc on /proc type proc (rw,relatime)

[root@docker /]# findmnt
TARGET SOURCE FSTYPE OPTIONS
/proc  proc   proc   rw,relatime

# findmnt -t proc

///so now my container mounted only this proc, where as if i check the base os that have mulitple mounts

//however ps command giving me an error inside container

//inside container to get internet access use this
cp /etc/resolv.conf /container_1/etc/resolv.conf

//if ps is not work inside need to download 

[root@docker /]# yum install -y procps-ng

///now inside chroot i can run ps

Understanding the Chroot Environment Limitations

When you use chroot to enter a container, you're essentially running in a restricted environment that mimics a new root filesystem. However, it doesn't automatically configure things like networking, devices, or system services the way a full container or VM would.

To make this chroot environment more functional, here are the steps to help it behave more like a full container:

mount --bind /dev /container_1/dev 

mount --bind /sys /container_1/sys 

mount --bind /run /container_1/run

//this need to be executed on the host machine

[root@docker boobalan]# mount --bind /dev container_1/dev

[root@docker boobalan]# findmnt
TARGET                                                  SOURCE     FSTYPE     OPTIONS
/                                                       /dev/mapper/rl-root
│                                                                  xfs        rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota
├─/proc                                                 proc       proc       rw,nosuid,nodev,noexec,relatime
│ └─/proc/sys/fs/binfmt_misc                            systemd-1  autofs     rw,relatime,fd=29,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=18570
├─/sys                                                  sysfs      sysfs      rw,nosuid,nodev,noexec,relatime
│ ├─/sys/kernel/security                                securityfs securityfs rw,nosuid,nodev,noexec,relatime
│ ├─/sys/fs/cgroup                                      cgroup2    cgroup2    rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot
│ ├─/sys/fs/pstore                                      pstore     pstore     rw,nosuid,nodev,noexec,relatime
│ ├─/sys/fs/bpf                                         bpf        bpf        rw,nosuid,nodev,noexec,relatime,mode=700
│ ├─/sys/kernel/debug                                   debugfs    debugfs    rw,nosuid,nodev,noexec,relatime
│ ├─/sys/kernel/tracing                                 tracefs    tracefs    rw,nosuid,nodev,noexec,relatime
│ ├─/sys/fs/fuse/connections                            fusectl    fusectl    rw,nosuid,nodev,noexec,relatime
│ └─/sys/kernel/config                                  configfs   configfs   rw,nosuid,nodev,noexec,relatime
├─/dev                                                  devtmpfs   devtmpfs   rw,nosuid,size=4096k,nr_inodes=217634,mode=755,inode64
│ ├─/dev/shm                                            tmpfs      tmpfs      rw,nosuid,nodev,inode64
│ ├─/dev/pts                                            devpts     devpts     rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000
│ ├─/dev/hugepages                                      hugetlbfs  hugetlbfs  rw,relatime,pagesize=2M
│ └─/dev/mqueue                                         mqueue     mqueue     rw,nosuid,nodev,noexec,relatime
├─/run                                                  tmpfs      tmpfs      rw,nosuid,nodev,size=356736k,nr_inodes=819200,mode=755,inode64
│ ├─/run/credentials/systemd-tmpfiles-setup-dev.service none       ramfs      ro,nosuid,nodev,noexec,relatime,mode=700
│ ├─/run/credentials/systemd-sysctl.service             none       ramfs      ro,nosuid,nodev,noexec,relatime,mode=700
│ ├─/run/credentials/systemd-tmpfiles-setup.service     none       ramfs      ro,nosuid,nodev,noexec,relatime,mode=700
│ └─/run/user/1000                                      tmpfs      tmpfs      rw,nosuid,nodev,relatime,size=178364k,nr_inodes=44591,mode=700,uid=1000,gid=1000,inode64
├─/boot                                                 /dev/sda1  xfs        rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota
├─/home/boobalan/container_1/proc                       proc       proc       rw,relatime
└─/home/boobalan/container_1/dev                        devtmpfs   devtmpfs   rw,nosuid,size=4096k,nr_inodes=217634,mode=755,inode64


///now in the last line you see the dev and proc we have mounted to the container

///now verifiy this inside container_1

[root@docker boobalan]# chroot container_1/ /bin/bash
[root@docker /]# ls /dev/
autofs           disk      hidraw0       mcelog  pts     sg1       tty1   tty19  tty28  tty37  tty46  tty55  tty7     urandom      vcs5   vcsu1        vhost-vsock
block            dm-0      hpet          mem     random  shm       tty10  tty2   tty29  tty38  tty47  tty56  tty8     usbmon0      vcs6   vcsu2        vmci
bsg              dm-1      hugepages     midi    rfkill  snapshot  tty11  tty20  tty3   tty39  tty48  tty57  tty9     usbmon1      vcsa   vcsu3        vsock
bus              dma_heap  hwrng         mqueue  rl      snd       tty12  tty21  tty30  tty4   tty49  tty58  ttyS0    usbmon2      vcsa1  vcsu4        zero
cdrom            dmmidi    initctl       net     rtc     sr0       tty13  tty22  tty31  tty40  tty5   tty59  ttyS1    userfaultfd  vcsa2  vcsu5
char             dri       input         nul

Now, commands related to device management, system processes, or service management (like systemctl, lsmod, etc.) should work.


////concept of this bind mount

The --bind option in the mount command is used to bind-mount an existing directory to a new location. It doesn't copy files or directories, but creates a mirror of the source directory at the target location. This is useful for making a directory or file visible to another environment, such as when you want to give access to devices from the host system to a chroot environment or container.

///so it take the file from the host system --the main linux machine

///The mount --bind command does not copy files from /dev to /container_1/dev. Instead, it makes the contents of /dev on the host available inside the /container_1/dev directory. This allows processes inside the container or chroot to interact with the host system’s devices (e.g., disk partitions, terminals, etc.).


/////different between these two mount -t proc proc /proc  and mount --bind /dev /container_1/dev

1. mount -t proc proc /proc

  • Purpose: This command mounts a proc filesystem at /proc.
  • What is proc?:
    • The proc filesystem is a virtual filesystem that provides information about the kernel, processes, and system state. It is not a traditional filesystem but a kernel interface to access information about the system in a structured manner.
    • It contains directories and files that provide details about processes, kernel parameters, hardware configuration, and much more. For example, /proc/cpuinfo provides information about the CPU, and /proc/meminfo provides information about memory usage.
  • How it works:
    • When you run mount -t proc proc /proc, you're telling the system to mount a virtual proc filesystem from the kernel to the /proc directory. This is needed for applications inside your container or chroot to be able to access information about the system, processes, and the kernel itself.
  • Typical use:
    • This mount is typically used for chroot environments or containers to provide access to system information (e.g., processes, CPU, memory) that would otherwise not be available in a sandboxed environment.

2. mount --bind /dev /container_1/dev

  • Purpose: This command uses the --bind option to bind the host's /dev directory to the /container_1/dev directory.

  • What is /dev?:

    • The /dev directory contains device files that represent hardware devices on the system, such as disks (/dev/sda), terminals (/dev/tty), and special devices (/dev/null).
    • These device files are used by applications to interact with hardware. For example, reading from /dev/sda would give access to the first disk, and writing to /dev/null would discard the output.
  • How it works:

    • When you run mount --bind /dev /container_1/dev, you're creating a mirror of the host’s /dev directory inside the container or chroot environment at /container_1/dev.
    • This is necessary because the chroot or container doesn't automatically have access to the host's devices, so you need to explicitly provide that access by binding /dev from the host system to the chroot/container.
  • Typical use:

    • This is useful for allowing applications inside your chroot/container to interact with the host's hardware, like accessing storage devices, serial ports, or other system devices.


//network tools

#yum install -y iproute iputils net-tools

#yum install -y openssh-server

///for logs

mount --bind /var/log /container_1/var/log

//////to unmount all these if don't want

umount /container_1/dev 

umount /container_1/sys 

umount /container_1/run 

umount /container_1/proc



[root@docker /]# useradd akilan

[root@docker /]# su akilan
bash: /dev/null: Permission denied
bash: /dev/null: Permission denied
bash: /dev/null: Permission denied
bash: /dev/null: Permission denied
bash: /dev/null: Permission denied
bash: /dev/null: Permission denied
[akilan@docker /]$ whoami
akilan

///now i ran top command inside container_1

///on my base os 
[root@docker boobalan]# ps -faux | grep pts
boobalan    1561  0.0  0.3  20660  6828 ?        S    17:39   0:00  |   \_ sshd: boobalan@pts/0
boobalan    1563  0.0  0.2   8704  5120 pts/0    Ss   17:39   0:00  |       \_ -bash
root        1600  0.0  0.4  20408  7808 pts/0    S    17:39   0:00  |           \_ su
root        1604  0.0  0.3   8736  5504 pts/0    S+   17:39   0:00  |               \_ bash
boobalan    1676  0.0  0.3  20660  6992 ?        S    18:20   0:03  |   \_ sshd: boobalan@pts/1
boobalan    1677  0.0  0.2   8704  5248 pts/1    Ss   18:20   0:00  |       \_ -bash
root        1719  0.0  0.4  20408  7936 pts/1    S    18:20   0:00  |           \_ su
root        1723  0.2  0.3   9236  6016 pts/1    S    18:20   0:09  |               \_ bash
root       10865  0.0  0.2   4936  3968 pts/1    S    19:11   0:00  |                   \_ /bin/bash
root       10975  0.1  0.3  12164  5760 pts/1    S    19:28   0:00  |                       \_ su akilan
boobalan   10976  0.0  0.2   4840  3968 pts/1    S    19:28   0:00  |                           \_ bash
boobalan   10985  0.7  0.3  15980  6656 pts/1    S+   19:28   0:00  |                               \_ top
boobalan   10553  0.0  0.3  20660  6836 ?        S    18:47   0:00  |   \_ sshd: boobalan@pts/2
boobalan   10554  0.0  0.3   8704  5376 pts/2    Ss   18:47   0:00  |       \_ -bash
root       10595  0.0  0.4  20408  7808 pts/2    S    18:47   0:00  |           \_ su
root       10599  0.0  0.3   9000  5760 pts/2    S    18:47   0:00  |               \_ bash
root       10988  0.0  0.3  19788  6656 pts/2    R+   19:28   0:00  |                   \_ ps -faux
root       10989  0.0  0.1   6408  2176 pts/2    S+   19:28   0:00  |                   \_ grep --color=auto pts


///i can kill the top process 
[root@docker boobalan]# kill -9 10985

//and the process was killed - the pid is the first one comes after the username

//inside container we can only control the container_1 process
[root@docker /]# ps -afux | grep pts
akilan      1561  0.0  0.3  20660  6828 ?        S    16:39   0:00  |   \_ sshd: boobalan@pts/0
akilan      1676  0.0  0.3  20660  6992 ?        S    17:20   0:03  |   \_ sshd: boobalan@pts/1
root       10997  0.0  0.1   3852  2048 ?        S+   18:32   0:00  |                       \_ grep --color=auto pts
akilan     10553  0.0  0.3  20660  6836 ?        S    17:47   0:00  |   \_ sshd: boobalan@pts/2
[root@docker /]# kill -9 1561
[root@docker /]# kill -9 10553
[root@docker /]# ps -afux | grep pts
akilan      1676  0.0  0.3  20660  6992 ?        S    17:20   0:03  |   \_ sshd: boobalan@pts/1
root       11001  0.0  0.1   3852  2048 ?        S+   18:33   0:00  |                       \_ grep --color=auto pts
[root@docker /]#




/////then how to check if the host machine have running any container or not

#findmnt

or check if incase the container run based on docker or podman
ps aux | grep docker 
ps aux | grep podman

///check if any proc, dec is mounted twice :)


-----------------------------------

///next 
namespace - namespace enable us to create restricted views of systems like the process tree, network interface and mounts. for ex , by creating the namespaces for  process tree of an container we can let the container have a separate process tree, from the host system. this implies that the first process insdie the container will have pid 1, irrespective of the number of process already on the run in the host system.

control group - cgroup
is kernal feature offered by linux that allow the kernel to restric the amount of resources each process uses like process, cpu, memory , disk, network,, such isolation of resources is required to prevent any malicious process or evet in the background, which could dtrain RAM or other resources.
for ex, we can set up a directroy or process to set some memory limit, like 30MB, if that particular process consume more then 30M Ram then this based on cgroup that will be automatically killed.







Post a Comment

0 Comments