目录
docker概述
Docker是一个用于开发,交付和运行应用程序的开放平台。Docker使您能够将应用程序与基础架构分开,从而可以快速交付软件。
是一个开源的应用容器引擎,让开发者可以打包方式封装应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或者windows机器上,也可以实现虚拟化。容器是完全使用沙箱机制(隔离机制),相互之间不会有任何接口。
Docker从一开始就以提供标准化的运行时环境为目标,真正做到"build once,runanywhere",可以将同一个构建版本用于开发、测试、预发布、生产等任何环境,并且做到了与底层操作系统的解耦(不吃操作系统)。在此基础上还进一步发展出了Caas(容器即服务)技术。
简单来说,Docker镜像是一个配置好了所需环境的操作系统,我们在自己的电脑上运行一个docker容器,相当于开启了一个新的操作系统。比如说,如果我们在一台windows系统的电脑上运行一个安装了ubuntu系统的docker镜像,就意味着我们可以进入一台ubuntu系统的电脑进行操作。
Docker的优势
环境隔离:Docker镜像就像一个个的集装箱,我们每一个“集装箱”里面运行的“系统环境”都是不一样的,而且也是互不干扰的。举个例子,其中一个“集装箱”内运行的是基于“UBUNTU”系统内核的开发环境,另一个“集装箱”内运行的是基于“CENTOS”系统内核的生产环境,然而这两个“集装箱”都可以运行在同一个“平台”上,无论这个“平台”是WINDOWS 还是 LINUX。
迁移方便: Docker将应用所需内容全部打包到一个容器中,然后在虚拟机、服务器或云之间迁移该容器,而无需重构应用。
docker的底层原理
通过cgroup和namespace构成docker的底层原理。
cgroup:资源控制,对cpu,io,内存等系统资源进行限制和度量。
namespace:通过六种命名空间完成容器之间的相互隔离
docker隔离的六个命名空间
docker通过隔离这六个命令空间确保容器之间互不影响。
mount:文件系统、挂载点隔离
user:操作进程的用户和用户组的隔离
pid:进程编号的隔离
uts:主机名和主机域的隔离
ipc:消息队列、内存、信号量的隔离
net:网络设备、网络协议栈、端口的隔离
docker的三大组件
镜像:一组资源集合,包含了应用程序软件包、应用程序相关的依赖包、运行应用程序所需要的基础环境(泛指操作系统环境),可以理解为容器的模板
容器:基于镜像的一种运行时状态
仓库:存放image镜像。仓库分共有仓库与私有仓库。共有仓库有docker hub,私有仓库需要自己搭建比如registry、harbor。
docker与虚拟机的区别
启动速度上:docker通过进程控制,启动速度为秒级,而虚拟机则通过操作系统管理,需要分钟级才能启动。
运行速度上:由于docker是直接运行在宿主机的内核上,所以性能接近宿主机的90%。虚拟机由于是虚拟化出来的,中间有一个抽象层,所以在性能上会有50%的损失。
磁盘占用:docker可以看作是一个轻量版虚拟机,所以占用空间不大几百M就可以,而虚拟机通过操作系统镜像安装,一般在3-4G。
数量:一台宿主机上可以运行成百上千个docker,但是虚拟机只能运行几十台(理论上)
隔离性:docker通过进程控制,属于进行级别的隔离,虚拟机属于系统级别,隔离的更彻底,相比来说更安全。
操作系统:只要支持docker引擎的都可以运行,主要是linux。虚拟机支持几乎所有操作系统
封装程度:docker只打包项目代码和依赖关系,共享宿主机内核。虚拟机拥有完整的操作系统,与宿主机隔离,封装程度更高。
与此同时,docker运行会带有服务运行所需的依赖环境,解决了虚拟机的环境孤岛问题。
docker的网络模式
host模式:host容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口,如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的NetworkNamespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是dockerhost上已经使用的端口就不能再用了,网络的隔离性不好。
container模式:container创建的容器不会创建自己的网卡、设置IP等,而是和一个指定地容器共享IP、端口范围。这个模式指定新创建的容器和已经存在的一个容器共享一个network namespace,而不是和宿主机共享,新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定地容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表还是隔离的。
none模式:这种网络模式下容器只有lo回环网口,没有其他的网卡。none模式可以在容器创建时通过-network=none参数指定,这种网络类型无法联网,但是能很好保证容器的安全性,一般不单独使用。
bridge模式:该模式会为每一个容器分配、设置IP等,并将容器连接到一个docker虚拟网桥,通过dockero 网桥及iptables.的 nat,表配置与宿主机通信当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。从dockerO子网中分配一个IP给容器使用,并设置dockero的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair 设备,Docker将 veth pair 设备的一端放在新创建的容器中,并命名为etho(容器的网卡),另一端放在主机中,以vethxxx.这样类似的名字命名,并将这个网络设备加入到docker0 网桥中。可以通过brctl show命令查看。bridge模式是docker 的默认网络模式,不写-net参数,就是bridge模式。使用docker run -p时, docker实际是在iptables, 做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -knL查看。
docker的数据管理
docker有两种数据管理方式,数据卷和数据卷容器。数据卷通过在容器中创建数据卷并将宿主机的目录挂载到数据卷,可以让用户在不登录容器的情况下对容器中的数据进行查看修改等操作。
数据卷容器用于容器与容器之间的数据共享,容器1创建数据卷后,容器2在运行时–volus-from指定容器1,也就是将容器1的数据卷挂载到容器2,完成容器间的数据共享。
docker镜像的分层
一个能够被容器使用的镜像由多个小镜像组成,这些小镜像分为镜像层、环境层、应用层、应用的配置文件、应用的启动脚本等、work工作层。每层镜像都会做一个缓存,然后提供给上层镜像使用,比如环境层提供依赖环境给应用层手工编译服务。每层的镜像的缓存最终由work工作层整合并保存在本地同时清空缓存以减少镜像大小。
如果其中一个镜像层的配置发生更改,work工作层保存的缓存失效,那么会重新加载该镜像层的缓存然后基于这层镜像的缓存进行缓存复用(一层一层往上复用),最后汇总到work层,然后work层更新这个镜像大小。修改之后会生成一个全新镜像。
docker部署
安装依赖包
[root@c1 ~]# yum -y install device-mapper=persistent-data lvm2
设置阿里云镜像源
[root@c1 ~]# cd /etc/yum.repos.d/
[root@c1 yum.repos.d]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安装docker社区版
[root@c1 yum.repos.d]# yum -y install docker-ce
启动docker
[root@c1 yum.repos.d]# systemctl start docker
[root@c1 yum.repos.d]# systemctl enable docker
docker的命令
查看docker版本
[root@c1 ~]# docker -v
Docker version 20.10.8, build 3967b7d
查看镜像
[root@c1 ~]# docker images
名称 标签 镜像id 创建时间 大小
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 822b7ec2aaf2 21 hours ago 133MB
查看容器
[root@c1 ~]# docker ps -a
容器id 镜像名 启动脚本 创建时间 容器状态 端口 名称
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cd39c892b54f hello-world "/hello" 25 seconds ago Exited (0) 24 seconds ago strange_diffie
创建容器
docker create -it 镜像名:标签 /bin/bash -i让容器的标准输入保持打开,-t分配一个伪终端用户可以登录docker容器
[root@c1 ~]# docker create -it nginx:latest /bin/bash
3d938668909a8727a404c6f1f4439656bb0b85c9b82eef5af37e0df3f7138bd9
启动镜像,start后面跟的是容器的id或容器的名字
[root@c1 ~]# docker start cd39c892b54f
cd39c892b54f
[root@c1 ~]# docker start strange_diffie
strange_diffie
拉取镜像,从私有仓库或共有仓库将镜像下载至本地,可以看到一个镜像由多个小镜像组成
[root@c1 ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
a330b6cecb98: Pull complete
5ef80e6f29b5: Pull complete
f699b0db74e3: Pull complete
0f701a34c55e: Pull complete
3229dce7b89c: Pull complete
ddb78cb2d047: Pull complete
Digest: sha256:a05b0cdd4fc1be3b224ba9662ebdf98fe44c09c0c9215b45f84344c12867002e
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
docker run启动镜像,如果本地没有这个镜像则回去私有/共有仓库拉取镜像并创建容器然后运行该镜像
查找镜像,会从仓库中寻找含有该镜像的镜像文件
docker search 镜像名
查看镜像的详细信息
docker inspect 镜像名
docker info查看容器信息
添加镜像标签
[root@c1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 822b7ec2aaf2 24 hours ago 133MB
hello-world latest d1165f221234 6 months ago 13.3kB
[root@c1 ~]# docker tag nginx:latest nginx:lnmp
[root@c1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 822b7ec2aaf2 24 hours ago 133MB
nginx lnmp 822b7ec2aaf2 24 hours ago 133MB
hello-world latest d1165f221234 6 months ago 13.3kB
删除镜像
docker rmi 镜像名:镜像标签 docker rmi -f 强制删除镜像
[root@c1 ~]# docker rmi nginx:lnmp
Untagged: nginx:lnmp
[root@c1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 822b7ec2aaf2 24 hours ago 133MB
hello-world latest d1165f221234 6 months ago 13.3kB
删除容器 强制删除容器
docker rm 容器id docker rm -f 容器id
指定容器的网络模式,创建容器时指定
[root@c1 ~]# docker create -it nginx:lnmp /bin/bash -net=host
807dc556e6a32924073ac4e87ba9c80d192ce1c520f9f6d254b35e17994a8e8b
[root@c1 ~]# docker create -it nginx:lnmp /bin/bash -net=container:nginx
daae3044c7e98e9cdf2f35f37350aee1bc8329d67427f2deda2cfaeff2d8560a
[root@c1 ~]# docker create -it nginx:lnmp /bin/bash -net=container:none
6fccff6fe8510f8ea7719d39b2e1dc93777f9a7a2dc617185cf18bc9d8fc6d3e
[root@c1 ~]# docker create -it nginx:lnmp /bin/bash -net=container:bridge
be81be54c1077611c8fd0800f9f5f81351b703b5e5775bce60fde1d2e88fe266
查看网络列表
docker network ls
查看容器信息 包含配置、环境、网关、挂载、cmd等等信息
docker inspect容器id
指定分配容器ip地址
docker run -itd --name test1 --network bridge --ip 172.17.0.10 centos:latest /bin/bash(以上会报错)
自定义网络固定ip
docker network create --subnet=172.18.0.0/16 mynetwork
docker run -itd --name test2 --net mynetwork --ip 172.18.0.100 centos:latest /bin/bash
暴露端口
docker run -itd -p 333:80 nginx /bin/bash ( docker 0)
docker run -itd -P nginx / bin/bash
dockerfile制作镜像
[root@localhost ~]# cd ~
#上传软件包
[root@localhost ~]# ls
apache-tomcat-9.0.16.tar.gz jdk-8u91-linux-x64.tar.gz
[root@localhost ~]# vim Dockerfile-v1
FROM centos:7 #基于centos7镜像制作
ADD jdk-8u91-linux-x64.tar.gz /usr/local/ #将jdk包放到docker的/usr/local/目录下并解压 ADD上传文件包含上传、解压的步骤
ENV JAVA_HOME /usr/local/jdk1.8.0_91 #设置全局变量
ENV JRE_HOME ${JAVA_HOME}/jre
ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
ENV PATH $JAVA_HOME/bin:$PATH
ADD apache-tomcat-9.0.16.tar.gz /usr/local/ #将tomcat软件包放在/usr/local/
EXPOSE 8080 #开放8080端口
CMD ["/usr/local/apache-tomcat-9.0.16/bin/catalina.sh","run"] #使用catalina.sh启动tomcat,并通过run持续运行
#通过dockerfile文件制作tomcat镜像
[root@localhost ~]# docker build -f Dockerfile-v1 -t tomcat:new1 . -f指定文件 -t指定镜像名和标签 "."表示在宿主机的当前目录下查找软件包
#创建容器并运行
[root@localhost ~]# docker run -itd -P --name tomcat tomcat:new1
02201c3c724975fdaf84a1871992a9db643a8642f9085d7944c798a9908273f4
[root@localhost ~]# docker ps -a #查看容器状态
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
02201c3c7249 tomcat:new1 "/usr/local/apache-t…" 14 hours ago Up 14 hours 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp inspiring_lamport
3d938668909a nginx:latest "/docker-entrypoint.…" 2 days ago Created ecstatic_gould
cd39c892b54f hello-world "/hello" 2 days ago Exited (0) 2 days ago strange_diffie
访问192.168.218.215:8080