docker 实践开发

本文摘自: docker 高级进阶
前面几篇详细的介绍了,docker的一些基本内容和知识. 这里, 我们来实践一下,在正式环境中,docker是怎么搭建的.
在开始之前,说一些docker运行时的基本原理.
docker最大的特点就是虚拟化, 通过VM来获得底层的操作权限,并且利用自身的进程构建了一个庞大的集群系统, 相当于,一个docker下面,我们可以连接上不同的电脑. 但实际上, 他们都可以虚拟化在一个docker daemon里面.
在实践开发中,我们需要100%的掌握Volume以及EXPOSE等网络接口命令的用法. 因为, 这是multi-docker交互的必备. 而且, 使用container的时候, 开启某一个进程时,不能设置为background. 因为docker, 只会检查子进程是否处于active状态,如果你一旦退出container,那么他下面的background jobs 也就go die了.

搭建自己的Server

Ps: 这里翻译了一下docker books 里面的例子–搭建Jekyll 和 Apache

这里,先简单说一些jekyll的原理,jekyll就是一个html的生成工具, 用来将你静态的文件自动生成为一个静态博客所需要的内容.

# jekyll 运行命令
// 自动将子目录下的文件解析并且编译为/var/www/html
jekyll build --destination=/var/www/html

这里,我就直接放dockerfile了.

FROM ubuntu:14.04

MAINTAINER James Turnbull <james@example.com>

RUN apt-get -yqq update
# 这里下载ruby, 并编译nodeJS, 因为jekyll需要
RUN apt-get -yqq install ruby ruby-dev make nodejs
# 下载jekyll
RUN gem install --no-rdoc --no-ri jekyll -v 2.5.3
# 将该container下的/data共享
VOLUME /data
# 将该container下的/var/www/html共享
VOLUME /var/www/html
# 设置当前工作目录
WORKDIR /data
# 当在RUN的时候自动运行的命令
ENTRYPOINT [ "jekyll", "build", "--destination=/var/www/html" ]

上面理解起来不难, 显示下载环境,然后将文件共享,最后设置运行命令.
关键想说一下VOLUME的内容, 前面已经提到过, docker daemon 运行时, 会自动调起一个环境,相当于有一块独立的内存。 使用VOLUME共享一个目录,则该目录则会被所有在docker运行下的container共享.(就是其他的container可以获得你的数据了)
ok, 我们接下来来看一下Apache docker 的搭建.同样, 放一份dockerfile就够了.

FROM ubuntu:14.04

# 下载Apache
RUN apt-get -yqq update
RUN apt-get -yqq install apache2

# 设置同享盘
VOLUME [ "/var/www/html" ]
# 这我就不说了
WORKDIR /var/www/html

# 设置一些列Apache2需要配置的文件
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE_PID_FILE /var/run/apache2.pid
ENV APACHE_RUN_DIR /var/run/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2

RUN mkdir -p $APACHE_RUN_DIR $APACHE_LOCK_DIR $APACHE_LOG_DIR 
EXPOSE 80

# 设置默认命令 apache2 -D FOREGROUND
ENTRYPOINT [ "/usr/sbin/apache2" ]
CMD ["-D", "FOREGROUND"]

这里,再次注意一下VOLUME这条命令. 可以看到后面的/var/www/html和上面jekyll设置的是一样的. 这样的意义就是,我的这个container设置的共享文件的目录和jekyll是一致的.这里先不说有什么用. 我们放到后面来看看。
现在,上面两个image都已经准备好了. 该run这两个image。run的过程为:

  • 第一步: 先run jekyll, 让其先编译好静态博客所需要的文件.

  • 第二步: 运行Apache2, 提供对外服务的接口

运行jekyll

运行还是docker run命令.

# 注意下面的-v参数.
// 将/home/james/james_blog的文件,共享到/data/目录下
docker run -v /home/james/james_blog:/data/ \
   --name james_blog jimmy/jekyll

上面唯一特别的地方就在于 -v这个参数, 在image文章里面,我提到过. 这个flag就是用来代表将外部的文件建立与内容container的联系,并且,container的操作完全反映到外部对应的文件.
其中/home/james/james_blog目录下就是jekyll的文件. 这里提供一份:(FROM docker books)

git clone https://github.com/jamtur01/james_blog.git

现在,静待jekyll编译完成,然后你就可以run Apache2

运行Apache2

同样也是使用run

# 注意--volumes-from 这个参数
docker run -d -P --volumes-from james_blog jamtur01/apache

关于–volumes-from,可以参考我写的另外,一篇image博文. 他可以用来将一个container中共享的VOLUMES共享到另外一个container中.
如果,顺利的话,那这个博客就已经搭建好了. 最后我们在看看docker实际暴露到外部的端口, 然后就可以访问了.

docker port jimmy/Apache2 80
 0.0.0.0:33221
// 最后访问你的本机ip:33221即可
198.124.10.239:33221

blog update

上面几步已经讲清楚怎么从0到1搭建一个静态blog. 但,问题是,如果后续我们要更新怎么呢?
很简单,重新编译jekyll即可–就是重启container…

docker start james_blog
# 检测一下logs记录
docker logs james_blog

VOLUMES的备份

当你的blog运行一段时间,可能会担心某一天数据没了… 那么很重要的一步就是做备份了. 在docker里面对VOLUMES备份,灰常简单.

# 在运行的Apache2 container中运行
// 将当前目录: /var/www/html 共享到/backup里面.
// 使用tar进行压缩,然后生成备份文件
docker run --rm --volumes-from james_blog \ -v $(pwd):/backup ubuntu \
tar cvf /backup/james_blog_backup.tar /var/www/html
# 使用ls查看
$ ls *.tar
>>> james_blog_backup.tar

说一下里面需要注意的几个点吧:

  • 重点一:
    其中--rm的参数的作用是神马? –rm这个flag表示当运行完container之后,就立即删除.

  • 重点二:
    为什么退出之后,在当前目录会存在*.tar文件?

这是因为,你在备份的时候,指定了共享目录,你在container中对目录做的改动都会反映到外部.

ok, 现在大部分内容差不多已经结束了. 最后,再补充一点关于docker VOLUMES的知识.

docker 之 VOLUMES

dokcer 构建VOLUMES的机制有点特殊, 实际上你在dockerfile里面新定义的VOLUMES都会映射到/var/lib/docker/volumes下面. 并且,docker会永久的保存. 即使,你已经退出该container.
我们可以通过docker inspect 来检查我们的某个container共享的文件夹放在哪个位置.

# sample 是指定的container name
docker inspect -f "{{ range .Mounts }}{{.}}{{end}}" sample

link container间通信

link是在docker run 时,手动指定的命令. 这个命令,我们也可以认为是用来作为container间的通信, 但这同network, volume有着他独特的地方. link 实际上也是host通信, 不过, 相比显示创建PORT来说, 这个更方便,也更灵活. 因为他会内建port 并且抽象的使用name来进行通信.
我们按照demo来,讲解.
首先创建一个dockerfile — link_child

FROM ubuntu:latest
MAINTAINER jimmy "villainhr@gmail.com"
ENV REFRESH second
WORKDIR /var
EXPOSE 3669
ENTRYPOINT ["/bin/bash"]

使用docker build:

docker build -t="jimmy/link:0.1" .

现在,轮到我们正式使用–link来连接两个container了.

# 首先run 刚才创建的image
docker run -d -ti --name child_link jimmy/link:0.1 
# ok, 正常运行之后,现在就可以link了.
# 使用cat 来查看建立的网桥连接
docker run --rm --link child_link ubuntu:latest 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    child_link  // 这就是我们link进来的container

# 上面只是看看一下成功没. 接下来,我们需要使用ENV指令,来查看docker 具体做了些什么
docker run --rm --link ba6f1726435a:child_link ubuntu:latest env    
// 得到结果
HOSTNAME=1be326e281d5
CHILD_LINK_PORT=tcp://172.17.0.2:3669 # 主要使用这个!!
CHILD_LINK_PORT_3669_TCP=tcp://172.17.0.2:3669
CHILD_LINK_PORT_3669_TCP_ADDR=172.17.0.2
CHILD_LINK_PORT_3669_TCP_PORT=3669
CHILD_LINK_PORT_3669_TCP_PROTO=tcp
CHILD_LINK_NAME=/tender_payne/child_link
CHILD_LINK_ENV_REFRESH=second
HOME=/root

# 然后在生产环境中,直接使用CHILD_LINK_PORT全局变量进行container间通信即可.

这样的做法就是,不需要你手动指定port, docker 内置的帮你搭建了通信的tunnel. 是不是很方便?

    原文作者:villainhr
    原文地址: https://segmentfault.com/a/1190000006208042
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞