1. docker 是什么2. docker 解决什么问题1. 解决虚拟机资源消耗问题。2. 快速部署。3. 提供一次性的环境。4. 提供弹性的云服务。5. 组建微服务架构。3. docker 安装部署与使用1. 安装 docker 引擎2. 使用 docker1. 理解 docker 的架构2. docker 命令3. 卷的概念4. 自制镜像并发布4. docker 网络6. docker pipework7. docker 网络端口映射4. 总结php
docker 可能会改变软件行业java
你们都知道虚拟机吧,windows 上装个 linux 虚拟机是大部分程序员的经常使用方案。公司生产环境大多也是虚拟机,虚拟机将物理硬件资源虚拟化,按需分配和使用,虚拟机使用起来和真实操做系统如出一辙,当废弃不用时直接删除虚拟机文件便可回收资源,很方便集中管理。node
因为虚拟机很是庞大,同时对硬件资源的消耗也大,linux 发展出了另外一种虚拟化技术,即 linux 容器(Linux Containers,缩写为 LXC),它并不像虚拟机那样模拟一个完整的操做系统,却提供虚拟机同样的效果。若是说虚拟机是操做系统级别的隔离,那么容器就是进程级别的隔离,能够想象这种级别隔离的优势,无疑是快速的,节省资源的。linux
docker 就是对 linux 容器的封装,提供简单实用的用户接口,是目前最流行的 linux容器解决方案。nginx
下面是百科的定义:git
docker 是基于 Go 语言的开源的应用容器引擎,并听从Apache2.0协议,docker 让开发者能够打包他们的应用以及依赖包到一个可移植的容器中,而后发布到任何流行的 linux 机器上,也能够实现虚拟化。容器是彻底使用沙箱机制,相互之间不会有任何接口。程序员
服务器操做系统之上运行着虚拟机,虚拟机上运行着客户操做系统,客户操做系统之上运行着用户的应用程序,一台服务器 80% 的资源开销都花费在了硬件虚拟化和客户机操做系统自己。github
如图 1 所示,若是采用 docker 容器技术,容器上运行着虚拟服务器,虚拟服务器中运行着用户的应用程序,虚拟服务器和服务器操做系统使用同一内核,虚拟服务器的文件系统使用物理服务器的文件系统,但作了隔离,看上去每一个虚拟服务器都有本身独立的文件系统;在物理服务器上创建了虚拟网桥设备,每一个虚拟服务器经过虚拟网桥设备链接网络。虚拟服务器直接使用物理服务器的CPU、内存、硬盘,并不对硬件进行虚拟化,所以没有硬件虚拟化和客户机操做系统占用的资源消耗,每一台虚拟服务器的性能接近于物理服务器性能。web
一台普通家用电脑运行一个 Linux 虚拟机可能已经很是卡,可是却可使用 docker 虚拟出几十甚至上百台虚拟的 linux 服务器。若是换成性能强劲的服务器,使用 docker 就能够提供私有云服务了。docker
软件开发的难题在于环境配置,在本身电脑上运行的软件,换一台机器可能就没法运行,除非保证操做系统的设置正确,各类组件和库的正确安装。好比部署一个 Java 开发的 web 系统,计算机必须安装 Java 和正确的环境变量,可能还须要安装 tomcat、nginx。换台机器部署就要重来一次。
使用 docker 能够将应用程序及依赖打包在一个文件里(docker 镜像文件),运行这个文件就会启动虚拟服务器,在虚拟服务器启动应用程序或服务,就像在真实在物理机上运行同样,有了 docker,就能够一次部署,到处运行,也能够用于自动化发布。
好比,本地测试他人的软件、持续集成的时候提供单元测试和构建的环境,启动或关闭一个虚拟服务器就像启动或关闭一个进程同样简单和快速。
由于 Docker 容器能够随开随关,很适合动态扩容和缩容。
经过多个容器,一台机器能够跑不少个虚拟服务器,所以在一台机器上就能够模拟出微服务架构,也能够模拟出分布式架构。
本文介绍 ubuntu 18.04 系统下的安装与使用。其余操做系统请参考官方文档https://docs.docker.com/。
获取最新版本的 Docker 安装包
aaron@ubuntu:~$ wget -qO- https://get.docker.com/ | sh
执行上述命令,输入当前用户密码,便可自动下载最新版的 docker 安装包,并自动安装。
安装完成后有个提示:
If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:
sudo usermod -aG docker aaron
Remember that you will have to log out and back in for this to take effect!
WARNING: Adding a user to the "docker" group will grant the ability to run
containers which can be used to obtain root privileges on the
docker host.
Refer to https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface
for more information.
当要以非 root 用户能够直接运行 docker 时,须要执行
sudo usermod -aG docker aaron
命令将用户 aaron 添加到 docker 用户组中,而后从新登录,不然会报下面的错误:
docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.38/containers/create: dial unix /var/run/docker.sock: connect: permission denied.
See 'docker run --help'.
执行下列命令启动 docker 引擎
aaron@ubuntu:~$ sudo service docker start
安装成功后已默认设置开机启动并自动启动,若是要手动设置,执行下面命令:
sudo systemctl enable docker
sudo systemctl start docker
测试运行
aaron@ubuntu:~$ sudo docker run hello-world
使用前先了解下 docker 的架构,以下图所示:
docker 镜象(image) 是存放在 docker 仓库(Registry)的文件,是用于建立 docker 容器 的模板。
docker 容器 是独立运行的一个或一组应用,能够理解为前述介绍的虚拟服务器。
docker 主机 是一个物理或者虚拟的机器用于执行 docker 守护进程和容器。
docker 客户端 经过命令行或者其余工具使用 docker API 与 docker 的守护进程通讯。
做为用户,咱们直接使用的是 docker 客户端。
查看docker 命令的帮助信息
docker --help #docker 所有命令帮助信息
docker COMMAND --help #docker 具体命令COMMAND的帮助信息
查看docker 信息
docker info
能够看到容器的池、已用数据大小、总数据大小,基本容器大小、当前运行容器数量等。
搜索镜像,从网络中搜索别人作好的容器镜像。
docker search ubuntu
docker search centos
从网络中下载别人作好的容器镜像。
docker pull centos
docker pull ubuntu
导入下载好的容器镜像文件
docker load < image_xxx.tar
查看镜像
docker images
docker images -a
检查镜像
docker inspect ubuntu
能够看到容器镜像的基本信息。
删除镜像,经过镜像的 id 来指定删除
docker rmi ubuntu
删除所有镜像
docker rmi $(docker images -q)
显示镜像历史
docker history ubuntu
运行容器
Docker容器能够理解为在沙盒中运行的进程,这个沙盒包含了该进程运行所必须的资源,包括文件系统、系统类库、shell 环境等。但这个沙盒默认是不会运行任何程序的,须要在沙盒中运行一个进程来启动某一个容器。这个进程是该容器的惟一进程,因此当该进程结束的时候,容器也会彻底中止。
运行 ubuntu 容器并进入交互式环境
aaron@ubuntu:~$ docker run -i --name="ubuntu1" --hostname="ubuntu1" ubuntu /bin/sh
cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 ubuntu1
whoami
root
uname -a
Linux ubuntu1 4.15.0-34-generic #37-Ubuntu SMP Mon Aug 27 15:21:48 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
上述命令咱们建立了一个名字为 ubuntu1 的容器,设置容器的主机名为 ubuntu1,进入 /bin/sh 命令后咱们打印了 hosts 文件的内容,查看了内核版本(与本机操做系统版本一致),这里可使用各类 linux 命令,就像在新的操做系统中使用命令一个样。一样的方法,咱们在新的终端建立一个 ubuntu2 的容器,并使用
docker ps
查看正在运行的容器。
docker run -d ubuntu
会出现一串长的字母数字组成的串,为容器的 id,请注意容器要有持续运行的进程存在,不然,容器会很快自动退出。
运行容器并指定MAC地址
docker run -d --name='centos3' --hostname='centos3' --mac-address="02:42:AC:11:00:24" docker-centos6.10-hadoop-spark
列出全部的容器
docker ps -a
列出最近一次启动的容器
docker ps -l
检查容器
docker inspect centos1
能够获取容器的相关信息。
获取容器CID
docker inspect -f '{{.Id}}' centos1
获取容器PID
docker inspect -f '{{.State.Pid}}' centos1
获取容器IP
docker inspect -f '{{.NetworkSettings.IPAddress}}' centos1
获取容器网关
docker inspect -f '{{.NetworkSettings.Gateway}}' centos1
获取容器 MAC
docker inspect -f '{{.NetworkSettings.MacAddress}}' centos1
查看容器 IP 地址
docker inspect -f '{{.NetworkSettings.IPAddress}}' centos1
链接容器
ssh 容器的 IP 地址
输入密码:123456
容器运行后,能够经过另外一种方式进入容器内部
docker exec -it centos /bin/sh
查看容器运行过程当中的日志
docker logs centos1
列出一个容器里面被改变的文件或者目录,列表会显示出三种事件,A 增长的;D 删除的;C 被改变的
docker diff centos1
和初始容器镜像项目,用户或系统增长/修改/删除了那些目录文件,均可以查看到。
查看容器里正在运行的进程
docker top centos1
拷贝容器里的文件/目录到本地服务器
docker cp centos1:/etc/passwd /tmp/
ls /tmp/passwd
经过网络 IP 地址也能够将容器的文件拷贝到服务器,这种方式比较方便。
中止容器
docker stop centos1
中止全部容器
docker kill $(docker ps -a -q)
启动容器
docker start centos1
删除单个容器
docker stop centos1
docker rm centos1
删除容器以前要先中止该容器的运行。
删除全部容器
docker kill $(docker ps -a -q)
docker rm $(docker ps -a -q)
为了可以保存(持久化)数据以及共享容器间的数据,docker 提出了卷的概念。卷 Volume 就是容器的特定目录,该目录下的文件保存在宿主机上,而不是容器的文件系统内。
数据卷是一个可供一个或多个容器使用的特殊目录,它绕过容器默认的文件系统,能够提供不少有用的特性:
(1)数据卷能够在容器之间共享和重用;
(2)对数据卷的修改会立马生效;
(3)对数据卷的更新,不会影响镜像;
(4)数据卷默认会一直存在,即便容器被删除。
注意:数据卷的使用,相似于 Linux下对目录进行挂载 mount,容器中被指定为挂载点的目录中的文件会隐藏掉,能显示看的是挂载的数据卷。
建立、使用数据卷
mkdir -p /root/volume1
mkdir -p /root/volume2
docker run -d -v /volume1 --name='centos5' docker-centos6.10-hadoop-spark
docker run -d -v /root/volume1:/volume1 --name='centos6' docker-centos6.10-hadoop-spark
docker run -d -v /root/volume1:/volume1 -v /root/volume2:/volume2 --name='centos7' docker-centos6.10-hadoop-spark
docker run -d -v /root/volume1:/volume1:ro --name='centos8' docker-centos6.10-hadoop-spark
使用docker run命令建立容器,指定 -v 标记来建立一个数据卷并挂载到容器里;能够挂载多个数据卷;能够设置卷的只读属性;能够不指定服务器映射的目录,由系统自动指定目录,经过 docker inspect 来查看映射的路径。
分别进入这些容器,查看 /volume一、/volume2目录。
数据卷共享
若是要受权一个容器访问另外一个容器的数据卷,可使用-volumes-from 参数来执行。
数据卷容器
若是有一些持续更新的数据须要在容器之间共享,最好建立数据卷容器。
数据卷容器,其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的。
(1)建立一个名为 dbdata 的数据卷容器
docker run -d -v /dbdata --name dbdata docker-centos6.10-hadoop-spark
(2)在其余容器中使用--volumes-from来挂载 dbdata 容器中的数据卷
docker run -d --volumes-from dbdata --name db1 docker-centos6.10-hadoop-spark
docker run -d --volumes-from dbdata --name db2 docker-centos6.10-hadoop-spark
这样就能够实现容器之间的数据共享。
分别进入这些容器,查看 /volume一、/volume2 目录。
保存容器修改,提交一个新的容器镜像
docker commit centos1 centos111
将现有的容器提交造成一个新的容器镜像,使用 docker images 能够看到 centos111 镜像。经过此方法,能够建立一个新的容器镜像。
查看镜像
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos111 latest d691a75ee371 23 minutes ago 501.5 MB
根据新容器镜像建立容器
docker run -d --name='centos111' centos111
查看容器
docker inspect centos111
导出和导入镜像
当须要把一台机器上的镜像迁移到另外一台机器的时候,须要导出镜像与导入镜像。
机器A
docker save docker-centos6.10-hadoop-spark > docker-centos6.10-hadoop-spark2.tar
或
docker save -o docker-centos6.10-hadoop-spark docker-centos6.10-hadoop-spark2.tar
使用 scp 命令同其余方式将 docker-centos6.10-hadoop-spark2.tar 拷到机器 B 上
机器B
docker load < docker-centos6.10-hadoop-spark2.tar
或
docker load -i docker-centos6.10-hadoop-spark2.tar
发布容器镜像
docker push centos6.8-lamp1
将容器发布到网络中。
docker 启动时会在宿主机器上建立一个名为 docker0 的虚拟网络接口。它会从RFC 1918 定义的私有地址中随机选择一个主机不用的地址和子网掩码,并将它分配给 docker0,默认选择 172.18.0.1/16,一个 16 位的子网掩码给容器提供了 65534 个 IP 地址。
docker0 并非正常的网络接口,只是一个在绑定到这上面的其余网卡间自动转发数据包的虚拟以太网桥,可使容器与主机相互通讯、容器与容器间相互通讯。
docker 每建立一个容器,就会建立一对对等接口(Peer Interface),相似于一个管子的两端,在一边能够收到另外一边发送的数据包。docker会将对等接口中的一个作为 eth0 接口链接到容器上,并使用相似于vethAQI2QT 这样的唯一名称来持有另外一个,该名称取决于主机的命名空间。经过将全部 veth* 接口绑定到 docker0 桥接网卡上,docker 在主机和全部 docker 容器间建立一个共享的虚拟子网。
docker NAT 网络
docker 容器默认经过 nat 方式访问网络,docker 启动时会在宿主主机上建立一个名为 docker0 的虚拟网络接口,docker0 只是一个在绑定到这上面的其余网卡间自动转发数据包的虚拟以太网桥,它可使容器和主机相互通讯、容器与容器间通讯。
docker0 的网关地址是172.18.0.1,掩码是 16 位,提供了 65534 个IP地址。
NAT 方式,虚拟器容器能够访问外网(宿主机之外),但宿主机之外的机器不能访问容器内网。
docker Bridage 网络
docker 容器能够经过 bridge 方式访问网络。
bridge方式,虚拟器容器能够访问外网(宿主机之外),宿主机之外的机器也能访问容器内网。
docker 自身的网络功能比较简单,不能知足不少复杂的应用场景。所以有不少开源项目用来改善 docker 的网络功能,如 pipework、weave、flannel 等。
pipework 是由 docker 的工程师 Jérôme Petazzoni 开发的一个 docker 网络配置工具,由 200 多行 shell 实现,方便易用。
安装 pipework
git clone https://github.com/jpetazzo/pipework
cp pipework/pipework /bin/
或
wget [http://172.17.1.240/docker/software/pipework](http://172.17.1.240/docker/software/pipework)
chmod a+x pipework
cp pipework /bin/
运行容器
docker run -d --net='none' --name='centos9' docker-centos6.10-hadoop-spark
配置容器网络,并连到网桥 docker0 上;网关在IP地址后面加 @ 指定。
pipework docker0 centos9 172.18.0.100/16@172.18.0.1
容器若是使用 docker0 虚拟网络,那么容器的网络是 172.17.0.0/16,容器能够经过 NAT 方式访问外网;但外网不能访问内网。若是容器使用 br0 虚拟网络,容器和服务器能够在同一个网络地址段;容器能够访问外网;外网也能够访问容器网络。
对于使用 docker0 虚拟网络的容器,能够经过端口映射的方式,让外网访问容器某些端口。
运行容器
docker run -d -p 38022:22 --name='centos10' docker-centos6.10-hadoop-spark
链接容器
ssh localhost -p 38022
在其余服务器上经过访问物理服务器加端口便可访问容器,能够一次映射多个端口。
运行容器
docker run -d -p 38022:22 -p 38080:80 --name='centos11' docker-centos6.10-hadoop-spark
其实现原理是在服务器上经过 iptables 转发来实现。固然也能够经过iptables 转发整个容器 IP 地址。
因为容器是进程级别的,相比虚拟机有不少优点。
(1)启动快
容器里面的应用,直接就是底层系统的一个进程,而不是虚拟机内部的进程。因此,启动容器至关于启动本机的一个进程,而不是启动一个操做系统,速度就快不少。
(2)资源占用少
容器只占用须要的资源,不占用那些没有用到的资源;虚拟机因为是完整的操做系统,不可避免要占用全部资源。另外,多个容器能够共享资源,虚拟机都是独享资源。
(3)体积小
容器只要包含用到的组件便可,而虚拟机是整个操做系统的打包,因此容器文件比虚拟机文件要小不少。
总之,容器有点像轻量级的虚拟机,可以提供虚拟化的环境,可是成本开销小得多。