程序员人生 网站导航

Docker学习总结(5)——超实用Docker入门学习教程

栏目:互联网时间:2016-06-15 07:55:58

Docker是甚么

Docker是1种容器技术,它可以将利用和环境等进行打包,构成1个独立的,类似于iOS的APP情势的“利用”,这个利用可以直接被分发到任意1个支持Docker的环境中,通过简单的命令便可启动运行。Docker是1种最流行的容器化实现方案。和虚拟化技术类似,它极大的方便了利用服务的部署;又与虚拟化技术不同,它以1种更轻量的方式实现了利用服务的打包。使用Docker可让每一个利用彼此相互隔离,在同1台机器上同时运行多个利用,不过他们彼此之间同享同1个操作系统。Docker的优势在于,它可以在更细的粒度上进行资源的管理,也比虚拟化技术更加节俭资源。

超实用Docker入门学习教程!

上图:虚拟化和Docker架构对照,来自Docker官网

基本概念

开始实验Docker之前,我们先来了解1下Docker的几个基本概念:

镜像:我们可以理解为1个预配置的系统光盘,这个光盘插入电脑后就能够启动1个操作系统。固然由因而光盘,所以你没法修改它或保存数据,每次重启都是1个原样全新的系统。Docker里面镜像基本上和这个差不多。

容器:一样1个镜像,我们可以同时启动运行多个,运行期间的产生的这个实例就是容器。把容器内的操作和启动它的镜像进行合并,就能够产生1个新的镜像。

开始

Docker基于LXC技术实现,依赖于Linux内核,所以Docker目前只能在Linux以原生方式运行。目前主要的Linux发行版在他们的软件仓库中内置了Docker:

Ubuntu:

  • Ubuntu Trusty 14.04 (LTS)

  • Ubuntu Precise 12.04 (LTS)

  • Ubuntu Saucy 13.10

CentOS:

  • CentOS 7

Docker要求64位环境,这些操作系统下可以直接通过命令安装Docker,老1些操作系统Docker官方也提供了安装方案。下面的实验基于CentOS 7进行。关于其他版本操作系统上Docker的安装,请参考官方文档:https://docs.docker.com/installation/

在CentOS 7上安装Docker

使用yum从软件仓库安装Docker:

yum install docker 首先启动Docker的守护进程:service docker start 如果想要Docker在系统启动时运行,履行:chkconfig docker on Docker在CentOS上好像和防火墙有冲突,利用防火墙规则后可能致使Docker没法联网,重启Docker可以解决。

Docker仓库

Docker使用类似git的方式管理镜像。通过基本的镜像可以定制创建出来不同种利用的Docker镜像。Docker Hub是Docker官方提供的镜像中心。在这里可以很方便地找到各类利用、环境的镜像。

由于Docker使用联合文件系统,所以镜像就像是夹心饼干1样1层层构成,相同底层的镜像可以同享。所以Docker还是相当节俭磁盘空间的。要使用1 个镜像,需要先从远程的镜像注册中心拉取,这点非常类似git。

docker pull ubuntu 我们很容易就可以从Docker Hub镜像注册中心下载1个最新版本的ubuntu镜像到本地。国内网络可能会稍慢,DAOCLOUD提供了Docker Hub的国内加速服务,可以尝试配置使用。

运行1个容器

使用Docker最关键的1步就是从镜像创建容器。有两种方式可以创建1个容器:使用docker create命令创建容器,或使用docker run命令运行1个新容器。两个命令并没有太大差别,只是前者创建后其实不会立即启动容器。

以ubuntu为例,我们启动1个新容器,并将ubuntu的Shell作为入口:

docker run -i -t ubuntu /bin/bash这时候候我们成功创建了1个Ubuntu的容器,并将当前终端连接为这个Ubuntu的bash shell。这时候候就能够愉快地使用Ubuntu的相干命令了~可以快速体验1下。

参数-i表示这是1个交互容器,会把当前标准输入重定向到容器的标准输入中,而不是终止程序运行。-t指为这个容器分配1个终端。

好了,按Ctrl+D可以退出这个容器了。

在容器运行期间,我们可以通过docker ps命令看到所有当前正在运行的容器。添加-a参数可以看到所有创建的容器:

docker ps -a [root@localhost ~]# docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

cb2b06c83a50 ubuntu:latest "sh -c /bin/bash" 7 minutes ago Exited (0) 7 seconds ago trusting_morse

每一个容器都有1个唯1的ID标识,通过ID可以对这个容器进行管理和操作。在创建容器时,我们可以通过–name参数指定1个容器名称,如果没有指定系统将会分配1个,就像这里的“trusting_morse”(甚么鬼TAT)。

当我们按Ctrl+D退出容器时,命令履行完了,所以容器也就退出了。要重新启动这个容器,可使用docker start命令:

docker start -i trusting_morse 一样,-i参数表示需要交互式支持。

注意:每次履行docker run命令都会创建新的容器,建议1次创建后,使用docker start/stop来启动和停用容器。

存储

在Docker容器运行期间,对文件系统的所有修改都会以增量的方式反应在容器使用的联合文件系统中,其实不是真实的对只读层数据信息修改。每次运行容器对它的修改,都可以理解成对夹心饼干又添加了1层奶油。这层奶油仅供当前容器使用。当删除Docker容器,或通过该镜像重新启动时,之前的更改将会丢失。这样做其实不便于我们持久化和同享数据。Docker的数据卷这个东西可以帮到我们。

在创建容器时,通过-v参数可以指定将容器内的某个目录作为数据卷加载:

docker run -i -t -v /home/www ubuntu:latest sh -c '/bin/bash' 在容器中会多1个/home/www挂载点,在这个挂载点存储数据会绕过联合文件系统。我们可以通过下面的命令来找到这个数据卷在主机上真实的存储位置:docker inspect -f {{.Volumes}} trusting_morse 你会看到输出了1个指向到/var/lib/docker/vfs/dir/...的目录。cd进入后你会发现在容器中对/home/www的读写创建,都会反应到这儿。事实上,/home/www就是挂载自这个位置。

有时候,我们需要将本地的文件目录挂载到容器内的位置,一样是使用数据卷这1个特性,-v参数格式为:

docker run -it -v [host_dir]:[container_dir]

host_dir是主机的目录,container_dir是容器的目录.

容器和容器之间是可以同享数据卷的,我们可以单独创建1些容器,寄存如数据库持久化存储、配置文件1类的东西,但是这些容器其实不需要运行。

docker run --name dbdata ubuntu echo "Data container."在需要使用这个数据容器的容器创建时–volumes-from [容器名]的方式来使用这个数据同享容器。

网络

Docker容器内的系统工作起来就像是1个虚拟机,容器内开放的端口其实不会真正开放在主机上。可使我们的容器更加安全,而且不会产生容器间端口的争用。想要将Docker容器的端口开放到主机上,可使用类似端口映照的方式。

在Docker容器创建时,通过指定-p参数可以暴露容器的端口在主机上:

docker run -it -p 22 ubuntu sh -c '/bin/bash' 现在我们就将容器的22端口开放在了主机上,注意主机上对应端口是自动分配的。如果想要指定某个端口,可以通过-p [主机端口]:[容器端口]参数指定。

容器和容器之间想要网络通讯,可以直接使用–link参数将两个容器连接起来。例如WordPress容器对some-mysql的连接:

docker run --name some-wordpress --link some-mysql:mysql -p 8080:80 -d wordpress 环境变量

通过Docker打包的利用,对外就像是1个密闭的exe可履行文件。有时候我们希望Docker能够使用1些外部的参数来使用容器,这时候候参数可以通过环境变量传递进去,通常情况下用来传递比如MySQL数据库连接这类的东西。环境变量通过-e参数向容器传递:

docker run --name some-wordpress -e WORDPRESS_DB_HOST=10.1.2.3:3306 \

-e WORDPRESS_DB_USER=... -e WORDPRESS_DB_PASSWORD=... -d wordpress

关于Docker到现在就有了1个基本的认识了。接下来我会给大家介绍如何创建镜像。

创建镜像

Docker强大的威力在于可以把自己开发的利用随同各种依赖环境1起打包、分发、运行。要创建1个新的Docker镜像,通常基于1个已有的Docker镜像来创建。Docker提供了两种方式来创建镜像:把容器创建为1个新的镜像、使用Dockerfile创建镜像。

将容器创建为镜像

为了创建1个新的镜像,我们先创建1个新的容器作为基底:

docker run -it ubuntu:latest sh -c '/bin/bash' 现在我们可以对这个容器进行修改了,例如我们可以配置PHP环境、将我们的项目代码部署在里面等:apt-get install php

# some other opreations ...

当履行完操作以后,我们按Ctrl+D退出容器,接下来使用docker ps -a来查找我们刚刚创建的容器ID:docker ps -a 可以看到我们最后操作的那个ubuntu容器。这时候候只需要使用docker commit便可把这个容器变成1个镜像了:docker commit 8d93082a9ce1 ubuntu:myubuntu这时候候docker容器会被创建为1个新的Ubuntu镜像,版本名称为myubuntu。以后我们可以随时使用这个镜像来创建容器了,新的容器将自动包括上面对容器的操作。

如果我们要在另外1台机器上使用这个镜像,可以将1个镜像导出:

docker save -o myubuntu.tar.gz ubuntu:myubuntu 现在我们可以把刚才创建的镜像打包为1个文件分发和迁移了。要在1台机器上导入镜像,只需要:docker import myubuntu.tar.gz这样在新机器上就具有了这个镜像。

注意:通过导入导出的方式分发镜像其实不是Docker的最好实践,由于我们有Docker Hub。

Docker Hub提供了类似GitHub的镜像存管服务。1个镜像发布到Docker Hub不但可以供更多人使用,而且便于镜像的版本管理。关于Docker Hub的使用,以后我会单独写1篇文章展开介绍。另外,在1个企业内部可以通过自建docker-registry的方式来统1管理和发布镜像。将Docker Registry集成到版本管理和上线发布的工作流当中,还有许多工作要做,在我整理出最好实践后会第1时间分享。

使用Dockerfile创建镜像

使用命令行的方式创建Docker镜像通常难以自动化操作。在更多的时候,我们使用Dockerfile来创建Docker镜像。Dockerfile是1个纯文本文件,它记载了从1个镜像创建另外一个新镜像的步骤。撰写好Dockerfile文件以后,我们就能够轻而易举的使用docker build命令来创建镜像了.

Dockerfile非常简单,唯一以下命令在Dockerfile中常被使用:

超实用Docker入门学习教程!

下面是1个Dockerfile的例子:

# This is a commentFROM ubuntu:14.04 MAINTAINER Kate Smith <ksmith@example.com> RUN apt-get update &amp;&amp; apt-get install -y ruby ruby-dev

RUN gem install sinatra

这里其他命令都比较好理解,惟独CMD和ENTRYPOINT我需要特殊说明1下。CMD命令可用指定Docker容器启动时默许的命令,例如我们上面例子提到的docker run -it ubuntu:latest sh -c '/bin/bash'。其中sh -c '/bin/bash'就是通过手工指定传入的CMD。如果我们不加这个参数,那末容器将会默许使用CMD指定的命令启动。ENTRYPOINT是甚么呢?从字面看是进入点。没错,它就是进入点。ENTRYPOINT用来指定特定的可履行文件、Shell脚本,并把启动参数或CMD指定的默许值,当作附加参数传递给ENTRYPOINT。

不好理解是吧?我们举1个例子:

ENTRYPOINT ['/usr/bin/mysql']

CMD ['-h 192.168.100.128', '-p']

假定这个镜像内已准备好了mysql-client,那末通过这个镜像,不加任何额外参数启动容器,将会给我们1个mysql的控制台,默许连接到192.168.100.128这个主机。但是我们也能够通过指定参数,来连接别的主机。但是不管不管如何,我们都没法启动1个除mysql客户端之外的程序。由于这个容器的ENTRYPOINT就限定了我们只能在mysql这个客户端内做事情。这下是否是明白了~

因此,我们在使用Dockerfile创建文件的时候,可以创建1个entrypoint.sh脚本,作为系统入口。在这个文件里面,我们可以进行1些基础性的自举操作,比如检查环境变量,根据需要初始化数据库等等。下面两个文件是我在SimpleOA项目中添加的Dockerfile和entrypoint.sh,仅供参考:

  • https://github.com/starlight36/SimpleOA/blob/master/Dockerfile

  • https://github.com/starlight36/SimpleOA/blob/master/docker-entrypoint.sh

在准备好Dockerfile以后,我们就能够创建镜像了:docker build -t starlight36/simpleoa .关于Dockerfile的更详细说明,请参考 https://docs.docker.com/reference/builder/。

杂项和最好实践

在产品构建的生命周期里使用Docker,最好实践是把Docker集成到现有的构建发布流程里面。这个进程其实不复杂,可以在延续集成系统构建测试完成后,将打包的步骤改成docker build,延续集成服务将会自动将构建相应的Docker镜像。打包完成后,可以由延续集成系统自动将镜像推送到Docker Registry中。生产服务器可以直接Pull最新版本的镜像,更新容器便可很快地实现更新上线。目前Atlassian Bamboo已支持Docker的构建了。

由于Docker使用联合文件系统,所以其实不用担心屡次发布的版本会占用更多的磁盘资源,相同的镜像只存储1份。所以最好实践是在不同层次上构建Docker镜像。比如利用服务器依赖于PHP+Nginx环境,那末可以把定制好的这个PHP环境作为1个镜像,利用服务器从这个镜像构建镜像。这样做的好处是,如果PHP环境要升级,更新了这个镜像后,重新构建利用镜像便可完成升级,而不需要每一个利用项目分别升级PHP环境。

新手常常会有疑问的是关于Docker打包的粒度,比如MySQL要不要放在镜像中?最好实践是根据利用的范围和可预感的扩大性来肯定Docker打包的粒度。例如某小型项目管理系统使用LAMP环境,由于团队范围和使用人数其实不会有太大的变化(可预计的团队范围范围是几人到几千人),数据库也不会承受没法承载的记录数(生命周期内可能1个表最多会有数10万条记录),并且客户最关心的是快速部署使用。那末这时候候把MySQL作为依赖放在镜像里是1种不错的选择。固然如果你在为1个互联网产品打包,那最好就是把MySQL独立出来,由于MySQL极可能会单独做优化做集群等。

使用公有云构建发布运行Docker也是个不错的选择。DaoCloud提供了从构建到发布到运行的全生命周期服务。特别合适像微擎这类微信公众平台、或中小型企业CRM系统。上线周期更短,比使用IAAS、PAAS的云服务更具有优势。

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐