docker是一个用Go语言实现的开源项目,可以让我们方便的创建和使用容器,docker将程序以及程序所有的依赖都打包到docker container,这样你的程序可以在任何环境都会有一致的表现,这里程序运行的依赖也就是容器就好比集装箱,容器所处的操作系统环境就好比货船或港口,程序的表现只和集装箱有关系(容器),和集装箱放在哪个货船或者哪个港口(操作系统)没有关系。
因此我们可以看到docker可以屏蔽环境差异,也就是说,只要你的程序打包到了docker中,那么无论运行在什么环境下程序的行为都是一致的。
此外docker的另一个好处就是快速部署,这是当前互联网公司最常见的一个应用场景,一个原因在于容器启动速度非常快,另一个原因在于只要确保一个容器中的程序正确运行,那么你就能确信无论在生产环境部署多少都能正确运行。
Docker 的基础是 Linux 容器(LXC)等技术,在 LXC 的基础上 Docker 进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。
VM(VMware)在宿主机器、宿主机器操作系统的基础上创建虚拟层、虚拟化的操作系统、虚拟化的仓库,然后再安装应用;
Docker在宿主机器的操作系统上创建Docker引擎,直接在宿主主机的操作系统上调用硬件资源,而不是虚拟化操作系统和硬件资源,所以操作速度快。
我们都知道,操作系统分为 内核 和 用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统。
Docker 镜像 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像 不包含 任何动态数据,其内容在构建之后也不会被改变
因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。
分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。
前面讲过镜像使用的是分层存储,容器也是如此。每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为 容器存储层。
容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失
镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
一个 Docker Registry 中可以包含多个 仓库(Repository);每个仓库可以包含多个 标签(Tag);每个标签对应一个镜像。
docker诞生的目的就是实现轻量级的操作系统虚拟化解决方案
一款软件或服务产生的原因和背景有一定的原因是为了解决生产或工作环境中遇到的问题
生产、工作中产生的问题
开发和运维环境或配置不同,导致开发环境运行良好的交付产物在运维环境出问题,此类问题让人不胜其烦。
传统运维过程中,如果线上有十台机器,每台都需要重新部署一次,重复劳动。
配置应用环境不能跨平台。
多个应用安装到环境中可能会冲突,例如端口冲突。
软件包->发布(应用商店)->下载包->安装可用
软件包->打包带上环境(镜像)->Docker仓库:商店->下载发布的镜像->直接运行可用
docker的机制很好的解决了这些问题
通过传统方式使用容器功能的话需要我们自己写代码去进行系统调用来实现创建内核,实际上拥有此能力的人廖廖无几。而LXC(LinuX Container)把容器技术做得更加易用,把需要用到的容器功能做成一组工具,从而极大的简化用户使用容器技术的麻烦程度。
LXC是最早一批真正把完整的容器技术用一组简易使用的工具和模板来极大的简化了容器技术使用的一个方案。
LXC虽然极大的简化了容器技术的使用,但比起直接通过内核调用来使用容器技术,其复杂程度其实并没有多大降低,因为我们必须要学会LXC的一组命令工具,且由于内核的创建都是通过命令来实现的,通过批量命令实现数据迁移并不容易。其隔离性也没有虚拟机那么强大。
后来就出现了docker,所以从一定程度上来说,docker就是LXC的增强版。
环境说明:
系统版本 | ip地址 |
---|---|
centos 7.5 | 192.168.182.131 |
[root@localhost ~]# yum -y install epel-release //安装epel源
[root@localhost ~]# yum -y install lxc lxc-templates bridge-utils lxc-libs libcgroup libvirt perl debootstrap
lxc-templat //LXC的配置模板
bridge-utils //这个是网桥管理的工具包
lxc-libs //LXC所需要的库文件
libcgroup //cgroup是为linux内核提供任务聚集和划分的机制,通过一组参数集合将一些任务组织成一个或多个子系统。
libvirt //管理linux虚拟化功能所需要的服务器端的守护程序。需要针对特定驱动程序的管理程序。
[root@localhost ~]# systemctl start lxc
[root@localhost ~]# systemctl start libvirtd
[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-archlinux lxc-centos lxc-debian lxc-fedora lxc-openmandriva lxc-oracle lxc-sshd lxc-ubuntu-cloud
lxc-altlinux lxc-busybox lxc-cirros lxc-download lxc-gentoo lxc-opensuse lxc-plamo lxc-ubuntu
[root@localhost ~]# lxc-create -t centos -n myhost1 //创建LXC主机,-t 指定模板容器,-n 指定要创建的主机名
Copying rootfs to /var/lib/lxc/myhost1/rootfs ... #生成虚拟系统的根,文件默认路径在/var/lib/lxc/myhsot1下
/var/lib/lxc/myhost1/tmp_root_pass' #这个文件保存了主机的初始root密码
chroot /var/lib/lxc/myhost1/rootfs passwd #可以使用这个命令修改初始root密码
lxc主机所生成的文件默认路径在/var/lib/lxc/主机名/目录下
[root@localhost myhost1]# pwd
/var/lib/lxc/myhost1
[root@localhost myhost1]# ls
config rootfs tmp_root_pass
// config为配置文件
// rootfs为根目录
// tmp_root_pass root密码存放位置
[root@localhost myhost1]# chroot /var/lib/lxc/myhost1/rootfs/ passwd //修改初始密码
更改用户 root 的密码 。
新的 密码:
重新输入新的 密码:
passwd:所有的身份验证令牌已经成功更新。
[root@localhost myhost1]# lxc-start -n myhost1
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.
此处省略N行
myhost1 login: root #使用root用户登陆
Password: #输入设置的root密码
[root@myhost1 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 50G 2.3G 48G 5% /
devtmpfs 1.4G 0 1.4G 0% /dev
tmpfs 1.4G 0 1.4G 0% /dev/shm
tmpfs 1.4G 17M 1.4G 2% /run
tmpfs 1.4G 0 1.4G 0% /sys/fs/cgroup
tmpfs 280M 0 280M 0% /run/user/0
[root@myhost1 ~]# ip a //查看网卡的信息
1: lo: 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
5: eth0@if6: mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether fe:9f:2e:9a:ff:b5 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.122.118/24 brd 192.168.122.255 scope global dynamic eth0
valid_lft 3403sec preferred_lft 3403sec
inet6 fe80::fc9f:2eff:fe9a:ffb5/64 scope link
valid_lft forever preferred_lft forever
lxc-start -n myhost1 -d #在启动时添加-d选项可以把主机防止后台有运行
lxc-console -n myhost1 #使用lxc-console 进行连接
[root@localhost ~]# ssh [email protected]
[email protected]'s password: //可以使用ssh进行连接
[root@localhost myhost1]# lxc-info -n myhost1
Name: myhost1
State: RUNNING
PID: 1741
IP: 192.168.122.118
CPU use: 0.17 seconds
BlkIO use: 15.54 MiB
Memory use: 8.04 MiB
KMem use: 0 bytes
Link: veth55YWH2
TX bytes: 1.42 KiB
RX bytes: 6.19 KiB
Total bytes: 7.61 KiB
[root@localhost myhost1]# lxc-stop -n myhost1
[root@localhost myhost1]# lxc-clone -o myhost1 -n myhost2 //把myhost1克隆为名字为myhost2
Created container myhost2 as copy of myhost1
[root@localhost myhost1]# lxc-destroy -n myhost1
[root@localhost ~]# lxc-start -n myhost2
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)!
此处省略N行
myhost2 login: root
Password: //密码与myhost1相同
// lxc-create 创建一个系统对象
用法: lxc-create {-n name} [-f config_file] {-t template} [-B backingstore] [-- template-options]
// 选项
-n,--name #容器的主机名
-f,--config #指定配置文件以配置容器的虚拟化和隔离功能
-t template #调用模板脚本,可执行模板脚本的完整路径也可以作为参数传递。 “none”可用于强制lxc-create跳过rootfs创建。
-B backingstore #指定根文件储存路径的文件系统,可选:dir、lvm、loop、btrfs、zfs、best ,默认为dir,如果是dir可以使用--dir指定lxc主机的根在宿主机的存储路径。
-P, --lxcpath #自定义容器路径。默认值为/var/lib/lxc。
-o, --logfile #输出创建过程到一个日志文件中。
-l, --logpriority #将日志优先级设置为LEVEL,默认优先级为ERROR
-- #向template传递参数查看可选参数:lxc-create -t TEMPLATE -h,常用参数如下
-n,--name #容器标识符
-p,--path #指定容器根的创建路径,默认/var/lib/lxc/容器名/
-c,--clean #清除缓存
-R,--release #指定Centos的发行版本
--fqdn #用于DNS和系统命名的完全域名(FQDN)
--repo #指定创建容器是使用的yum源,这个是redhat系统的参数
-a,--arch #指定容器的架构,可选i686,x86_64
用法:lxc-destroy {-n name} [-f]
选项:-f, --force #强制删除
用法:lxc-start {-n name} [-f config_file] [-c console_device] [-L console_logfile] [-d] [-F] [-p pid_file] [-s KEY=VAL] [-C] [--share-[net|ipc|uts] name|pid] [command]
// 选项:
-n #指定容器名
-d, --daemon #后台运行
-F #前台运行,默认选项
-p, --pidfile #创建一个保存了pid的文件
-f, --rcfile #指定配置文件以配置容器的虚拟化和隔离功能。覆盖现有配置文件。
c, --console #指定一个前台运行容器的终端。不指定默认为当前终端。
-L, --console-log #把容器控制台输入保存到一个文件中。
-C, --close-all-fds #如果任何文件描述符被继承,关闭它们。 如果未指定此选项,则lxc-start将退出而失败。 注意:--daemon意味着--close-all-fds。
--share-net name|pid #从其他容器继承网络名称空间。
--share-ipc #从其他容器继承IPC命名空间。
--share-uts #从其他容器继承UTS命名空间。
// 选项:
-r,--reboot #重启容器
-s,--shutdown #设置定时关闭容器,使用-t 设置关闭时间。
-k,--kill #关闭容器
// 选项:
-r,--reboot #重启容器
-k,--kill #关闭容器,默认选项
--nokill #挂起容器
--nolock #此选项避免使用任何API lxc锁定。
// 选项:
-s #显示状态
-p #显示pid
-i #显示IP地址
-S #显示内存使用
-H #显示原始数值
-t #指定连接的tty
-o,--orig #要克隆的原始容器的名称
-n #新容器的名称
-p, --lxcpath #原始容器的系统文件路径,不选使用系统默认路径
-P, --newpath #新容器的系统文件路径
-K, --keepname #保留原容器的主机名
-M, --keepmac #使用和原容器相同的mac地址
lxc-checkconfig #检查当前内核lxc支持
lxc-config
lxc-monitor
lxc-top #容器统计信息
lxc-usernsexec #以root用户身份在容器内运行任务
可以使用-m 选项指定用户的uid以该用户的身份运行命令
lxc-freeze #冻结容器内运行的所有进程。
lxc-unfreeze #解冻容器内运行的所有进程。
lxc-execute #在指定的容器内运行指定的命令。
lxc-wait
lxc-snapshot #创建,列出和还原容器快照。
快照文件默认保存在var /lib/lxc-snaps/容器名
-c,--comment file #将文件中的注释信息和快照关联
-d,--destroy #删除快照
-L,--list #列出所有快照
-C #显示快照注释信息
-r #恢复快照
newname #恢复快照时用于指定容器的名称。可选参数 ,如果没有给出任何名称,则原始容器将被破坏,并且恢复的容器将占据其位置.
注意:在aufs,overlayfs或zfs支持的快照的情况下,删除原始快照是不可能的
lxc-cgroup在相应子系统的容器cgroup中获取或设置状态对象(例如,'cpuset.cpus')的值(例如,'cpuset')。 如果没有指定[value],则显示状态对象的当前值; 否则设置。注意lxc-cgroup不会检查状态对象是否对运行的内核有效,或者对应的子系统包含在任何已安装的cgroup层次结构中
lxc-cgroup {-n name} {state-object} [value]
可用于在一组克隆的命名空间中运行任务。 此命令主要用于测试目的。 尽管它的名字,它始终使用克隆而不是非共享创建新的任务与新的命名空间。 除了测试内核回归之外,这应该没有区别。
-s namespaces #指定要附加到的命名空间
-u user #指定新任务应该成为的用户标识
-H hostname #在新容器中设置主机名。只有设置了UTSNAME命名空间才允许。
-i interfacename #将命名的界面移动到容器中。仅当NETWORK命名空间被设置时才允许。您可以多次指定此参数以将多个接口移动到容器中。
-d #守护程序,退出前不要等待容器退出
-M #在容器中挂载默认文件系统(/ proc / dev / shm和/ dev / mqueue)。如果设置MOUNT命名空间,则只有al-lowed。
lxc-attach在由name指定的容器内运行指定的命令。 容器lxc-attach在名称指定的容器内运行指定的命令。 容器必须已经运行。 如果未指定命令,则将在容器内查找运行lxc-attach的用户的当前默认shell,然后执行。 如果容器内没有这样的用户,或容器没有工作的nsswitch机制这将失败。
-n,--name #容器的名称
-a, --arch #指定内核运行的架构