当 Coding 遇上 Docker

2015-09-17 08:49:06 +08:00
 CodingNET

原文链接: https://blog.coding.net/blog/Coding-and-Docker

Docker 是时下最为流行的开源容器技术,而 Coding 又是从来以革命者先驱的姿态拥抱新技术的,所以我们也与 Docker 擦出了火花,有爱有恨,有苦涩的过去时光,也有甜蜜的未来规划。

关于容器

注:本文容器仅仅代表 linux 容器,不包含其他操作系统的相关技术,更不是什么瓶子罐子之类的。:)

容器的本质

容器依赖高版本 linux kernel 提供的如下几种技术实现:

例如,我们可以在 /proc/PID/ns 目录下找到一些 namespace 相关的信息:


关于 namespace 这里就不再做过多介绍,有兴趣的读者可以自行去查找相关资料

Docker 是什么

想了又想,觉得这个概念还是没啥好说的,因为我觉得你去 docker 的官方网站看一看,或者随便找个搜索引擎搜一搜都比我解释的清楚。这里谈一谈个人认为的 Docker 的一些看法吧。

docker 是一种容器技术,又在容器技术之上创造了很多新的实用的功能和概念,例如 image , registry , layer , RESTful API 等等。 docker 的特点是简单能快速上手,目标是要解决 Build , Ship , Run 。这也是 docker 官方的 slogan 。

关于 libcontainer 和 runc

Google 是最早研究容器技术的公司,并在内部有大规模部署, libcontainer 是 docker 最初根据 Google 提出的一些关于容器相关的论文等做出得一个实现库。当然实现不止 docker 一个 ,还有例如 rocket ,以及很多大公司内部的一些实现等。为解决容器技术分裂化,各大技术厂商组建了 opencontainer 联盟,希望能统一容器标准。随后 docker 把 libcontainer 捐献给了 opencontainer 联盟。
源码位于: https://github.com/opencontainers/runc 的 libcontainer 目录中

docker 的优势

我觉得 docker 优势中最重要的一点,也是 docker 官方的标语 Build, Ship, Run ,简化标准化了应用生命周期流程。

而如果配合编排系统后,还能做到如下几点:
* 使快速的分布式大规模部署成为可能
* 使基础资源和应用分离成为了可能
* 使弹性计算可以做的更好

docker 常见周边容器编排系统

有了容器,要想在一定规模的硬件计算资源上应用,往往需要做容器编排,例如定义哪些容器在哪些服务器上运行,相互之间的关系是什么,负载均衡,热备等等的一系列操作。时下有如下这些编排软件或框架比较流行,这里做一个简要介绍:

Coding 目前使用容器技术的状况

Coding 踏入容器技术的大门最早是演示平台( 基于 CloudFoundry 的 PaaS 系统 ),演示平台依赖容器技术进行应用隔离。但是一开始 Coding 并没有系统中其他功能服务中使用容器技术,随着 DevOps 发展,越来越发觉容器技术是必不可少的一环,是未来发展的方向,开始在其他功能和服务中逐渐使用 docker 来取代一些传统的做法。

Coding 开始使用 Docker 后的一个观念就是 everything in docker 。所以我们也把之前在本地跑得程序构建过程移到了 docker 中。我们给每个应用写了一个构建脚本,这个脚本就负责启动一个 docker container 然后在里面把项目构建完成, 得到一个 ready to run 的 package ,可能是一个 jar 包,可能是一个 可执行程序,也可能是一个下载完依赖的 文件夹;然后编写一个 Dockerfile 用以描述该应用在什么样的环境下如何运行。直接交付 一个 docker image 给运维

示例 build.sh 文件

VERSION="test"
  cur_dir=`pwd`
  mkdir -p ./.src/target
  cd ../../../CodingBlog
  docker run -it -v "`pwd`:/app:rw" -v "$HOME/.gradle:/root/.gradle:rw" java:8-jdk sh -c "cd /app && ./gradlew clean build"
  cp ./build/libs/CodingBlog-1.0.jar $cur_dir/.src/target/CodingBlog-1.0.jar
  mkdir -p /data/git
  cd $cur_dir
  echo "$VERSION" > ./.src/.version

这个文件的执行结果就是要在特定的目录下生成特定的 readytorun 的 jar 包,好处是执行者只需要安装有 docker 即可执行,不需在额外安装 jdk gradle 等等。注意上面一个小细节:把 .gralde 目录挂载进去,可以将依赖的 jar 包缓存下来,加快下次构建速度。

示例 Dockerfile 文件

# Base
FROM java:8-jdk

COPY ./.src/target/RepoManager-1.0.jar /app/

RUN useradd -m -u 1000 coding
USER coding

WORKDIR /app
CMD [ "java", "-server", \
      "-Xms2048m", "-Xmx2048m","-XX:+UseFastAccessorMethods", \
      "-jar", "./CodingBlog-1.0.jar" \
]

没有什么特别的就是 java -jar 运行就好了。

显而易见的,利用 docker ,我们轻而易举的完成了应用构建的标准化,以及应用交付流程的简化。
另外,我们为了 image 的统一管理,搭建了 docker registry ,目前是 V1 版本,方便给生产环境的快速分发。

Coding 目前简单的容器编排

Coding 在参考调研过目前的一些容器编排系统之后,决定自行写一套简易的符合 Coding 现状的编排系统,其实类似于 compose 或者之前的 fig 的概念,即用配置文件定义容器如何编排,包括容器配置,环境变量等等信息,然后写一个程序读取这个配置文件,再来操作 docker daemon 。

我们的配置示例:

job: <
  name: "repo-manager-5"
  image: "repo-manager:latest"
  run_on_host: "git-5"
  envs: <
    key: "port"
    value: "8866"
  >
  volumes: <
    container_path: "/data"
    host_path: "/data"
    read_only: false
  >
>

我们以 job 的形式组织一个应用实例,目前并没有使用容器技术中的诸如 CPU 内存限制等,而且目前 所有的 docker 容器网络都配置为 host 模式,一方面是出于性能考虑,另一方面,也是为了与之前老的系统兼容,方便迁移。

我们写了一个命令行工具,可以用来读取这个文件,并操作 docker daemon 。有诸如 start , stop , restart , update , log , shell , inspect 这些功能。

例如,执行 update 操作,会列出当前的 image 列表,选择后,就可以进行全自动更新。

Coding 的开发环境

我们在开发团队内部推行一套 Coding-local 的机制,即使用一个 Vagrant VM ,配合 Coding-local 这样一套构建脚本和 Dockerfile ,得以让任何一个同事都可以执行很简单的几部操作就可以在一个虚拟机里面运行起整个 Coding 系统,方便不熟悉,却又需要使用的同事也能快速上手开发。

为保持生产环境和开发环境一致性,我们在 coding-local 环境里面也使用 job 这样的方式,以及 build.sh 构建脚本 Dockerfile 这样的方式来支撑整个系统,唯独少了 docker-registry , 因为在 coding-local 里面不存在 image 分发的问题。

目前 Coding 存在的一些问题

发现 docker 的一些问题

Coding 关于 docker 以及 容器未来的发展方向

3193 次点击
所在节点    Coding
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/221310

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX