《使用docker构建后端测试和线上服务》
一 docker的应用场景
RD对QA说:“诶?这个程序在我的环境里是好使的呀?”,QA怒视之!~
这个场景真实出现过,linux版本,gcc,版本,依赖版本会导致各种各样奇怪的问题。之前在B公司,每个新人都要自己动手搭建一套复杂的线上搜索环境,而这个时间通常需要1周。
上面是一些开发中的痛点,也是docker可以解决的方面。总结docker,我觉得的优点如下:
- 将线下和线上的环境统一,减少开发和测试的复杂度
之前我们team的做法是把程序的依赖尝试都使用相对路径,并跟程序一起打包上线。思路很类似。现在很多公司都将docker用在这个地方,但我觉得如果docker更加稳定后应用场景会更多,更通用 - 集群管理可视化更加高效,开源的容器编排工具Kubernetes,可视化工具提供了强大的支持
- 云平台,测试机云平台可以利用docker技术提升整个集群的利用效率,榨干每一台机器的能力
- 开源社区强大,外围工具很多,如上下游服务发现组件如:etcd和Consul
- toB的业务发布后端程序更加简便
例如:A公司开发游戏,发布给B公司进行运营,使用docker发布不用再编写复杂的部署说明手册了,变更也更加方便 - 需求迭代迅速,流量变化迅速的互联网web服务后端(易发布,易扩容)
二. 上手
-
运行的环境要求
docker是典型的CS架构,docker client把要执行的程序发给驻守的服务Docker Machine执行。Linux可以不需要驻守进程外的任何环境,mac os和windows需要安装Boot2Docker。
墙内的加速工具:DaoCloud -
使用已有的docker镜像
docker file:相当有用于构建二进制程序的makefile
image镜像:相当于构建好的二进制文件
container:相当于运行起来的二进制- 镜像的市场dockerhub
这里面有官方officical的镜像如:ubuntu,redis,mysql等等。也有第三方发布的image(不保证安全性和质量) - image操作命令集合
docker images
shows all images.
docker import
creates an image from a tarball.
docker build
creates image from Dockerfile.
docker commit
creates image from a container.
docker rmi
removes an image.
docker load
loads an image from a tar archive as STDIN, including images and tags (as of 0.7).
docker save
saves an image to a tar archive stream to STDOUT with all parent layers, tags & versions (as of 0.7).
- 镜像的市场dockerhub
- container操作命令集合
docker create
creates a container but does not start it.
docker run
creates and starts a container in one operation.
docker stop
stops it.
docker start
will start it again.
docker restart
restarts a container.
docker rm
deletes a container.
docker kill
sends a SIGKILL to a container.
docker attach
will connect to a running container.
docker wait
blocks until container stops.
示例:
docker run -it -v $HOSTDIR:$DOCKERDIR
-p 127.0.0.1:$HOSTPORT:$CONTAINERPORT kaixhin/caffe:latest /bin/bash
说明:镜像 kaixhin/caffe:latest 分为作者名/镜像名:tag版本号
-it表示启动容器后会进入执行交互的shell命令终端tty
如果执行的时候没有下载好image文件,会首先默认执行docker pull
-v 表示将本地目录挂在到容器中的目录位置,这个对于容器运行后的数据持久化很有用
-p表示使用容器使用port到本机实际的port的映射
- container状态查询命令集合
docker ps
shows running containers.
docker logs
gets logs from container.
docker inspect
looks at all the info on a container (including IP address).
docker events
gets events from container.
docker port
shows public facing port of container.
docker top
shows running processes in container.
docker stats
shows containers' resource usage statistics.
docker diff
shows changed files in the container's FS.
- 构建自己的docker 镜像
有2种方式可以构建自己的镜像image
-
使用docker commit(不推荐,因为细节变化不好维护,不好复用)
具体:在已经运行的基础容器上面执行命令,保存修改并推出。之后通过docker commit来提交变更部分到自己的新镜像。这个过程类似git修改代码提交的过程。 -
使用dockerfile + docker build命令
dockerfile相当于Makefile,决定了镜像具体的构建过程和最终的效果。其使用了专门的DSL语言来描述。
.dockerignore 类似.gitingore,忽略打包的镜像的文件
FROM 依赖的基础镜像
MAINTAINER维护着
RUN就是运行
CMD配置执行等同于docker run执行时的命令,只能有一条生效,如果需要执行多个启动命令,可以使用supervisored+配置多个启动进程来实现
EXPOSE设置要使用的端口号
ENV设置环境变量
ADD将build同级目录下文件上传到容器的指定目录,如果是tar还会自动的解压缩
COPY类似add,没有解压缩功能
ENTRYPOINT
VOLUME创建可以穿透到docker虚拟环境,持久化数据的目录
USER镜像运行使用的用户账号
WORKDIR工作目录,类似cd功能
ONBUILD注入命令,在本dockerfile被FROM继承并build的时候插入
一个例子
FROM ubuntu:trusty
MAINTAINER zhaoming "ming.zhao@horizon-robotics.com"
RUN apt-get update \ && apt-get -y install \ curl \ wget \ apache2 \ libapache2-mod-php5 \ php5-mysql \ php5-sqlite \ php5-gd \ php5-curl \ php-pear \ php-apc
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf \
RUN mkdir -p /app && rm -rf /var/www/html && ln -s /app /var/www/html
COPY . /app
WORKDIR /app
RUN chmod 755 ./start.sh
EXPOSE 80
CMD ["./start.sh"]
注意:start.sh 需要跟本Dockerfile在同一级目录
由于build过程都是递进复用上一层的镜像,所以命令行数原则上越少镜像会越小,build过程更快
dockerfile最佳实践
- 发布自己的镜像
docker push you/yourimage
- 更自动化的方案
在docker hub操作关联在github上的dockerfile项目,每次提交dockerfile的修改就可以触发自动构建流程
- 基于多个docker镜像构建后端服务
互联网的后端服务需要多个模块协同组成micro-service,进而构建起整个互联网服务。官方建议一个docker容器中运行单个进程,这样更有利于服务的扩容和管理。这就需要容器间具备类似进程间通讯的机制
- docker的解决方案-link连接
docker run -it -p 4567 --name testapp --link redis:db -v $PWD/webapp:/data/webapp zmoon/testapp /bin/bash
说明:--link redis:db表示本次启动的容器作为父容器,使用子容器redis,并重命名为db。在本容器中的webapp程序可以通过使用主机名"db"来作为子容器的ip访问相应服务。 如:redis = Redis.new(:host=>'db', :port=>'6379')
注意:link只支持在一台物理主机上的的容器之间连接
- 使用Volume卷
docker run -it -d -P --volumes-from other-v-container my/apache_service
说明:other-v-container 是依赖的另一个容器,其中定义了
VOLUME /var/www/html
卷的特性:可以在容器间共享;卷是持久化的;卷会一直存在直到没有容器使用
- 服务集群编配工具和组件
-
Compose - Dockerfile 可以让用户管理一个单独的应用容器;而 Compose 则允许用户在一个模板(YAML 格式)中定义一组相关联的应用容器(被称为一个 project
,即项目),例如一个 Web 服务容器再加上后端的数据库服务容器等。
web service with compose - etcd - 它的目标是构建一个高可用的分布式键值(key-value)数据库用来管理配置和提供服务发现功能,基于 Go 语言实现,部署多台具有高可用性。
- kubernetes-Kubernetes 是 Google 团队发起的开源项目,它的目标是管理跨多个主机的容器,提供基本的部署,维护以及运用伸缩,主要实现语言为Go语言。适合更大规模的集群
- Consul类似etcd,提供分布式环境下服务发现的功能,部署多台具有高可用性。
三 docker更多的使用场景
物联网IOT设备上运行的环境更加多样,不同的cpu:如arm等。不同的os如:android,linux多版本等。在这样的环境下引入docker可以更好的屏蔽不同的硬件环境以及更容易的自动升级,这部分工作在:Raspberry Pi with Docker 1.5.0