容器一词的英文是container,其实container还有集装箱的意思,集装箱绝对是商业史上了不起的一项发明,大大降低了海洋贸易运输成本。让我们来看看集装箱的好处:
集装箱之间相互隔离
长期反复使用
快速装载和卸载
规格标准,在港口和船上都可以摆放
现代软件开发的一大目的就是隔离,应用程序在运行时相互独立互不干扰,这种隔离实现起来是很不容易的,其中一种解决方案就是上面提到的虚拟机技术,通过将应用程序部署在不同的虚拟机中从而实现隔离。
现代软件开发的一大目的就是隔离,应用程序在运行时相互独立互不干扰,这种隔离实现起来是很不容易的,其中一种解决方案就是上面提到的虚拟机技术,通过将应用程序部署在不同的虚拟机中从而实现隔离。但是操作系统是一个很重而且很笨的程序,而每个虚拟机都要安装系统,无疑造成了资源的浪费,docker应运而生,与虚拟机通过操作系统实现隔离不同,容器技术只隔离应用程序的运行时环境但容器之间可以共享同一个操作系统,这里的运行时环境指的是程序运行依赖的各种库以及配置。
容器相比虚拟机更加的轻量级且占用的资源更少,与操作系统动辄几G的内存占用相比,容器技术只需数M空间,因此我们可以在同样规格的硬件上大量部署容器,这是虚拟机所不能比拟的,而且不同于操作系统数分钟的启动时间容器几乎瞬时启动,容器技术为打包服务栈提供了一种更加高效的方式
Docker 是一个开源的应用容器引擎,基于 Go 语言,并遵从Apache2.0协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
Docker 和传统虚拟化方式的不同之处,可见容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件层面实现。
Docker在整个开发周期都可以完美的辅助你实现快速交付。Docker允许开发者在装有应用和服务本地容器做开发。可以直接集成到可持续开发流程中。
例如:开发者可以使用一个标准的镜像来构建一套开发容器,开发完成之后,运维人员可以直接使用这个容器来部署代码。 Docker 可以快速创建容器,快速迭代应用程序,并让整个过程全程可见,使团队中的其他成员更容易理解应用程序是如何创建和工作的。 Docker 容器很轻很快!容器的启动时间是秒级的,大量地节约开发、测试、部署的时间。
Docker 容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。 这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个。
Docker的兼容性和轻量特性可以很轻松的实现负载的动态管理。你可以快速扩容或方便的下线的你的应用和服务,这种速度趋近实时。
Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。
使用 Docker,只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理。
Docker使用C/S架构,Client 通过接口与Server进程通信实现容器的构建,运行和发布。client和server可以运行在同一台集群,也可以通过跨主机实现远程通信。
文件系统隔离:每个进程容器运行在完全独立的根文件系统里。
资源隔离:可以使用cgroup为每个进程容器分配不同的系统资源,例如CPU和内存。
网络隔离:每个进程容器运行在自己的网络命名空间里,拥有自己的虚拟接口和IP地址。
写时复制:采用写时复制方式创建根文件系统,这让部署变得极其快捷,并且节省内存和硬盘空间。
日志记录:Docker将会收集和记录每个进程容器的标准流(stdout/stderr/stdin),用于实时检索或批量检索。
变更管理:容器文件系统的变更可以提交到新的映像中,并可重复使用以创建更多的容器。无需使用模板或手动配置。
交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上,例如运行一个一次性交互
shell。
虚拟化技术依赖物理CPU和内存,是硬件级别的;而docker构建在操作系统上,利用操作系统的containerization技术,所以docker甚至可以在虚拟机上运行
虚拟化系统一般都是指操作系统镜像,比较复杂,称为“系统”;而docker开源而且轻量,称为“容器”,单个容器适合部署少量应用,比如部署一个redis、一个memcached。
传统的虚拟化技术使用快照来保存状态;而docker在保存状态上不仅更为轻便和低成本,而且引入了类似源代码管理机制,将容器的快照历史版本一一记录,切换成本很低。
传统的虚拟化技术在构建系统的时候较为复杂,需要大量的人力;而docker可以通过Dockfile来构建整个容器,重启和构建速度很快。更重要的是Dockfile可以手动编写,这样应用程序开发人员可以通过发布Dockfile来指导系统环境和依赖,这样对于持续交付十分有利。
Dockerfile可以基于已经构建好的容器镜像,创建新容器。Dockerfile可以通过社区分享和下载,有利于该技术的推广。Docker会像一个可移植的容器引擎那样工作。它把应用程序及所有程序的依赖环境打包到一个虚拟容器中,这个虚拟容器可以运行在任何一种 Linux服务器上。这大大地提高了程序运行的灵活性和可移植性,无论需不需要许可、是在公共云还是私密云、是不是裸机环境等等。
LXC(LinuX Containers)Linux容器,一种操作系统层虚拟化技术,为Linux内核容器功能的一个用户空间接口。它将应用软件系统打包成一个软件容器(Container),内含应用软件本身的代码,以及所需要的操作系统核心和库。透过统一的名字空间和共享API来分配不同软件容器的可用硬件资源,创造出应用程序的独立沙箱运行环境,使得Linux用户可以容易的创建和管理系统或应用容器。
在Linux内核中,提供了cgroups功能,来达成资源的隔离。它同时也提供了名称空间隔离的功能,使应用程序看到的操作系统环境被区隔成独立区间,包括进程树,网络,用户id,以及挂载的文件系统。但是cgroups并不一定需要启动任何虚拟机。
LXC利用cgroups与名称空间的功能,提供应用软件一个独立的操作系统环境。LXC不需要Hypervisor这个软件层,软件容器(Container)本身极为轻量化,提升了创建虚拟机的速度。
而Docker本质来说不是容器,而是容器的管理工具,最初的Docker也是基于LXC实现的。
LXC关键技术点:
经过实践目前lxc无法在centos8上使用,所以我们以centos7为
lxc-checkconfig
//检查系统环境是否满足容器使用要求;
lxc-create
//创建lxc容器;
格式:lxc-create -n NAME -t TEMPLATE_NAME
lxc-start
//启动容器;
格式:lxc-start -n NAME -d
lxc-info
//查看容器相关的信息;
格式:lxc-info -n NAME
lxc-console
//附加至指定容器的控制台;
格式:lxc-console -n NAME -t NUMBER
lxc-stop
//停止容器;
lxc-destory
//删除处于停机状态的容器;
lxc-snapshot
//创建和恢复快照;
//退出容器方式:
//安装一个epel源
[root@localhost ~]# yum -y install epel-release
//安装LXC软件包和依赖包
[root@localhost ~]# yum -y install lxc lxc-templates bridge-utils lxc-libs libcgroup libvirt perl debootstrap
lxc #主程序包
lxc-templates #lxc的配置模板
bridge-utils #网桥管理工具
lxc-libs #lxc所需的库文件
libcgroup #cgroup是为Linux内核提供任务聚集和划分的机制,通过一组参数集合将一些任务组织成一个或多个子系统。
libvirt #管理Linux的虚拟化功能所需的服务器端守护程序。 需要针对特定驱动程序的管理程序。
//启动服务
[root@localhost ~]# systemctl start lxc libvirtd
[root@localhost ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 5 192.168.122.1:53 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
//查看状态
[root@localhost ~]# systemctl status lxc
● lxc.service - LXC Container Initialization and Autoboot Code
Loaded: loaded (/usr/lib/systemd/system/lxc.service; disabled; vendor preset: disabled)
Active: active (exited) since 三 2021-12-01 14:58:51 CST; 2min 9s ago
Process: 6068 ExecStart=/usr/libexec/lxc/lxc-autostart-helper start (code=exited, status=0/SUCCESS)
Process: 6060 ExecStartPre=/usr/libexec/lxc/lxc-devsetup (code=exited, status=0/SUCCESS)
Main PID: 6068 (code=exited, status=0/SUCCESS)
12月 01 14:58:21 localhost.localdomain systemd[1]: Starting LXC Container Initialization and Autoboot Code...
12月 01 14:58:21 localhost.localdomain lxc-devsetup[6060]: Creating /dev/.lxc
12月 01 14:58:21 localhost.localdomain lxc-devsetup[6060]: /dev is devtmpfs
12月 01 14:58:21 localhost.localdomain lxc-devsetup[6060]: Creating /dev/.lxc/user
12月 01 14:58:51 localhost.localdomain lxc-autostart-helper[6068]: Starting LXC autoboot containers: [ 确定 ]
12月 01 14:58:51 localhost.localdomain systemd[1]: Started LXC Container Initialization and Autoboot Code.
//检查系统是否满足容器使用要求
[root@localhost ~]# lxc-checkconfig
Kernel configuration not found at /proc/config.gz; searching...
Kernel configuration found at /boot/config-3.10.0-862.el7.x86_64
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
newuidmap is not installed
newgidmap is not installed
Network namespace: enabled
Multiple /dev/pts instances: enabled
--- Control groups ---
Cgroup: enabled
Cgroup clone_children flag: enabled
Cgroup device: enabled
Cgroup sched: enabled
Cgroup cpu account: enabled
Cgroup memory controller: enabled
Cgroup cpuset: enabled
--- Misc ---
Veth pair device: enabled
Macvlan: enabled
Vlan: enabled
Bridges: enabled
Advanced netfilter: enabled
CONFIG_NF_NAT_IPV4: enabled
CONFIG_NF_NAT_IPV6: enabled
CONFIG_IP_NF_TARGET_MASQUERADE: enabled
CONFIG_IP6_NF_TARGET_MASQUERADE: enabled
CONFIG_NETFILTER_XT_TARGET_CHECKSUM: enabled
--- Checkpoint/Restore ---
checkpoint restore: enabled
CONFIG_FHANDLE: enabled
CONFIG_EVENTFD: enabled
CONFIG_EPOLL: enabled
CONFIG_UNIX_DIAG: enabled
CONFIG_INET_DIAG: enabled
CONFIG_PACKET_DIAG: enabled
CONFIG_NETLINK_DIAG: enabled
File capabilities: enabled
Note : Before booting a new kernel, you can check its configuration
usage : CONFIG=/path/to/config /usr/bin/lxc-checkconfig
//查看当前系统中可用的LXC模板容器
[root@localhost ~]# ls /usr/share/lxc/templates/
lxc-alpine lxc-busybox lxc-debian lxc-gentoo lxc-oracle lxc-ubuntu
lxc-altlinux lxc-centos lxc-download lxc-openmandriva lxc-plamo lxc-ubuntu-cloud
lxc-archlinux lxc-cirros lxc-fedora lxc-opensuse lxc-sshd
//创建LXC容器
[root@localhost ~]# lxc-create -t centos -n myhost1
Copy /var/cache/lxc/centos/x86_64/7/rootfs to /var/lib/lxc/myhost1/rootfs ...
Copying rootfs to /var/lib/lxc/myhost1/rootfs ...//生成虚拟系统的根,文件默认路径在/var/lib/lxc/myhost1下
sed:无法读取 /var/lib/lxc/myhost1/rootfs/etc/init/tty.conf:没有那个文件或目录
Storing root password in '/var/lib/lxc/myhost1/tmp_root_pass'
chpasswd:无法打开 /etc/passwd
正在终止用户 root 的密码。
passwd: Libuser error at line: 425 - Error replacing `/etc/passwd': 权限不够.
passwd: 错误
sed:无法读取 /var/lib/lxc/myhost1/rootfs/etc/rc.sysinit:没有那个文件或目录
sed:无法读取 /var/lib/lxc/myhost1/rootfs/etc/rc.d/rc.sysinit:没有那个文件或目录
Container rootfs and config have been created.
Edit the config file to check/enable networking setup.
The temporary root password is stored in:
'/var/lib/lxc/myhost1/tmp_root_pass' //这个文件保存了主机的初始root密码
The root password is set up as expired and will require it to be changed
at first login, which you should do as soon as possible. If you lose the
root password or wish to change it without starting the container, you
can change it from the host by running the following command (which will
also reset the expired flag):
chroot /var/lib/lxc/myhost1/rootfs passwd //可以使用这个命令修改初始root密码
//lxc主机所生成的文件默认路径在/var/lib/lxc/主机名/目录下
[root@localhost ~]# tree /var/lib/lxc/mytest/ -L 1
/var/lib/lxc/myhost1/
├── config
├── rootfs
└── tmp_root_pass
//修改密码,这里遇到点问题,需要关闭防火墙selinux,不然修改不了 换了一个主机,密码要8位以上
[root@localhost ~]# chroot /var/lib/lxc/mytest/rootfs passwd
更改用户 root 的密码 。
新的 密码:
重新输入新的 密码:
passwd:所有的身份验证令牌已经成功更新。
//启动
[root@localhost ~]# lxc-start -n mytest
systemd 219 running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN)
Detected virtualization lxc.
Detected architecture x86-64.
Welcome to CentOS Linux 7 (Core)!
Running in a container, ignoring fstab device entry for /dev/root.
Cannot add dependency job for unit display-manager.service, ignoring: Unit not found.
[ OK ] Reached target Remote File Systems.
[ OK ] Started Forward Password Requests to Wall Directory Watch.
[ OK ] Reached target Local Encrypted Volumes.
[ OK ] Created slice Root Slice.
[ OK ] Listening on /dev/initctl Compatibility Named Pipe.
[ OK ] Listening on Journal Socket.
[ OK ] Created slice System Slice.
Starting Read and set NIS domainname from /etc/sysconfig/network...
[ OK ] Listening on Delayed Shutdown Socket.
[ OK ] Created slice User and Session Slice.
[ OK ] Reached target Slices.
Starting Remount Root and Kernel File Systems...
Starting Journal Service...
[ OK ] Created slice system-getty.slice.
Mounting POSIX Message Queue File System...
[ OK ] Started Dispatch Password Requests to Console Directory Watch.
[ OK ] Reached target Paths.
Mounting Huge Pages File System...
[ OK ] Reached target Swap.
[ OK ] Started Journal Service.
[ OK ] Mounted POSIX Message Queue File System.
[ OK ] Mounted Huge Pages File System.
[ OK ] Started Read and set NIS domainname from /etc/sysconfig/network.
[ OK ] Started Remount Root and Kernel File Systems.
Starting Flush Journal to Persistent Storage...
[ OK ] Reached target Local File Systems (Pre).
Starting Configure read-only root support...
Starting Rebuild Hardware Database...
<46>systemd-journald[16]: Received request to flush runtime journal from PID 1
[ OK ] Started Flush Journal to Persistent Storage.
[ OK ] Started Configure read-only root support.
Starting Load/Save Random Seed...
[ OK ] Reached target Local File Systems.
Starting Rebuild Journal Catalog...
Starting Create Volatile Files and Directories...
Starting Mark the need to relabel after reboot...
[ OK ] Started Load/Save Random Seed.
[ OK ] Started Rebuild Journal Catalog.
[ OK ] Started Mark the need to relabel after reboot.
[ OK ] Started Create Volatile Files and Directories.
Starting Update UTMP about System Boot/Shutdown...
[ OK ] Started Update UTMP about System Boot/Shutdown.
[ OK ] Started Rebuild Hardware Database.
Starting Update is Completed...
[ OK ] Started Update is Completed.
[ OK ] Reached target System Initialization.
[ OK ] Listening on D-Bus System Message Bus Socket.
[ OK ] Reached target Sockets.
[ OK ] Reached target Basic System.
Starting Permit User Sessions...
Starting Login Service...
Starting LSB: Bring up/down networking...
Starting OpenSSH Server Key Generation...
[ OK ] Started D-Bus System Message Bus.
[ OK ] Started Daily Cleanup of Temporary Directories.
[ OK ] Reached target Timers.
[ OK ] Started Permit User Sessions.
Starting Cleanup of Temporary Directories...
[ OK ] Started Command Scheduler.
[ OK ] Started Console Getty.
[ OK ] Reached target Login Prompts.
[ OK ] Started Login Service.
[ OK ] Started Cleanup of Temporary Directories.
[ OK ] Started OpenSSH Server Key Generation.
CentOS Linux 7 (Core)
Kernel 3.10.0-862.el7.x86_64 on an x86_64
mytest login: root //输入之前创建的账户密码
Password:
[root@mytest ~]#
[root@mytest ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether fe:e5:ea:0c:fb:4b brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.122.202/24 brd 192.168.122.255 scope global dynamic eth0
valid_lft 3533sec preferred_lft 3533sec
inet6 fe80::fce5:eaff:fe0c:fb4b/64 scope link
valid_lft forever preferred_lft forever
[root@mytest ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 17G 3.9G 14G 23% /
devtmpfs 476M 0 476M 0% /dev
tmpfs 488M 0 488M 0% /dev/shm
tmpfs 488M 6.3M 482M 2% /run
tmpfs 488M 0 488M 0% /sys/fs/cgroup
tmpfs 98M 0 98M 0% /run/user/0
//可以ssh直接连接
[root@localhost ~]# ssh 192.168.122.202
The authenticity of host '192.168.122.202 (192.168.122.202)' can't be established.
ECDSA key fingerprint is SHA256:hvfEka4oBUjMvE38Yju9sAuRhNM/6lRSWjIp7KoPTWE.
ECDSA key fingerprint is MD5:d3:81:8c:55:72:f7:29:3d:68:67:dc:63:9d:c0:ec:7d.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.122.202' (ECDSA) to the list of known hosts.
root@192.168.122.202's password:
Last login: Wed Dec 1 08:11:34 2021
[root@mytest ~]#