Analysis of Docker container technology principle (2 ways to create a custom container)

To complete a basic container, the six isolations that the container needs to do
The Linux kernel provides these six namespace-isolated system calls
Serial number Name space System call parameters Quarantine content
1 UTS CLONE_NEWUTS Host name and domain name
2 IPC CLONE_NEWIPC Semaphore, shared memory
3 PID CLONE_NEWPID Process number
4 Network CLONE_NEWNET Internet equipment
5 Mount CLONE_NEWNS Mount point, file system
6 User CLONE_NEWUSER Users and user groups
The main purpose of the Linux kernel to implement namespace is to achieve lightweight virtualization (container) services. Processes under the same namespace can perceive each other's changes, and know nothing about external processes, so that you can make the container Illusion of progress
Create virtual root
[root@es2 ~]# mkdir vroot
[root@es2 ~]# yum -y install --installroot=/root/vroot  bash yum coreutils
[root@es2 ~]# cd vroot
[root@es2 vroot]# ls

bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr

  • View the help information command of the isolation space command
[root@es2 ~]# man unshare
[root@es2 ~]# man setns
E.g:
  • Serial number (1): Use of host name isolation space (the same machine and two terminals are used below, distinguished by 1, 2)
2]# ushare --uts         //开启命名空间
2]# hostname bbb     //设置主机名
2]# bash
2]# exit      
1]# echo $HOSTNAME     //终端2改变了,但是终端1未影响
  • Serial number (2): File system mount is isolated from user user unshare --mount

--------- Terminal 1----------

1]# mount -l     // 查看可用的mount 文件
1]# cd /var/tmp
1]# lftp 192.168.1.254
lftp  192.168.1.254:->  ls
lftp  192.168.1.254:/> cd ios/
lftp  192.168.1.254:/iso>get RHEL7-extras.iso
lftp  192.168.1.254:/iso> bye
tmp]# ls
tmp]# unshare --mount
tmp]# mount -t iso9660 -o   loop,ro    RHEL7-extras.iso  /mnt/
tmp]# mount -l  | grep iso    

--------- Terminal 2----------

2]# mount -l  | grep iso   终端2 看不见
  • Serial number (3): IPC & PID isolation unshare --pid --ipc --fork --mount --proc /bin/bash
    --------- terminal 1----------
1]# ps -ef
1]# systemctl stop docker
1]# pstree -p
systemd(1)
1]# unshare --pid --ipc --fork --mount-proc /bin/bash
1]#pstree -p
bash(1) 
1]# kill -9 2346      //在终端2上随便找一个进程杀死,由于已隔离,无法杀死

--------- Terminal 2----------
(The following operations are to close docker and delete the network card. If docker is not turned on, there is no need to do the following)

2]# yum install bridge-utils
2]# ip link set dev docker0  down
2]# ip help link
2]# ip link help link
2]# ip link  del link dev docker0
2]# brctl show 
2]# ifconfig
  • Serial number (4): Network network isolation unshare --net /bin/bash
    --------- terminal 1---------
1]# ifconfig

--------- Terminal 2----------

2]# unshare --net /bin/bash
2]# ifconfig    //已无网卡
2]# ifconfig -a   //仅有本地回环地址
2]# ifconfig lo up    //启动回环
Make a network virtual switch
1]# ip link add name docker0 type bridge stp_state 1   //docker可改任意名  bridge 虚拟交换机   stp_state 1 打开协议
1]# ifconfig -a
1]# ip link set dev docker0 up  //开启虚拟交换机电源 
1]# ifconfig 
1]# ip addr add 172.17.0.1/16 brd 172.17.255.255 dev docker0    //设置ip地址
1]# ifconfig
Make a virtual network card (one-to-two-port device)
1]# ip link add lnic0 type veth peer  name rnic0    //lnic0 本地网卡    rnic0 容器插入网卡
1]# ifconfig -a      //能看见,但未使用
1]# ip netns list     //查看命名空间
1]# mkdir -p /var/run/netns
1]# cd  /var/run/netns
1]# ls

Go to another terminal to view the namespace process

2 ]# echo  $$     // (以12345为例)
12345

Return to terminal

1]# ln -s /proc/12345/ns/net  /var/run/netns/12345
1]# ll
1]# ip netns list
1]# ifconfig -a
1]# ip link set rnic0 netns 12345 name  eth0
2]# ifconfig -a    //会出现eth0
2]# ifconfig eth0 up
1]# ip netns exec 12345  ip addr  add dev eth0 172.17.0.2/16 brd 172.17.255.255    //设置ip地址
2]# ifconfig     
2]# ping 172.17.0.1     //ping 不通  (虚拟交换机只连接了一头)
1]# ip link set dev lnic0 master  docker0      //  (设置虚拟交换机连接容器)
1]# ip link set dev lnic0 up            //启动
2]# ping 172.17.0.1     //ping 不通   (未开启路由转发)
1]#sysctl -w net.ipv4.ip_forward=1    //开启路由转发
2]# ping 172.17.0.1 
2]# ping 192.168.1.254     //ping不通  (未设置网关)
2]# ip route replace default via 172.17.0.1       //设置网关
2]# ping 192.168.1.254     //ping通
2]#  pstree -p
systemd(1)

Start and run the container

Full version 1 (terminal 2)
2]# cd vroot/
2]#touch docker           //为了区别真实根和虚拟根 
2]# ushare --uts --mount --pid --ipc --fork --mount-proc
2]# mount --bind /proc  /root/vroot/proc
2]# hostname mydocker
2]# /usr/sbin/chroot  /root/vroot
2]# yum install psmisc vim net-tools 
2]# ls /
2]# pstree -p
bash(1)
2]# ifconfig
eth0 :172.17.0.2
2]# 
Full Version 2 (Terminal 1)
1]# systemd-nspawn   -M   aabb    -D  /root/vroot  --network-bridge=docker0
ooxx]# ifconfig -a
ooxx]# yum -y install  iproute
ooxx]# ip link set  host0 name eth0
ooxx]# ifconfig -a
ooxx]# ifconfig eth0 172.17.0.3/16
ooxx]# ip route replace ddefault via 172.17.0.1
ooxx]# yum provides ping
ooxx]# yum -y install iputils
Supplementary and summary commands
  1. What if there is no network card? Create a virtual device, join the namespace
  2. ip link add lnic0 type veth peer name rnic0 mkdir -p /var/run/netns
  3. ln -s /proc/${PID}/ns/net /var/run/netns/${PID}
  4. ip link set rnic0 netns ${PID} name eth0
Namespace plus chroot to build container
  • Create namespace vhost
  1. ip netns add vhost
  2. ip netns list
  • Set up a virtual switch
  1. ip link add name docker0 type bridge stp_state 1
  2. ip link set dev docker0 up
  3. ip addr add 172.17.0.1/16 brd 172.17.255.255 dev docker0
  • Create a virtual network card and add a virtual switch
  1. ip link add name global_nic type veth peer name ns_nic
  2. ip link set dev global_nic promisc on
  3. ip link set dev global _nic promisc on
  4. ip link set dev global_nic master docker0
  • Add the virtual network card to the namespace and set the ip gateway (vhost is the pid number)
  1. ip link set ns_nic netns vhost name eth0
  2. ip netns exec vhost ip link set dev lo up
  3. ip netns exec vhost ip link set dev eth0 up
  4. ip netns exec vhost ip addr add dev eth0 172.17.0.2/16 brd 172.17.255.255
  • Turn on routing and forwarding to make the namespace extremely accessible to external networks
  1. sysctl -w net.ipv4.ip_forward=1
  • Create a namespace, with the root directory, and enter the namespace
  1. ushare --uts --mount --pid --ipc --fork --mount -proc
  • Virtual directory mapping access memory
  1. mount --bind / proc / root / vroot / proc
  • Set hostname
  1. hostname vhost
  • Enter virtual directory
  1. ip netns exec vhost /usr/sbin/chroot /root/vroot
What should I do if so many steps are too troublesome?
  • One command (using the system's own commands)
  1. systemd-nspawn -M aabb -D / root / vroot --network-bridge = docker0

Guess you like

Origin blog.csdn.net/weixin_45942735/article/details/104364584