利用docker快速部署应用

标签: 利用 docker 应用 | 发表时间:2014-08-19 15:42 | 作者:snoopyxdy
出处:http://snoopyxdy.blog.163.com
最近研究了几天docker的快速部署,感觉很有新意,非常轻量级和方便,打算在公司推广一下,解放运维,省得每次部署一台新服务器都去跑安装脚本了,对于我们开发人员也是好事情,无需写太多重复的部署文档,直接将docker的images丢上服务器就可以运行了。
可能还有一些同学不了解docker这个项目,docker是一个快速部署的轻量级虚拟机项目,他允许开发人员将自己的程序的运行环境一起打包,制作成一个docker的image(镜像),这样部署到服务器上,也只需要下载这个image就可以将程序跑起来,免去每次都安装各种依赖和环境的麻烦,还能够做到应用程序之间的隔离,因为我们公司部署的python程序,这样一来我也省去了每次都配置 vitualenv了。
官网地址: http://www.docker.com/

一、安装:

安装很简单,直接进入下载页面,根据自己的操作系统下载相对应的安装包即可,下面说一下windows安装:

下载地址: https://docs.docker.com/installation/windows/

在安装docker时,会附带安装git和VirtualBox,所以可能安装时间稍微长一些,安装完毕重启系统,以管理员身份进入命令行,就可以使用进入linux虚拟机命令 "boot2docker" ,由于docker目前的镜像只针对linux,所以windows下面必须安装虚拟机才能使用。

第一次使用boot2docker start,会出现错误:

   

Failed to get machine "boot2docker-vm": machine does not exist

没关系,这是因为没有boot2docker iso的镜像所致,执行:   
    

boot2docker init

就可以初始化镜像,耐心等待下载并安装完毕后,我们继续执行开启虚拟机。     
     

boot2docker start

在windows下是无法直接使用cmd窗口来操作linux系统的,所以我们需要进入linux虚拟机来操作docker,执行:
   
    

boot2docker ssh

 就可以进入linux虚拟机,如果要退出并关闭虚拟机,执行如下命令:
    
     

exit
boot2docker stop
调试时查看虚拟机ip地址,后面部署测试环境会用到:
    
     

boot2docker ip
192.168.59.103
 如果不幸长时间无法init成功,说明镜像被GFW挡住了,手动去github上下载镜像,地址为:
    https://github.com/boot2docker/boot2docker/releases    
如果还是无法下载成功,我是好心人,把1.1.2版本的boot2docker.iso镜像丢到了百度云上:
    http://pan.baidu.com/s/1c01qieG
下载完毕之后放到目录:
    
     

C:\Users\你的用户名\.boot2docker\boot2docker.iso

然后再执行
     
      

$ boot2docker init

      
二、下载镜像,安装环境
我们先执行如下命令,启动虚拟机:
      
       

$ boot2docker start
2014/08/18 21:22:41 Waiting for VM to be started...        
...........
2014/08/18 21:23:21 Started.
2014/08/18 21:23:21 Docker client does not run on Windows for now. Please use
2014/08/18 21:23:21     "boot2docker" ssh
2014/08/18 21:23:21 to SSH into the VM instead.
如果我们的物理机内存低于4G,那么跑这个boot2docker可能需要手动设置内存占用大小:
       
        

boot2docker start -m=512

我们利用命令就可以进入linux虚拟机了
       
        

$ boot2docker ssh

                        ##        .
                  ## ## ##       ==
               ## ## ## ##      ===
           /""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
           \______ o          __/
             \    \        __/
              \____\______/
 _                 _   ____     _            _
| |__   ___   ___ | |_|___ \ __| | ___   ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
boot2docker: 1.1.2
master : 740106c - Thu Jul 24 03:24:10 UTC 2014

执行 docker 命令,会有一个命令列表,里面列出了所有 docker 支持的功能,列表如下:
        
         

Commands:          
    attach    Attach to a running container
    build     Build an image from a Dockerfile
    commit    Create a new image from a container's changes
    ... ...

下面会对一些常用的命令进行示例说明,我们可以通过如下命令,先查找centos的镜像,并把他下载下来
         
          

$ docker search centos #查找centos名字的镜像
$ docker pull centos #下载官方纯净版本的centos镜像
在调用search命令时,你会看到有好多centos包,他们都是这样的<username>/<image_name>,这些不在根目录的镜像都是非官方的,是其他用户提交到docker hub上去的,耐心等待片刻我们就可以将centos的镜像拉下来了。
如果脸黑,镜像又不幸被墙,那么试试加上下面的hosts:
          
           

54.234.135.251  get.docker.io
54.234.135.251  cdn-registry-1.docker.io

成功下载好centos镜像之后,我们可以利用如下命令来查看镜像列表:
           
            

docker images             
REPOSITORY          TAG                 IMAGE ID            CREATED
VIRTUAL SIZE
centos              centos6             b1bd49907d55        2 weeks ago
212.5 MB
centos              centos7             b157b77b1a65        2 weeks ago
243.7 MB
centos              latest              b157b77b1a65        2 weeks ago
243.7 MB

接下来我们就利用centos7这个镜像输出一段 hello world
            
             

$ docker run b15 /bin/echo 'Hello world'
Hello world

注意这里的 b15,他表示centos7这个images的id,不用全部打全,只要保证输入的id前几位能找到唯一镜像即可,这点很赞。
稍微复杂一点的例子:
            
             

docker run  -i -d -t b15 /bin/sh -c "while true; do echo hello world; sleep 1; done"

-i表示同步container的stdin,-t表示同步container的输出,-d表示deamon,以后台启动这个container,执行这个container是永远不会停止的,每一秒钟都会输出hello world。
至于什么是container,container和image的关系我们下一段再说。
             三、安装环境
在开始第三段介绍之前,有必要说几个利用windows cmd窗口的小技巧。
1、如果想要使用标记选中功能,你会发现,当我们进入 boot2docker ssh 之后,鼠标对窗口的右键是无效的,所以想要利用标记选中窗口内的文字得这么弄:“点击左上角图标->编辑->标记”,这样就可以使用标记了
2、如果从其他地方复制了命令,但是窗口没有右键无法粘贴怎么办?用和1相同的办法:“点击左上角图标->编辑->粘贴”。
3、坑爹的windws如果命令太长,在boot2docker ssh里换行会错位的,在“点击左上角图标->属性->布局->屏幕缓冲区大小和窗口大小”的数值,保证长的命令也在一行内就没有问题了,注意要重启cmd窗口。
 接下来我们简单说明一下image和container的关系,image顾名思义就是镜像的意思,我们把他理解为一个执行环境(env),当我们执行了docker run命令之后,dock就会根据当前的image创建一个新的container,container更像是一个操作或者程序运行的一个沙箱,他们互相独立,但是都运行在image创建的执行环境之上,根据上一段我们执行了2个run的任务,也就创建了2个独立的container,我们通过命令
             
              

docker ps #查看当前运行的container
docker ps -a #查看所有的container
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS                      PORTS               NAMES               
d1eca89869d0        centos:centos7      /bin/sh -c 'while tr   13 minutes ago      Exited (0) 7 minutes ago                        distracted_mcclintock
0b71024c8a95        centos:centos7      /bin/sh -c 'while tr   15 minutes ago      Exited (0) 7 minutes ago                        pensive_meitner
79a488c9cfb6        centos:centos7      console                22 minutes ago                                                      sick_babbage
06f43c19d10a        centos:centos7      /bin/echo 'Hello wor   25 minutes ago      Exited (0) 25 minutes ago                       berserk_einstein
我们可以分别利用命令对image和container进行删除
              
               

docker rm #删除container
docker rmi #删除image

这样执行一次run就创建一个container,势必会造成大量的无用的container,可能我不需要持久化保存container,如果在docker run命令加上 --rm=true 选项,那当这个container执行完毕,将自动自己删除,保证了container数量不会泛滥增长。
我们之前下载纯净版centos7是没有任何第三方软件的,包括wget,ping等命令都要通过yum工具来重新安装,我们当然不想每次都重新安装这些东西,我不仅希望要把一些常用的库安装到的image中去,同时还希望把程序运行的环境也安装进去,所以image更像是一个系统的模版。
你会发现,当你执行如下命令,wget命令时安装成功了,但是当你下次执行wget命令时,又会报错,说找不到这个命令,到底是怎么回事呢?
               
                

docker run -t b15 yum install -y wget #通过yum工具安装wget命令
#安装完毕后,执行wget会报没有这个命令
                 $ docker run -t b15 wget                  http://www.baidu.com                 
2014/08/18 15:42:19 exec: "wget": executable file not found in $PATH

为什么会出现这个问题呢?答案就是我们上面所说的那样,每次执行docker run都会去独立的创建一个新的container来执行程序,所以我们必须手动把这些对container的更改提交成一个新的image,才能够依据这个image执行wget操作。
我们先把当前所有的container都删除,然后直接登录到container的bash命令窗口中去,免得每次都去输入docker run了
                
                 

docker run -t -i b15 /bin/bash

bash-4.2#

这样我们进入了一个新的container,依据centos7作为模板,我们将要在其上面安装wget工具,直接执行
                 
                  

yum install -y wget

安装完毕之后,我们执行exit退出container
输入docker ps -a 我们找到刚才安装过wget工具的container ID,我们要把这个container重新做成一个新的image模版,这个模版将带wget命令。
                  
                   

docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
26cc82ad29af        centos:centos7      /bin/bash           3 minutes ago       Exited (0) 5 seconds ago                       desperate_mccarthy
 

我们执行如下命令,将一个安装过软件的container提交为一个image
                   
                    

docker commit 26  wget-centos7
60cd26c6ca1e753bf77aa913ed7b826767a678b75f6dd8421353f6c0899d3e5e

我们查看当前image镜像的列表:
                    
                     

wget-centos7        latest              60cd26c6ca1e        37 seconds ago      304.6 MB
centos              centos6             b1bd49907d55        2 weeks ago         212.5 MB
centos              centos7             b157b77b1a65        2 weeks ago         243.7 MB
centos              latest              b157b77b1a65        2 weeks ago         243.7 MB

你会发现多了一行我们刚才提交的 wget-centos7 的image镜像记录,现在我们执行这个镜像的wget命令,看看会不会报错
                    
                     

docker run -t -i --rm=true 60 wget http://www.baidu.com
--2014-08-18 15:54:55--  http://www.baidu.com/
Resolving www.baidu.com ( www.baidu.com)... 180.97.33.108, 180.97.33.107
Connecting to www.baidu.com ( www.baidu.com)|180.97.33.108|:80... connected.
HTTP request sent, awaiting response... 200 OK

执行完毕后,docker自动删除这个container,并且至今报错的wget命令无法找到也不会出错了。
第二种安装环境的办法,类似脚本安装,我们预先录入好一系列安装脚本,可以让docker帮我们依次执行这些安装脚本,然后生成image,例如有安装脚本Dockerfile:
                     
                      

# This is a comment FROM centos MAINTAINER doublespout <[email protected]> RUN yum install -y wget

我们执行如下命令进行创建images
                     
                      

mkdir wget
cd wget
vi Dockerfile #将上面内容复制进去
docker build -t="doublespout/wget" ./
#将看到安装脚本的执行输出,安装完成后,执行 docker images 就可以看到我们刚才创建的镜像了
docker images

                     四、发布应用程序
我们根据上一段的步骤,手动将node.js环境装好container并且发布成image,并保存"app.js"文件到"/var/nodejs/app.js",文件内容为:
                    
                     

var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }).listen(1337); //注意这边不能和官网示例那样监听127.0.0.1 console.log('Server running at http://0.0.0.0:1337/');

执行如下命令,运行container:
                   
                    

docker run -d -i -p --name=nodeapp 1337:1337 fa node /var/nodejs/app.js 32bac9ed8ba055c935bd641d23097a36a573a243ee942358fd74dc4140308bc6

其中fa是我创建的镜像id,这个值因人而异,name参数是给这个container取名字,必须是唯一的。
-p参数就是类似端口映射的功能,将主机的端口1337映射到contianer的1337端口,我们可以运行 docker ps,查看正在运行的container,打开浏览器,就能够看到 hello world了
                 
利用docker快速部署应用 - snoopyxdy - snoopyxdy的博客
用同样的方法就可以将我们开发好的应用快速部署到生产服务器上去了。如果在docker run命令需要设置cpu的支持数和权重值可以这样:
                 
                  

-c, --cpu-shares=0 CPU shares (relative weight) --cpuset="" CPUs in which to allow execution (0-3, 0,1)

另外一个小敲门,如果我想要进入一个在运行中的docker container时,可以使用 docker attach,连上这个container的输入和输出。
                 五、将多个 container 连接起来
我现在先下载一个redis数据库image,这也是以后做项目的常规用法,数据库单独用一个image,程序一个image,利用docker的link属性将他们连接起来。
                 
                  

docker pull redis #下载官方的redis镜像,耐心等待一段时间

接着我们执行命令启动redis镜像到一个container,开启redis-server持久化服务
                 
                  

docker run --name redis-server -d redis redis-server --appendonly yes

然后我们再启动一个redis镜像的container作为客户端连接它
                
                 

docker run -it --link redis-server:redis --rm redis /bin/bash

redis@7441b8880e4e:/data$ env #想要知道当前我们在主机还是container,注意$前面的host和name
REDIS_PORT_6379_TCP_PROTO=tcp
HOSTNAME=7441b8880e4e
TERM=xterm
REDIS_NAME=/boring_perlman/redis
REDIS_PORT_6379_TCP_ADDR=172.17.0.34 #redis服务器ip
REDIS_PORT_6379_TCP_PORT=6379 #redis服务器端口
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/data
REDIS_PORT_6379_TCP=tcp://172.17.0.34:6379
SHLVL=1
REDIS_PORT=tcp://172.17.0.34:6379
HOME=/
_=/usr/bin/env


$redis-cli -h "$REDIS_PORT_6379_TCP_ADDR" -p "$REDIS_PORT_6379_TCP_PORT"


172.17.0.34:6379> set a 1 #成功连入redis数据库服务器
OK
172.17.0.34:6379> get a
"1"
172.17.0.34:6379>

通过这样的方法,我们就可以将发布的应用程序和数据库分开,单独进行管理,以后对数据库进行升级或者对程序进行调整两者都没有冲突,系统环境变量我们可以通过程序的os模块来获得。
               六、文件卷标加载
比如我们想要一个日志文件保存目录,如果直接写入container,那样image升级之后,日志文件处理就比较麻烦了,所以就需要将主机的文件卷标挂载到container中去,挂载方法如下:
               
                

$ docker run --rm=true -i -t --name=ls-volume -v /etc/:/opt/etc/ centos ls /opt/etc boot2docker hostname ld.so.conf passwd- securetty sysconfig default hosts mke2fs.conf pcmcia services sysctl.conf fstab hosts.allow modprobe.conf profile shadow udev group hosts.deny motd profile.d shadow- version group- init.d mtab protocols shells gshadow inittab netconfig rc.d skel gshadow- issue nsswitch.conf resolv.conf ssl host.conf ld.so.cache passwd rpc sudoers

如果想要挂载后的文件是只读,需要在这样挂载:
              
               

-v /etc/:/opt/etc/:ro #read only

我们也可以挂载其他container中的文件系统,需要用到 -volumes-from 参数,我们先创建一个container,他共享/var/目录给其他container。
             
              

$ docker run -d -i -t -p 1337:1337 --name nodedev -v /var/ fa node /var/nodejs/app.js

             

然后我们启动一个ls-var的container来挂载nodedev共享的目录:

              

$ docker run --rm=true -i -t --volumes-from nodedev --name=aaa1 centos ls /var adm db games kerberos local log nis opt run tmp yp cache empty gopher lib lock mail nodejs preserve spool var

我们打印var目录,会发现多了一个nodejs的目录,就是从nodedev中的container挂载过来的。其实我们挂载其他container的路径都是在根目录上的。

七、发布到docker hub上去

我们做完镜像,就需要将镜像发布到docker hub上,供服务器下载然后运行,这类似git仓库,将自己开发的东西丢到云服务器上,然后自己在其他机器或者其他开发者可以下载镜像,并且从这个镜像开始运行程序或者再进行2次制作镜像。

我们需要先登录docker帐号,执行:

              

$ docker login #输入你在docker官网注册的帐号和密码就可以登录了

$ docker push <用户名>/<镜像名> #将你制作的镜像提交到docker hub上

非官方不允许直接提交根目录镜像,所以必须以<用户名>/<镜像名>这样的方式提交,比如 doublespout/dev 这样

八、总结

   
docker快速部署介绍完毕了,总结一下,要创建一个简单项目使用的步骤:
1、安装配置docker
2、pull镜像,安装程序执行环境
3、pull数据库镜像
4、开发程序
5、push 程序的镜像
6、服务器安装配置docker
7、运行数据库镜像
8、运行程序镜像,并且把数据库镜像link进来,并且挂载主机的日志目录或其他上传目录。
使用了docker以后,环境配置只需一次,免去了开发部署一套,测试部署一套,生产又部署一套的麻烦,以后程序搬家也是非常简单。
    

相关 [利用 docker 应用] 推荐:

利用docker快速部署应用

- - snoopyxdy的博客
最近研究了几天docker的快速部署,感觉很有新意,非常轻量级和方便,打算在公司推广一下,解放运维,省得每次部署一台新服务器都去跑安装脚本了,对于我们开发人员也是好事情,无需写太多重复的部署文档,直接将docker的images丢上服务器就可以运行了. 安装很简单,直接进入下载页面,根据自己的操作系统下载相对应的安装包即可,下面说一下windows安装:.

Docker应用场景

- - 灯火阑珊
Flynn:一个使用go语言编写的开源PaaS平台,目标是简化分布式环境中应用的部署和维护,可以通过git push命令,将应用部署到Docker,从而省去复杂的配置和操作. CoreOS:一种新的架构体系重新设计的Linux发型版,可以运行在既有的硬件活着云服务器上. CoreOS不提供类似yum或apt的包管理工具,用户不需要在CoreOS中安装软件,而是让程序都在Docker容器中运行.

利用Docker构建开发环境

- - UC技术博客
最近接触PAAS相关的知识,在研发过程中开始使用Docker搭建了自己完整的开发环境,感觉生活在PAAS时代的程序员真是幸福,本文会简要介绍下Docker是什么,如何利用Docker来搭建自己的开发环境(本文主要是面向Mac OS X),以及期间所遇到的一些坑和解决方案. (本文会要求你对PAAS、LXC、CGroup、AUFS有一定的了解基础,请自行Google ).

golang的杀手级应用:docker

- - _不是我干的 _
docker 是 golang 的第一个杀手级应用,发展迅猛, 现在各大云计算平台几乎全都支持 docker 实例,包括 谷歌,亚马逊,阿里云等. golang 本身已经让我惊喜万分,而 docker 更是极大的激发了我对虚拟化的想象. IT 业发展至今,软件和硬件始终是无法分割的两个物体. 就拿最近几年红红火火的智能机时代来说, 很久之前的诺基亚智能机, 软件和硬件相辅相成, 连进入主界面都需要按一个特定的按钮才能进入.

八个Docker的真实应用场景

- - ITeye资讯频道
【编者的话】Flux 7介绍了常用的8个Docker的真实使用场景,分别是简化配置、代码流水线管理、提高开发效率、隔离应用、整合服务器、调试能力、多租户环境、快速开发. 我们一直在谈Docker,Docker怎么使用,在怎么样的场合下使用. 有需要交流的地方,可以通过评论与我们交流. 几周前我们参加了 DockerCon ,Dockercon是首个以Docker为中心的技术大会.

Docker & Flatpak

- - IT瘾-dev
目前最流行的技术莫过于Docker,Docker和Docker衍生的东西用到了很多很酷的技术,目前deepin应用软件发布转变成flatpak,这些看似风牛马不相及的技术方案,实际都使用了一个共同的底层技术——Namespace,假如没有namespace支持,这些技术实现都将成为空中楼阁. 一句话总结,无论是Docker、sysmted-nspawn还是flatpak,都是在namespace基础上,针对不同的场景,生出的不同的解决方案.

docker如何利用cgroup对容器资源进行限制

- - 学习日志
在容器里有两个非常重要的概念,一个是 namespace用来进行对容器里所有进程的隔离;另一个就是 cgroup,用来对容器资源进行限制. 那 cgroup又是如何实现对进行资源的限制呢,今天我们来了解一下它的实现原理. cgroup 是 Control Groups 的缩写,是 Linux 内核提供的一种可以限制、记录、隔离 ` 进程组` 所使用的物理资源(如 cpu、memory、磁盘IO等等) 的机制,被 LXC、 docker 等很多项目用于实现进程资源控制.

减少使用Java应用服务器,迎接Docker容器

- - ITeye资讯频道
【编者的话】随着Docker的发展,越来越多的应用开发者开始使用Docker. James Strachan写了一篇有关Java开发者如何使用Docker进行轻量级快速开发的文章. 他告诉我们,使用Docker和服务发现的机制,可以有效减轻Java运维人员的负担,进行项目的快速启动和持续迭代. 多年来,Java生态系统一直在使用应用服务器.

在Docker中监控Java应用程序的5个方法

- -
作者:Chris Ward . 译者注:Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化. 通常情况下,监控的主要目的在于:减少宕机时间、扩展和性能管理、资源计划、识别异常事件和故障排除分析等. 本文作者介绍了5种方法帮助你在Docker中监控Java应用程序.

docker初体验之docker-tomcat

- - BlogJava-首页技术区
docker已经是现在最热的容器技术,最近也去体验了一下,在daocloud注册了一个账号,并开始本机实战docker. daocloud免费有两个容器可用,体验送T恤,邀请送书,这里我分享一个daocloud的邀请码 https://account.daocloud.io/signup?invite_code=mxeq2jkmcur37vz6ven8,daocloud是非常棒的容器云平台,使用体验好,问题响应也及时,绑定微信还送一个额外容器.