如何把Docker容器变成物理机系统

2023-12-09 00:30

本文主要是介绍如何把Docker容器变成物理机系统,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

如何把容器变成物理机

本文的主题是把容器变成物理机,根据所学的知识。以及通过各种搜索引擎。他们都告诉我们,这是不可能的。这真的是不可能的吗?我不信,那我就要创造奇迹。请继续往下看。本文将教你如何把容器变成物理机。作品来自2678885646@qq.com

这里只讲硬货,不废话!!!

什么是容器

在这里插入图片描述

​ 简单来说,容器是一个隔离的操作系统沙盒,目的是隔离所有操作系统的进程,那么我们也可以称容器的名称为被隔离的进程,在不同维度隔离级别有6个。隔离进程的名称空间是内核提供的功能,必须内核支持才可以。也就是说容器的内核跟宿主机的是同一个内核。Docker官方把它称作集装箱,我觉得这非常的形象,他们都工作在Linux 内核这条船上。

既然现在知道容器是个什么了,接下来要了解的是容器的运行逻辑。在用法上,一般把软件包直接放到容器内,然后在容器启动的时候,执行一个命令或者某个脚本文件,熟悉docker的人如果自己动手构建过自己的容器,就会知道CMD命令和ENTRYPOINT这个指令是定义docker的启动之后的执行逻辑。然后docker会安装启动之后的逻辑执行,若这个进程exit了,那么这个容器的运行状态也是exit状态。但是这些对我们本文的主题来讲并不重要。

docker的资源限制是通过cgroup来实现的,但是这也是针对运行状态的容器才会有资源消耗,我们是要转化这个容器,对我们的操作而言并不重要,另外顺便提一嘴,cgroup也是Linux内核的功能。

在空间占用方向上,(作品来自2678885646@qq.com)通常一个容器只需要几MB到数10MB不等,而咱们操作系统都需要G这个单位去计算,这是为什么呢?后面将会说容器与操作系统共享的几个文件和目录,这个是它变小的关键。

Docker的六个维度的隔离

内容备注内核版本
PID进程编号2.6.24
NET网络设备、网络协议栈、端口2.6.29
IPC信号量、消息队列、共享内存2.6.19
MOUNT文件系统2.4.19
UTS用户名和主机域2.6.19
USER操作系统的用户和用户组3.8.x

为什么容器比物理机占用空间小呢?这个问题涉及到了Linux设计架构,linus大佬在设计Linux的时候将Linux分成了rootfs,内核,vfs(虚拟文件系统)几部分,当然这又是一个巨大的话题,毕竟内核源码超过2760万行,想了解具体逻辑,这并不简单。我们需要知道,虚拟文件系统包括/proc /dev /sys /dev/pts,且不仅仅包括这些,因为过于复杂,对于容器来讲,只需要了解这几个即可。

  • /sys 他是内核的接口,是一个虚拟文件系统,由内核生成。
  • /proc 这个是内存和进程保存的地方,也就是物理硬件的RAM。
  • /dev 这个目录里存储了物理硬件的抽象为文件。
  • /dev/pts 这里面存储了一些虚拟终端

总之这些目录必须存在且由内核生成。刚刚聊到容器占用磁盘空间会比物理机小很多,根本原因是因为物理机是已经启动起来了,大部分文件在物理机种都已经包含,包括内核模块都不需要安装,这些东西对于一个已经启动了的容器来讲是完全不必要的。另外一个方面就是容器内部极度精简,所以到你们看到的时候就只有几十MB。我们今天要做的步骤就有这一步,将所有缺少了的东西全部补全。

什么是物理机

相对而言,物理机抽象概念上来讲是一个完整的操作系统。包括容器内的全部内容,并且包括各种物理硬件的驱动,EFI或者bios引导,内核模块,内核源码。

总而言之,它是一个标准,它是用来定义“完整的系统”。

容器和虚拟机机区别和联系

从用户眼里来看,它们相同的部分是都具有文件系统,都能运行应用程序。在我看来,这只是浅尝辄止罢了。

我不想用传统的眼光看待它们,又是通过运行模式啦,又是通过运行速度,又是性能损耗啦。我觉得这些都是没有太大意义的。这些比较讲了操作系统和容器出现之后的事情,而不是在创造创造这个东西之前。

我要做鲁迅笔下的勇士,不管是蜘蛛还是螃蟹,在尝之前都不知道什么味道,而不是要把尝了之后的味道从侧面告诉大家 “吃螃蟹的人比较多“,”几乎没有吃蜘蛛的人”。而我们就到这个阶段,来比较吃螃蟹和吃蜘蛛的口感,这往往是世俗之人忘记了的根本。

让我们来重新认识操作系统吧

从时间发生的顺序来讲,首先你按了开机键。bios开始从主板芯片CMOS里加载。然后开始读取硬盘里的esp分区,根据grub引导,找到系统内核,开始加载内核,生成vfs文件系统,加载init进程,开机解锁。这时,完整的操作系统就可以运行了。

那么容器的启动过程呢? docker run -it --rm alpine bash?么,不不不。首先他会将rootfs以及overlay进行叠加,放到宿主机系统的某个目录。然后调用内核api生成六个名称空间,将部分系统文件映射到容器内部(fs名称空间内),调用内核生成vfs,然后执行bash进程,这个是这条命令要干的事。

现在我将这俩进行对比,我们补全容器在启动过程中跟物理机不同的地方,这样是不是容器就能像是物理机一样运行了呢?答案是肯定的。让我们实际操作一下试试。

我们需要做什么

  • 制作一个容纳这个容器的磁盘

    • 分区表
    • 分区类型
    • 更新fstab
  • 生成rootfs,并补全缺少的目录和vfs

    • bindmount
    • /sys
    • /proc
    • /dev
    • /dev/pts
    • /etc/reslove.conf
    • hostname
    • /etc/fstab
  • 补全内核

    • linux-image
    • linux-header
  • 补全进程管理器

    • systemd
  • 补全init进程

    • init
  • 补全网络管理

    • NetworkManager
  • 补全grub引导

    • grub-install
  • 重启测试

    • 独立测试

开始干

制作一个容纳这个容器的磁盘

这一步我们通过VMware生成vmdk硬盘并使用DiskGenius进行分区。

VMware步骤:

创建一个空的虚拟机然后增加磁盘,这里我们用50G,实测1G都用不了。

在这里插入图片描述

开启EFI引导

在这里插入图片描述

最终我的虚拟机配置是这样的。

在这里插入图片描述

DiskGenius步骤

在diskgenius里面选择打开刚刚创建的vmdk文件

在这里插入图片描述

转换为GPT分区表

在这里插入图片描述

分区结果展示,我这里使用了1G的esp分区,49G的根分区

在这里插入图片描述

这样我们的磁盘准备工作就完成了。

生成rootfs

回到VMware,开机使用iso镜像进行引导,进入体验模式。如下图所示。

在这里插入图片描述

安装docker
apt update
# 安装docker
apt install curl -y && curl -sSL get.docker.com | bash
分区挂载
# 查看我们刚刚创建的硬盘分区名称
root@ubuntu:~# lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
loop0    7:0    0   2.2G  1 loop /rofs
loop1    7:1    0     4K  1 loop /snap/bare/5
loop2    7:2    0    62M  1 loop /snap/core20/1611
loop3    7:3    0  54.2M  1 loop /snap/snap-store/558
loop4    7:4    0 346.3M  1 loop /snap/gnome-3-38-2004/115
loop5    7:5    0  91.7M  1 loop /snap/gtk-common-themes/1535
loop6    7:6    0    47M  1 loop /snap/snapd/16292
sda      8:0    0    50G  0 disk
├─sda1   8:1    0     1G  0 part
└─sda2   8:2    0    49G  0 part 
sr0     11:0    1   3.6G  0 rom  /cdrom
root@ubuntu:~# mount /dev/sda2 /mnt/
root@ubuntu:~# mkdir -pv /mnt/boot/efi
mkdir: 已创建目录 '/mnt/boot'
mkdir: 已创建目录 '/mnt/boot/efi'
root@ubuntu:~# mount /dev/sda1 /mnt/boot/efi/
root@ubuntu:~# df -h
文件系统        容量  已用  可用 已用% 挂载点
udev            1.9G     0  1.9G    0% /dev
tmpfs           389M  1.9M  388M    1% /run
/dev/sr0        3.6G  3.6G     0  100% /cdrom
/dev/loop0      2.2G  2.2G     0  100% /rofs
/cow            1.9G  776M  1.2G   40% /
tmpfs           1.9G     0  1.9G    0% /dev/shm
tmpfs           5.0M  4.0K  5.0M    1% /run/lock
tmpfs           1.9G     0  1.9G    0% /sys/fs/cgroup
tmpfs           1.9G     0  1.9G    0% /tmp
/dev/loop1      128K  128K     0  100% /snap/bare/5
/dev/loop2       62M   62M     0  100% /snap/core20/1611
/dev/loop3       55M   55M     0  100% /snap/snap-store/558
/dev/loop6       47M   47M     0  100% /snap/snapd/16292
/dev/loop5       92M   92M     0  100% /snap/gtk-common-themes/1535
/dev/loop4      347M  347M     0  100% /snap/gnome-3-38-2004/115
tmpfs           389M   60K  389M    1% /run/user/999
tmpfs           389M     0  389M    0% /run/user/0
/dev/sda2        49G   16K   46G    1% /mnt
/dev/sda1      1022M  4.0K 1022M    1% /mnt/boot/efi
创建rootfs

使用当前最新镜像23.10

在这里插入图片描述

root@ubuntu:~# cd /mnt/
root@ubuntu:/mnt# docker export $(docker create ubuntu:23.10) | tar -C . -xvf -

在这里插入图片描述

临时代替内核补全vfs

for i in run sys proc dev dev/shm dev/pts; do echo "mount /$i"; mount --bind /$i /mnt/$i; done
root@ubuntu:/mnt# findmnt | grep mnt
│ │ └─/run/snapd/ns/snap-store.mnt         nsfs[mnt:[4026532702]] nsfs            rw
├─/mnt                                     /dev/sda2              ext4            rw,relatime
│ ├─/mnt/boot/efi                          /dev/sda1              vfat            rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro
│ ├─/mnt/run                               tmpfs                  tmpfs           rw,nosuid,nodev,noexec,relatime,size=398272k,mode=755,inode64
│ ├─/mnt/sys                               sysfs                  sysfs           rw,nosuid,nodev,noexec,relatime
│ ├─/mnt/proc                              proc                   proc            rw,nosuid,nodev,noexec,relatime
│ └─/mnt/dev                               udev                   devtmpfs        rw,nosuid,noexec,relatime,size=1952868k,nr_inodes=488217,mode=755,inode64
│   ├─/mnt/dev/shm                         tmpfs                  tmpfs           rw,nosuid,nodev,inode64
│   └─/mnt/dev/pts                         devpts                 devpts          rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000root@ubuntu:/mnt#

进入rootfs补全系统文件

使用下面的命令进入新的根分区
# chroot /mnt/
补全DNS配置
root@ubuntu:/# echo "nameserver 8.8.8.8" > /etc/resolv.conf
补全挂载的配置文件
root@ubuntu:/# echo "/dev/sda2 / ext4 defaults 0 1" >> /etc/fstab
root@ubuntu:/# echo "/dev/sda1 /boot/efi vfat umask=0077,shortname=winnt 0 2" >> /etc/fstab
root@ubuntu:/# cat /etc/fstab
# UNCONFIGURED FSTAB FOR BASE SYSTEM
/dev/sda2 / ext4 defaults 0 1 
/dev/sda1 /boot/efi vfat umask=0077,shortname=winnt 0 2
安装dialog
root@ubuntu:/# apt install dialog
安装时区
 apt install tzdataConfiguring tzdata
------------------Please select the geographic area in which you live. Subsequent configuration questions will narrow this down by presenting a list of cities, representing the time zones in which they are located.1. Africa  2. America  3. Antarctica  4. Arctic  5. Asia  6. Atlantic  7. Australia  8. Europe  9. Indian  10. Pacific  11. US  12. Etc
Geographic area: 5Please select the city or region corresponding to your time zone.1. Aden      9. Baghdad   17. Chita       25. Dushanbe     33. Irkutsk    41. Kashgar       49. Macau         57. Omsk        65. Riyadh         73. Tashkent     81. Urumqi2. Almaty    10. Bahrain  18. Choibalsan  26. Famagusta    34. Istanbul   42. Kathmandu     50. Magadan       58. Oral        66. Sakhalin       74. Tbilisi      82. Ust-Nera3. Amman     11. Baku     19. Chongqing   27. Gaza         35. Jakarta    43. Khandyga      51. Makassar      59. Phnom_Penh  67. Samarkand      75. Tehran       83. Vientiane4. Anadyr    12. Bangkok  20. Colombo     28. Harbin       36. Jayapura   44. Kolkata       52. Manila        60. Pontianak   68. Seoul          76. Tel_Aviv     84. Vladivostok5. Aqtau     13. Barnaul  21. Damascus    29. Hebron       37. Jerusalem  45. Krasnoyarsk   53. Muscat        61. Pyongyang   69. Shanghai       77. Thimphu      85. Yakutsk6. Aqtobe    14. Beirut   22. Dhaka       30. Ho_Chi_Minh  38. Kabul      46. Kuala_Lumpur  54. Nicosia       62. Qatar       70. Singapore      78. Tokyo        86. Yangon7. Ashgabat  15. Bishkek  23. Dili        31. Hong_Kong    39. Kamchatka  47. Kuching       55. Novokuznetsk  63. Qostanay    71. Srednekolymsk  79. Tomsk        87. Yekaterinburg8. Atyrau    16. Brunei   24. Dubai       32. Hovd         40. Karachi    48. Kuwait        56. Novosibirsk   64. Qyzylorda   72. Taipei         80. Ulaanbaatar  88. Yerevan
Time zone: 69Current default time zone: 'Asia/Shanghai'
Local time is now:      Tue May 16 15:12:32 CST 2023.
Universal Time is now:  Tue May 16 07:12:32 UTC 2023.
Run 'dpkg-reconfigure tzdata' if you wish to change it.Setting up tzdata-icu (2023c-4exp1ubuntu1) ...
安装systemd进程管理器 和 init进程
apt install systemd init

安装tar

apt install tar
安装最新Linux内核

这时我们会看到很多的依赖包下载下来了,439M+。

安装过程种会有很多报错,需要安装其他依赖。

root@ubuntu:/# apt install linux-image-6.2.0-21-generic linux-headers-6.2.0-21-generic
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:adduser busybox-initramfs cpio dmsetup gettext-base grub-common grub-gfxpayload-lists grub-pc grub-pc-bin grub2-common initramfs-tools initramfs-tools-bin initramfs-tools-core klibc-utils kmodlibbrotli1 libdevmapper1.02.1 libefiboot1 libefivar1 libelf1 libfreetype6 libfuse3-3 libklibc libkmod2 libpng16-16 libssl3 libzstd1 linux-base linux-headers-6.2.0-21 linux-modules-6.2.0-21-genericos-prober systemd-hwe-hwdb ucf udev zstd
Suggested packages:liblocale-gettext-perl perl cron ecryptfs-utils libarchive-dev multiboot-doc grub-emu mtools xorriso desktop-base console-setup bash-completion fuse3 fdutils linux-doc | linux-source-6.2.0linux-tools linux-modules-extra-6.2.0-21-generic
The following NEW packages will be installed:adduser busybox-initramfs cpio dmsetup gettext-base grub-common grub-gfxpayload-lists grub-pc grub-pc-bin grub2-common initramfs-tools initramfs-tools-bin initramfs-tools-core klibc-utils kmodlibbrotli1 libdevmapper1.02.1 libefiboot1 libefivar1 libelf1 libfreetype6 libfuse3-3 libklibc libkmod2 libpng16-16 libssl3 linux-base linux-headers-6.2.0-21 linux-headers-6.2.0-21-genericlinux-image-6.2.0-21-generic linux-modules-6.2.0-21-generic os-prober systemd-hwe-hwdb ucf udev zstd
The following packages will be upgraded:libzstd1
1 upgraded, 36 newly installed, 0 to remove and 6 not upgraded.
Need to get 81.5 MB of archives.
After this operation, 439 MB of additional disk space will be used.
Do you want to continue? [Y/n]
安装NetworkManager网络管理

apt install network-manager
生成引导目录,安装efi引导

错误示范,和解决方法

# 出错示范,如果出现这个问题,需要一个带有EFI系系统,来修复这个efi,网络上种种使用bios修复,其实是使用了grub-bios引导。
# 解决方法是安装grub-pc-bin安装包,使用--removable 选项
root@ubuntu:/# grub-install --removable /dev/sda
Installing for i386-pc platform.
grub-install: warning: this GPT partition label contains no BIOS Boot Partition; embedding won't be possible.
grub-install: warning: Embedding is not possible.  GRUB can only be installed in this setup by using blocklists.  However, blocklists are UNRELIABLE and their use is discouraged..
grub-install: error: will not proceed with blocklists.apt install grub-pc-bin
apt install grub-efi-amd64
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB --recheck --no-floppygrub-install --target=x86_64-efi --bootloader-id=Shoulong --recheck --no-floppy
设置密码
passwd
重启测试

效果展示

可以看到根分区只有893M

在这里插入图片描述

总结脚本

快速挂载

mount /dev/sda2 /mnt/
mount /dev/sda1 /mnt/boot/efi/
for i in run sys proc dev dev/shm dev/pts; do echo "mount /$i"; mount --bind /$i /mnt/$i; done

最后,因为Linus大佬设计系统的兼容性真的是太好了,真的可以容器和宿主机之间随意变换。致敬大佬(鞠躬)。
这样就做成了不到800M+的一个系统,是不是比官方的mini版更加迷你呢?

有疑问或有需求或有工作推荐可以dd我。

这篇关于如何把Docker容器变成物理机系统的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/471861

相关文章

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

K8S(Kubernetes)开源的容器编排平台安装步骤详解

K8S(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是K8S容器编排平台的安装步骤、使用方式及特点的概述: 安装步骤: 安装Docker:K8S需要基于Docker来运行容器化应用程序。首先要在所有节点上安装Docker引擎。 安装Kubernetes Master:在集群中选择一台主机作为Master节点,安装K8S的控制平面组件,如AP

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

容器编排平台Kubernetes简介

目录 什么是K8s 为什么需要K8s 什么是容器(Contianer) K8s能做什么? K8s的架构原理  控制平面(Control plane)         kube-apiserver         etcd         kube-scheduler         kube-controller-manager         cloud-controlle

禅道Docker安装包发布

禅道Docker安装包发布 大家好, 禅道Docker安装包发布。 一、下载地址 禅道开源版:   /dl/zentao/docker/docker_zentao.zip  备用下载地址:https://download.csdn.net/download/u013490585/16271485 数据库用户名: root,默认密码: 123456。运行时,可以设置 MYSQL_ROOT_P

828华为云征文|华为云Flexus X实例docker部署rancher并构建k8s集群

828华为云征文|华为云Flexus X实例docker部署rancher并构建k8s集群 华为云最近正在举办828 B2B企业节,Flexus X实例的促销力度非常大,特别适合那些对算力性能有高要求的小伙伴。如果你有自建MySQL、Redis、Nginx等服务的需求,一定不要错过这个机会。赶紧去看看吧! 什么是华为云Flexus X实例 华为云Flexus X实例云服务是新一代开箱即用、体

docker-compose安装和简单使用

本文介绍docker-compose的安装和使用 新版docker已经默认安装了docker-compose 可以使用docker-compose -v 查看docker-compose版本 如果没有的话可以使用以下命令直接安装 sudo curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-c

01 Docker概念和部署

目录 1.1 Docker 概述 1.1.1 Docker 的优势 1.1.2 镜像 1.1.3 容器 1.1.4 仓库 1.2 安装 Docker 1.2.1 配置和安装依赖环境 1.3镜像操作 1.3.1 搜索镜像 1.3.2 获取镜像 1.3.3 查看镜像 1.3.4 给镜像重命名 1.3.5 存储,载入镜像和删除镜像 1.4 Doecker容器操作 1.4

Windows与linux中docker的安装与使用

windos中安装使用docker 下载Docker_Desktop 安装包进入docker官网下载Docker_Desktop: https://www.docker.com/ 启用wsl 我们搜索“启用或关闭Windows功能”,打开后勾选适用于Linux的Windows 子系统 Docker_Desktop设置 出现Docker Engine stopped的解决

docker学习系列(四)制作基础的base项目镜像--jdk+tomcat

前面已经完成了docker的安装以及使用,现在我们要将自己的javaweb项目与docker结合 1.1准备jdk+tomcat软件 ​​我下载了apache-tomcat-7.0.68.tar.gz和jdk-7u79-linux-x64.tar.gz,存储于Linux机器的本地目录/usr/ect/wt/下(利用xshell上传)。利用linux命令 tar -zxvf apache-tom