Docker实战:更轻松、更愉快、更高效

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 本文讲的是Docker实战:更轻松、更愉快、更高效,【编者的话】本文作者(Michael Herman)通过实例展示了Docker在日常开发中的潜力,并不需要花费太多精力,就可以建立一套高效、简洁的流程,包括了项目自动化的测试、持续集成及部署,将开发者从这些令人厌倦的体力劳动中解放出来,同时为我们了解Docker提供了直观的经验。
本文讲的是Docker实战:更轻松、更愉快、更高效, 【编者的话】本文作者( Michael Herman )通过实例展示了Docker在日常开发中的潜力,并不需要花费太多精力,就可以建立一套高效、简洁的流程,包括了项目自动化的测试、持续集成及部署,将开发者从这些令人厌倦的体力劳动中解放出来,同时为我们了解Docker提供了直观的经验。

借助Docker,我们可以更容易地进行Web应用部署,而同时不必头疼于项目依赖、环境变量以及各种配置问题,Docker可以快捷、高效地处理好这一切。

而这也是本教程的目标。

首先我们来学习使用Docker容器运行一个Python Flask应用,然后逐步介绍一套更酷的开发流程,其中涵盖了应用的持续集成与发布........

我( Michael Herman )最初是在2015年2月8日的 PyTennessee 上介绍了这一工作流程,如果感兴趣的话,你可以直接浏览我当时使用的 幻灯片

流程

1. 在本地功能分支上完成应用代码。
2. 在GitHub上发起一个到master分支的Pull Request。
3. 在Docker容器上运行自动测试。
4. 如果测试通过,手动将这个PR merge进master分支。
5. 一旦merge成功,再次运行自动测试。
6. 如果第二次测试也通过,就在Docker Hub上对应用进行构建。
7. 一旦构建完成,自动化地部署到生产环境。
steps.jpg


本教程基于Mac OS X,在开始前需要保证以下工具已正确安装配置:Python v2.7.9, Flask v0.10.1, Docker v1.5.0, Docker Compose, v1.1.0, boot2docker 1.5.0, Redis v2.8.19
好了,让我们开始吧。

首先来介绍一些Docker中的基本概念:
  • Dockerfile中包括了一系列语句,用于对镜像的行为进行描述。
  • 镜像是一个模板,用来保存环境状态并创建容器。
  • 容器可以理解为实例化的镜像,并会在其中运行一系列进程。

如果对 Dockerfile镜像容器的具体细节感兴趣,那么可以从Docker的 官方文档获取更多详细信息。

为什么是Docker?

使用Docker意味着你能在开发机上完美地模拟生产环境,而不用再为任何由两者环境、配置差异所造成的问题而担心,除此之外Docker带给我们的还有:
  1. 良好的版本控制。
  2. 随时便捷地发布/重建整个开发环境。
  3. 一次构建,随处运行,就是这么神奇!

配置Docker

由于Darwin(OS X内核)缺少运行Docker容器的一些Linux内核功能,所以我们需要借助 boot2docker ,一个用于运行Docker的轻量级Linux发行版(启动一个专门为运行Docker定制过的小型虚拟机)。

首先为我们的Flask项目创建一个名为“fitter-happier-docker”的目录。

接下来遵照 官方文档 的步骤来完成Docker和boot2docker的安装。

我们可以通过以下命令来验证安装是否正确:
$ boot2docker version
Boot2Docker-cli version: v1.5.0
Git commit: ccd9032

Compose Up!

Docker Compose 是官方提供的容器业务流程框架(译者注:曾经的项目名称是 Fig ,甚至在本译文的初稿时依然是,进化速度之快可见一斑),只需通过简单的.yml配置文件,就能完成多个容器服务的构建和运行。

使用pip来安装Docker Compose,并通过如下命令来确认安装正确:
$ pip install docker-compose
$ docker-compose --version
docker-compose 1.1.0

现在来启动我们的Flask+Redis应用(你可以从这个 repo 来获取项目的全部源代码),首先在项目根目录下新建docker-compose.yml文件:
web:
build: web
volumes:
    - web:/code
ports:
    - "80:5000"
links:
    - redis
command: python app.py
redis:
image: redis:2.8.19
ports:
    - "6379:6379"

可以看到我们对项目所含两个服务进行的操作:
  • web:我们将在web目录下进行容器的构建,并且将其作为Volume挂载到容器的/code目录中,然后通过python app.py来启动Flask应用。最后将容器的5000端口暴露出来,并将其映射到主机的80端口上。
  • redis:我们直接使用Docker Hub上的官方镜像来提供所需的Redis服务支持,将6379端口暴露并映射到主机上。

你一定注意到了位于web目录下的Dockerfile文件,它用于指导Docker如何构建我们的应用镜像(基于Ubuntu),并且保证了完备的依赖支持。

构建并运行

接下来只需要一行简单命令,就能轻松搞定一切(镜像的构建及容器的启动运行):

Ubuntu
$ docker-compose up

figup.png

这会根据Dockerfile来构建Flask应用的镜像,从官方仓库拉取Redis镜像,然后将一切运行起来。

现在你可以去喝一杯咖啡,呃,也许是两杯:首次运行会花费相对较长的时间,事实上Docker会在构建过程中,将Dockerfile中的每一步操作(更正式的说法应该是 layer)缓存下来,以后的构建过程会因此提速很多,因为只有发生改变的步骤才会被重新执行。
Docker Compose会并行地启动全部容器,每个容器都会被分配各自的名字,并且会为日志设置可读性更高的配色方案。

好了,那么准备好来测试了吗?

打开你的浏览器,输入主机DOCKER_HOST环境变量所对应的IP地址,例如在我这里是  http://192.168.59.103/ (运行boot2docker ip命令可以查询到IP地址)。

接下来你应该会在浏览器中看到以下文本“Hello! This page has been seen 1 times.”: 
test.png

刷新页面,如果一切正常的话,计数器变量应该会进行累加。

通过Ctrl-C来终止我们的应用进程,然后通过以下命令让其改为在后台运行:
$ docker-compose up -d

想查看应用进程的运行状态?只需要输入以下命令就可以了:
$ docker-compose ps

Name                          Command             State              Ports
——————————————————————————————————————————————
fitterhappierdocker_redis_1     /entrypoint.sh redis-server   Up      0.0.0.0:6379->6379/tcp
fitterhappierdocker_web_1       python app.py                 Up      0.0.0.0:80->5000/tcp, 80/tcp

可以看到我们的两个进程运行在不同的容器中,而Docker Compose将它们组织在一起!

更进一步

在确定一切正常无误后,使用docker-compose stop命令来终止我们的应用,然后通过boot2docker down来安全地关闭虚拟机。接下来就可以向Git提交本地修改,并推送到GitHub了。

那么,我们刚才都完成了什么呢?

我们建立了本地环境,通过Dockerfile详尽描述了如何构建镜像,并基于该镜像启动了相应容器。我们使用Docker Compose来将这一切整合起来,包括构建和容器之间的关联、通信(在Flask和Redis进程之间)。

接下来,我们来看一个更酷的工作流程,即通过引入 CircleCI 来实现项目的持续集成。

同样的,你可以从 此处 获取源代码。

Docker Hub

到目前为止我们已经接触过Dockerfile、镜像以及容器(当然,借助了Docker Compose的帮助)。

如果你很熟悉Git的工作流程,那么可以把Docker镜像理解为Git的repo,而容器类似于该repo的clone,如果将这个比喻继续类推下去,那么 Docker Hub 也就相当于GitHub的地位了。
  • 为了使用Docker Hub,你可以用GitHub账号来完成注册
  • 添加一个新的自动构建,将刚才完成的项目repo加入进来,一切按照默认选项即可,除了将“Dockerfile Location”改为“/web”。

一旦添加完毕,Docker Hub会进行一次初始化构建,请确保一切正常。

Docker Hub和CI

Docker Hub自身通过 配置 就可以充当持续集成服务,从而在每次推送Git提交后自动进行构建。

这意味着你不能直接将镜像推送到(通过docker push)Docker Hub上。Docker Hub会自己从repo进行拉取并构建镜像,从而保证整个过程中没有错误。在你的工作流程中请铭记这一点,因为在Docker文档中目前并没有对此进行详细说明。
让我们来试一下,加入以下测试用例:
self.assertNotEqual(four, 5)

提交并推送到GitHub,然后就可以看到Docker Hub如何开始一次新构建了。

由于这是项目部署上线前的最后一道防线,我们当然希望Docker Hub在构建完成之前,能够捕获所有的错误和异常。另外,你肯定也希望能将自己的单元测试和集成测试加入到持续集成流程中, 而这正是CircleCI的用武之地。

CircleCI

circleci.png

CircleCI 是一个持续集成/发布平台,支持对Docker容器进行测试。你只需提供一个Dockerfile,CircleCI会据此构建镜像,并启动一个新容器,然后在其中运行你的测试。

还记得我们期望的工作流程吗? 链接

现在来看看如何完成它。

安装

CIrcleCI官方提供了很好的 入门指导

使用GitHub账号完成注册,然后将你的GitHub repo添加为一个新项目(成功后会收到邮件通知)。这会为该repo增加一个hook,每当你向其推送新的提交时,都会触发一次新的构建。

接下来需要向我们的repo添加一个配置文件,用以指导CircleCI完成构建。

circle.yml的文件内容如下:
machine:
services:
- docker

dependencies:
override:
- pip install -r requirements.txt

test:
override:
- docker-compose run -d --no-deps web
- python web/tests.py

实际上,我们构建了一个新的镜像,并启动了一个新容器,然后进行测试:首先检查web应用是否正常启动运行,然后逐一进行单元测试。

你应该已经注意到我们在这里使用了命令docker-compose run -d --no-deps web而不是docker-compose up来启动应用,这是因为CircleCI已经集成了可用的Redis 运行时环境,所以我们只需启动web应用进程就可以了。
当circle.yml文件修改完成,就可以推送到GitHub来启动一次新构建了。记住,这将同时在Docker Hub上启动一次构建。

一切正常?

在继续下去之前,需要对工作流程进行一些调整,因为我们通常不希望将提交直接推送到master分支上。

功能分支工作流程

>如果不太熟悉这一工作流程,那么可以从 此处 获得准确生动的解释。

让我们来快速浏览一个示例:

创建功能分支

$ git checkout -b circle-test master
Switched to a new branch 'circle-test'

更新应用

在texts.py里增加一个新的断言:
self.assertNotEqual(four, 6)

发起一个Pull Request

$ git add web/tests.py
$ git commit -m "circle-test"
$ git push origin circle-test

甚至在你真正发起PR之前,CircleCI就已经启动了构建。在PR创建完毕后,只需等待CircleCI通过所有测试,我们就可以点击Merge按钮来合并入master分支了。一旦merge成功,Docker Hub就会触发相应的构建过程。

重构工作流程

如果回到本文开头的工作流程处,你会发现我们实际上希望Docker Hub在master分支上再次进行测试后才启动构建,所以让我们来对现有流程进行以一些快速的调整:

打开你的Docker Hub仓库,在Settings下选择Automated Build。
取消对“When active we will build when new pushes occur”的选中状态。
  1. 保存。
  2. 选择位于Settings下的Build Triggers。
  3. 将status改为on。
  4. 复制以下curl命令:$ curl --data "build=true" -X POST https://registry.hub.docker.co ... 3b66/

将以下代码加入到circle.yml文件末尾:
deployment:
hub:
branch: master
commands:
  - $DEPLOY

现在我们会在merge到master分支并通过测试之后,执行$DEPLOY环境变量所代表的命令,我们需要将这个变量的值加入到CircleCi的环境变量中:
  • 打开 Project Settings,选择 Environment variables。
  • 添加一个名为“Deploy”的新变量,并且将刚才复制的curl命令粘贴进去作为该变量的值。

现在来检验一下成果:
$ git add circle.yml
$ git commit -m "circle-test"
$ git push origin circle-test

发起一个新的PR,一旦其通过CirecleCI测试,将其merge到master分支,这会触发另一次构建。一旦再次通过测试,之前设置的curl命令就会触发Docker Hub去启动一次新构建,一切都很完美。

结论

我们已经跑通了这个基于CircleCI的持续集成工作流程(步骤1-6):
  1. 在本地功能分支上完成应用代码。
  2. 在GitHub上发起一个到master分支的Pull Request。
  3. 在Docker容器上运行自动测试。
  4. 如果测试通过,手动将这个PR merge进master分支。
  5. 一旦merge成功,再次运行自动测试。
  6. 如果第二次测试也通过,就在Docker Hub上对应用进行构建。
  7. 一旦构建完成,自动化地部署到生产环境。

关于整个流程的最后一块拼图呢:及自动化地将应用发布到盛传环境(第7步),你可以在我的另一篇博客中得到答案。

原文链接:Docker in Action - Fitter, Happier, More Productive(翻译:李明 校对:宋瑜)

===========================
译者介绍
李明(微信:hydRAnger; 邮箱: armyiljfe@gmail.com ; GitHub:  https://github.com/hydRAnger  ),云栈科技前端程序猿,本科、硕士皆为生物科学方向,出于热情转投IT领域,做过游戏开发,兴趣广泛以致杂而不精,还需精进,欢迎交流、指导。目前关注于web相关技术、Docker、开源软硬件等领域。

原文发布时间为:2015-03-02
本文作者:hydRAnger
本文来自云栖社区合作伙伴DockerOne,了解相关信息可以关注DockerOne。
原文标题:Docker实战:更轻松、更愉快、更高效
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
3天前
|
关系型数据库 应用服务中间件 PHP
实战~如何组织一个多容器项目docker-compose
本文介绍了如何使用Docker搭建Nginx、PHP和MySQL的环境。首先启动Nginx容器并查看IP地址,接着启动Alpine容器并安装curl测试连通性。通过`--link`方式或`docker-compose`配置文件实现服务间的通信。最后展示了Nginx配置文件和PHP代码示例,验证了各服务的正常运行。
18 3
实战~如何组织一个多容器项目docker-compose
|
1月前
|
Java 应用服务中间件 Linux
【Docker容器化技术】docker安装与部署、常用命令、容器数据卷、应用部署实战、Dockerfile、服务编排docker-compose、私有仓库
本文主要讲解了Docker的安装与部署、常用命令、容器数据卷、应用部署实战、Dockerfile、服务编排docker-compose、私有仓库以及Docker容器虚拟化与传统虚拟机比较。
535 11
【Docker容器化技术】docker安装与部署、常用命令、容器数据卷、应用部署实战、Dockerfile、服务编排docker-compose、私有仓库
|
19天前
|
存储 缓存 监控
Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
本文介绍了Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
54 7
|
1月前
|
SQL 关系型数据库 数据库
国产数据实战之docker部署MyWebSQL数据库管理工具
【10月更文挑战第23天】国产数据实战之docker部署MyWebSQL数据库管理工具
135 4
国产数据实战之docker部署MyWebSQL数据库管理工具
|
28天前
|
运维 Cloud Native 云计算
云原生之旅:Docker容器化实战
本文将带你走进云原生的世界,深入理解Docker技术如何改变应用部署与运维。我们将通过实际案例,展示如何利用Docker简化开发流程,提升应用的可移植性和伸缩性。文章不仅介绍基础概念,还提供操作指南和最佳实践,帮助你快速上手Docker,开启云原生的第一步。
|
1月前
|
机器学习/深度学习 数据采集 Docker
Docker容器化实战:构建并部署一个简单的Web应用
Docker容器化实战:构建并部署一个简单的Web应用
|
21天前
|
Kubernetes Linux 开发者
深入探索容器化技术——Docker 的实战应用
深入探索容器化技术——Docker 的实战应用
67 0
|
22天前
|
存储 Cloud Native 开发者
深入探索容器化技术——Docker的实战应用
深入探索容器化技术——Docker的实战应用
35 0
|
22天前
|
存储 安全 Docker
Docker 的实战应用与优化策略
Docker 的实战应用与优化策略
33 0
|
23天前
|
JavaScript Linux 持续交付
深入探索容器化技术——Docker 的实战应用
深入探索容器化技术——Docker 的实战应用
48 0