Docker初体验
一、什么是Docker
Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机)、bare metal、OpenStack 集群和其他的基础应用平台。
- Docker is the world’s leading software containerization platform.
- Docker公司开发,开源,托管在github
- 跨平台,支持Windows、Mac、Linux
Docker的思想来自于集装箱,集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来。并且各种各样的货物被集装箱标准化了,集装箱和集装箱之间不会互相影响。那么我就不需要专门运送水果的船和专门运送化学品的船了。只要这些货物在集装箱里封装的好好的,那我就可以用一艘大船把他们都运走。docker就是类似的理念。现在都流行云计算了,云计算就好比大货轮。docker就是集装箱。1.不同的应用程序可能会有不同的应用环境,比如.net开发的网站和php开发的网站依赖的软件就不一样,如果把他们依赖的软件都安装在一个服务器上就要调试很久,而且很麻烦,还会造成一些冲突。比如IIS和Apache访问端口冲突。这个时候你就要隔离.net开发的网站和php开发的网站。常规来讲,我们可以在服务器上创建不同的虚拟机在不同的虚拟机上放置不同的应用,但是虚拟机开销比较高。docker可以实现虚拟机隔离应用环境的功能,并且开销比虚拟机小,小就意味着省钱了。2.你开发软件的时候用的是Ubuntu,但是运维管理的都是centos,运维在把你的软件从开发环境转移到生产环境的时候就会遇到一些Ubuntu转centos的问题,比如:有个特殊版本的数据库,只有Ubuntu支持,centos不支持,在转移的过程当中运维就得想办法解决这样的问题。这时候要是有docker你就可以把开发环境直接封装转移给运维,运维直接部署你给他的docker就可以了。而且部署速度快。3.在服务器负载方面,如果你单独开一个虚拟机,那么虚拟机会占用空闲内存的,docker部署的话,这些内存就会利用起来。总之docker就是集装箱原理。
作者:刘允鹏
链接:https://www.zhihu.com/question/28300645/answer/67707287
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
那个大鲸鱼(或者是货轮)就是操作系统把要交付的应用程序看成是各种货物,原本要将各种各样形状、尺寸不同的货物放到大鲸鱼上,你得为每件货物考虑怎么安放(就是应用程序配套的环境),还得考虑货物和货物是否能叠起来(应用程序依赖的环境是否会冲突)。现在使用了集装箱(容器)把每件货物都放到集装箱里,这样大鲸鱼可以用同样地方式安放、堆叠集装了,省事省力。Docker就是这整套机制啦
作者:周宇刚
链接:https://www.zhihu.com/question/28300645/answer/50922662
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
二、Docker历史
三年前的云计算,提到最多的关键字无疑是IaaS(Infrastructure-as-a-Service,基础设施即服务)。企业往往通过IaaS技术建立起信息化的数据中心,有效地管理池化资源。如果历史的发展仅仅满足于此,那么科技也就会停滞不前。
当时,在加州湾区以Solomon Hykes为首的几位天才工程师就在尝试,能否在资源之上,架构出一套完善的分布式平台,有效快速帮助用户的应用系统平稳运行。他们的公司实体也就是Docker的前身dotCloud。经历了一段时间的试水之后,历史并未遂这群极客的愿,dotCloud云战略的运营并非成功。
然而,常言道,失败是成功之母,这句话印证在dotCloud身上再适合不过。失利的同时,Solomon敏锐地嗅探到了,dotCloud体系的中的容器技术,反倒是解决了目前市场上用户应用构建、分发和发布的诸多痛点。痛定思痛,Solomom迅速技术转型,开始投向容器技术,并从一开始就开源,当时就吸引了为数不少的开发者。
时间定格在2013年3月,容器技术定名为Docker,原力诞生。
三、理解Docker
1. Docker解决了什么问题
1. 我在本地运行的没问题呀
2. 系统好卡,那个哥们又写了死循环
3. 双11来了,服务器撑不住了
2. Docker的好处
- 可以在同一个主机上运行多个应用程序,而应用程序的运行环境彼此隔离,互不干扰
- 可以充分利用主机的计算和存储资源
- 新机器只需要安装docker并导入构建好的镜像就可以完成程序部署,免去了繁琐的安装和配置工作,维护成本大大降低
3. Docker应用场景
请参照:
四、走进Docker
1. Docker镜像
要理解Docker镜像和docker容器之间的区别,确实不容易。
假设Linux内核是第0层,那么无论怎么运行Docker,它都是运行于内核层之上的。这个Docker镜像,是一个只读的镜像,位于第1层,它不能被修改或不能保存状态。
一个Docker镜像可以构建于另一个Docker镜像之上,这种层叠关系可以是多层的。第1层的镜像层我们称之为基础镜像(Base Image),其他层的镜像(除了最顶层)我们称之为父层镜像(Parent Image)。这些镜像继承了他们的父层镜像的所有属性和设置,并在Dockerfile中添加了自己的配置。
Docker镜像通过镜像ID进行识别。镜像ID是一个64字符的十六进制的字符串。但是当我们运行镜像时,通常我们不会使用镜像ID来引用镜像,而是使用镜像名来引用。要列出本地所有有效的镜像,可以使用命令
# docker images
镜像可以发布为不同的版本,这种机制我们称之为标签(Tag)。
如上图所示,neo4j镜像有两个版本:lastest版本和2.1.5版本。
可以使用pull命令加上指定的标签:
# docker pull ubuntu:14.04
# docker pull ubuntu:12.04
2. Docker容器
Docker容器可以使用命令创建:
# docker run imagename
它会在所有的镜像层之上增加一个可写层。这个可写层有运行在CPU上的进程,而且有两个不同的状态:运行态(Running)和退出态(Exited)。这就是Docker容器。当我们使用docker run启动容器,Docker容器就进入运行态,当我们停止Docker容器时,它就进入退出态。
当我们有一个正在运行的Docker容器时,从运行态到停止态,我们对它所做的一切变更都会永久地写到容器的文件系统中。要切记,对容器的变更是写入到容器的文件系统的,而不是写入到Docker镜像中的。
我们可以用同一个镜像启动多个Docker容器,这些容器启动后都是活动的,彼此还是相互隔离的。我们对其中一个容器所做的变更只会局限于那个容器本身。
如果对容器的底层镜像进行修改,那么当前正在运行的容器是不受影响的,不会发生自动更新现象。
如果想更新容器到其镜像的新版本,那么必须当心,确保我们是以正确的方式构建了数据结构,否则我们可能会导致损失容器中所有数据的后果。
64字符的十六进制的字符串来定义容器ID,它是容器的唯一标识符。容器之间的交互是依靠容器ID识别的,由于容器ID的字符太长,我们通常只需键入容器ID的前4个字符即可。当然,我们还可以使用容器名,但显然用4字符的容器ID更为简便。
五、安装Docker
个人推荐的是Ubuntu上安装Docker
Ubuntu
系统要求:64-bit OS and version3.10
检查内核的版本
更新apt-get
系统自带的安装方式
这是系统自带的安装Docker的方式,有可能就是Docker不是最新版本的。
Docker官方提供的方式,可以安装最新版本
安装是否成功,进行验证
Docker 体验1 —— Hello World
Docker在国内的镜像仓库
https://c.163.com/hub#/m/home/
第一个dockerr镜像
// 在docker上拉取镜像
docker pull [OPTIONS] NAME[:TAG]
// 查看本机docker的所有镜像
docker images [OPTIONS] [REPOSITORY[:TAG]]
// TAG:镜像的版本
// OPTION 属性
第一个docker容器
// 运行一个docker容器
docker run [OPTION] IMAGE[:TAG] [COMMAND][ARG...]
// TAG:镜像的版本
// COMMAND:执行的命令
// ARG:参数
拉取helloworld镜像
docker pull hub.c.163.com/dengyakui/helloworld:latest
运行helloworld镜像的结果
docker run hub.c.163.com/dengyakui/helloworld
如果出现这个界面说明安装正常。
并且Docker执行了下列4个过程:
1. Docker客户端连接上Docker daemon。
2. 从Docker daemon从Docker Hub上拉去hello-world镜像。
3. Docker daemon创建一个容器从那个镜像,这个容器运行了一个可执行的文件,可执行文件产生当前的输出。
4. Docker daemon将输出变为输出流并且输出到Docker Client,然后将Docker Client发送到我们的终端。
分为三个部分,最左边是docker client,在执行命令时使用。中间的一部分是由Docker daemon管理的服务。最右边则不在我们的本机,相对于helloworld来说,就是docker的远程仓库。
第一条命令:docker pull,首先向Docker daemon发送这样一条命令,docker daemon先检查在本机是否存在这样一个镜像。如果存在并且想要的版本是你所拉取的版本,就不会做任何的操作。如果不存在,则会到docker仓库中找我们想要拉取的镜像名字。如果找到了,就会把镜像拉取到本地。
第二条命令:docker run,将命令发送到本地的Docker daemon,Docker daemon就会检查该镜像是否在本机存在,如果不存在,则会执行一个docker pull的命令,去docker仓库将镜像下载回来。镜像然后通过一定的方式运行起来,编程docker的容器。
以上就是docker执行这两条命令所经历的过程。
Docker 体验2 —— Nginx服务
体验前奏:
1. 持久运行的容器
2. 前台挂起&后台运行
3. 进入容器内部
1. 从163镜像中心下载一个nginx镜像
docker pull hub.c.163.com/library/nginx:latest
查看docker中正在运行的镜像
docker ps
查看docker执行时的命令帮助
进入到容器中的内部
常用的命令:
docker 停止服务
Docker stop ‘container ID’ // 加上容器Id具体常见命令请参考:
ocker常用命令 & 坑
docker网络
在这一小节主要是为了可以在外面的主机上访问到在Docker上面创建的Nginx镜像。
1. 网络类型:
Brige、Host、None
Docker在一般的情況下会分配一个独立的Network Space也就是网络类型中的Brige模式。——桥接
如果启动容器时特别的指定为Host模式,则Docker在启动的时候就不会分配一个network space而是和主机共同使用一个,现在容器就不会再虚拟出一个网卡,配置自己的IP等。而是会使用宿主机上的IP和端口,也就是说在Docker上使用网络跟在主机上使用的网络是一样的。
None类型则是Docker不会也外界进行任何的通信。
2. 端口映射
如果再用了Brige的模式,有自己独立的network space就涉及到一个技术,使容器内的端口,可以在主机上访问到,这个技术就是端口的映射。
Docker可以使容器内的一个端口,在容器所在的主机上的一个端口之间做一个映射。再访问主机上这个端口时就是访问容器里面的这个端口。
Docker run -p/-P 的区别
-p开放一个端口到host主机
-P开放所有的端口到一个随机的端口
这张图解释了docker的网络模式,eht0是主机的网卡,在Host模式下,直接与主机的模式相连,和主机使用同一块网卡,所以说在主机上看到的网络与主机上的网络完全相同。
中间的就是bridge模式,在中间创建一个docker0(bridge)网桥,网桥与eth0主机网卡相连,在启动容器的时候,容器会虚拟一个eth0的网卡与网桥相连,通过这样与主机相互通信。这样的容器有自己的IP,也有自己的端口。
后台运行Nginx镜像,并且开放80端口到host机的8080端口上
docker run -d -p 8080:80 hub.c.163.com/library/nginx
Docker 体验3 —— 自定义镜像
制作自己的镜像
准备条件:
* Dockerfile*
Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令。docker程序将这些Dockerfile指令翻译真正的linux命令。Dockerfile有自己书写格式和支持的命令,Docker程序解决这些命令间的依赖关系,类似于Makefile。Docker程序将读取Dockerfile,根据指令生成定制的image。相比image这种黑盒子,Dockerfile这种显而易见的脚本更容易被使用者接受,它明确的表明image是怎么产生的。有了Dockerfile,当我们需要定制自己额外的需求时,只需在Dockerfile上添加或者修改指令,重新生成image即可,省去了敲命令的麻烦。docker build命令
build 主要用于建立一个新的image,也就是属于你自己的image
Usage: docker build [OPTIONS] PATH | URL |-Build a new image from the source code at PATH–force-rm=falseAlways remove intermediate containers, even after unsuccessful builds
–no-cache=falseDonotuse cache when building the image
-q,–quiet=falseSuppress the verbose output generated by the containers
–rm=trueRemove intermediate containers after a successful build
-t,–tag=”“Repository name (and optionally a tag) to be applied to the resulting image incase of success自己的镜像war包
在这里我们以Jpress开源的博客。
Jpress: http://jpress.io/
步骤:
1. 下载Jpress war包
2. 在与war包同样的位置添加Dockerfile文件。
```
from hub.c.163.com/library/tomcat
MAINTAINER liuzhenqing liuzhenqing173@163.com
COPY jpress.war /usr/local/tomcat/webapps
// 第1行 ==》需要的镜像文件
// 第2行 ==》当前自定义文件的用户名与联系方式
// 第3行 ==》将jpress.war 赋值到tomcat下
```
3. 在当前目录下自动构建镜像
在当前目录下自动构建镜像,并且命名为jpress
可以看到自定义的docker命名为jpress
4. 启动docker 并且映射端口
netstat -na|grep 8888 查看8888端口是否开放
5. 开启Mysql镜像,并且端口号为3306,密码为000000,在创建一个数据库jpress