Docker for Devs — 如何将应用容器化

我们来聊聊Docker。如果你想容器化你的应用,这篇文章可以作一些指导,帮助你使用Dockerfiles和创建镜像

作为一个开发者,我们经常在寻找捷径或者更简单的方法来取得成功。如果你是一个团队的负责人,那让你的团队也来看看这篇内容,安装、并且用最小的错误和痛苦来完成是非常重要的。Docker就能帮你做到。

在软件开发领域,模块化是逐渐强调的重点,从单一职责等一般原则到更具体的实施,模块化java脚本功能变为无状态组件。现在,我将展示我们为了一些优点,是如何使用Docker来模块化我们的开发环境,包括帮助我们取得成功。

20170206214604

Docker开发人员

如你所知,随着一个项目的的进行,你有一个应做事项的检查表:

  • 从资源库中拉出代码库。
  • 安装外部工具,例如数据库、缓存存储、其他的工具和服务。
  • 安装补丁,更新外部工具。
  • 为跨应用程序通信准备配置数据库和服务。
  • 交叉手指握拳并祷告(时间可能会有所不同)
  • 调试(至少重启3次)

想象一下,如果在把应用程序的代码库从存储库中拉出,你只需要运行少量的命令(可能只有一个)就让全部的应用环境准备运行。

听上去是不是很酷?

这正是我们实现的。使用Docker来取代一个百科全书式的方法来安排所有的特性和代码,在使用Docker容器化开发环境时,我会介绍它的主要的特性。

本文是系列文章中的第一部分,利用Docker容器化的力量来简易的创建一个应用开发环境,它可以在任何时候共享、启动和运行。

Docker工具箱和Docker for X

Docker工具箱是工具的原始集合,用来处理大量的Docker资源,并且根据你选择的操作系统变化。但是自那之后,他们已经发布新的Windows和Mac原生应用。所以除了Linux、OS X和Windows Docker工具箱变化,也将看到“Docker for Mac”和“Docker for Windows”。

为了了解和决定该用哪个工具,我先概述下新的原生应用的前提。原始Docker工具箱设置了大量的工具,连同使用VirtualBox。它还提供一个虚拟机在Linux Hypervisor上运行Windows或Mac。

VirtualBox,Hyper-V和Hyperkit

原生应用,例如Docker在Mac的情况下,安装实际原生OS X应用。它也不再使用VirtualBox,但是OS X虚拟机管理程序hyperkit。此外,共享接口和网络管理更加简便。也有一些用户体验更新工具也可以用来和Docker一起运用。这些相同的变化也是在Docker for Windows原生应用中比较明显的,利用Hyper-V虚拟机管理程序代替,连同其他类似网络主机和工具更新。

最后,体验应该是积极的,有效的和更少的出错。然而,你会发现大多数的外部文档与工具箱有关,所以它对于你了解工具箱有帮助。

Getting Started!

一开始的教程会用一个即开即用的express.js应用程序。当我们开始编辑资源代码和容器间通信的时候,会用一个更复杂、更普通的React.js应用,在Webpack’s dev-server中运行,通过热模块加载、MongoDB数据库和其他。

第一步:安装

为了使用Docker和容器化开发环境与大量、不同的操作系统版本的各种优点,需要先下载一个Docker版本(工具箱或原生)和操作系统:

Toolbox: https://www.docker.com/products/docker-toolbox (OS X and Windows)
Docker for Windows: https://www.docker.com/products/docker#/windows
Docker for Mac: https://www.docker.com/products/docker#/mac

工具箱用户:Docker工具箱伴随着一个“Docker快速入门终端”,并且当它运行时连接到Docker环境。然而,它一般单独运行一个终端或者在你选择的IDE内。为了让Docker和其他终端/提示相互作用,需要运行“docker-machine env”来初始化Docker env。结束时显示的文本是一个命令,需要从在同样的终端/提示内复制/粘贴到初始化的Docker环境。

第2步:资源代码/环境

接下来的步骤就是获得你想容器化的开发应用的资源代码。

到目前为止,可以从GitHub抓取这部分项目(https://github.com/hyndsite/docker-4-devs),我正在用这个教程的一部分,可以节省一些步骤。

第3步:创建一个Docker镜像文件

记住,主要目标是在一个隔离的和模块化的环境中运行应用程序。为了让Docker创建这样的环境,必须告诉它如何创建。我们用一组Docker镜像文件指令集(https://docs.docker.com/engine/reference/builder/)。

  1. 使用选择的IDE,增加一个文件,命名“Dockerfile”到项目root
  2. 复制下面的内容

注意:这个Docker镜像文件将允许创建一个镜像,这个镜像将表示我们之前说到的容器化环境,最终创建这个叫做容器的镜像的运行实例。但是我们先跳过这个,移至步骤5。

Dockerfile

FROM mhart/alpine-node:6.9.2
WORKDIR /var/app
COPY . /var/app
RUN npm install –production
EXPOSE 3000
ENV NODE_ENV=production
CMD [“node”, “bin/www”]

Dockerfile是Docker在镜像文件中查找的默认名称,但是它可以是任意的名字,这个我们将在后面说到。以下指令告诉Docker我们将创建镜像:

  • RORM一个基础镜像,mhart/alpine-node通过标签6.9.2
  • 设置程序将运行的工作目录WORKDIR
  • 复制当下本地目录“.” 的内容到指定位置
  • 然后从WORKDIR运行命令“npm install —production”
  • 当它从镜像中创建时,从容器开放3000端口
  • 另外,我们曾想创建一个容器NODE_ENV的局部ENV变量,设置为“production”
  • 最后,启动express.js服务,在属于“bin”目录的“www” 的文件中执行命令“node bin/www”

提示:Docker永远需要一个基础镜像,保持镜像尽可能小的封装是关键。alpine-node镜像建立在非常小的(49.65mb)包括Node.js和NPM的基础上。

第4步:创建镜像

现在我们已经有一个Docker镜像文件,规定了如何创建一个镜像的细节,我们停下先谈谈什么是镜像:

20170206214615

镜像是一个只读的分层文件系统。它构成了我们一直逃避的环境的基础文件系统。在之前步骤中创建的镜像文件会指导Docker如何创建镜像的每个图层,我们现在将从Dockerfile中创建。

但是如果它只是一个“只读”文件系统,那我们将怎么写入(例如,在开发中执行代码改变应用代码库)?好问题,我将在下一个步骤中回答。

1、创建Production镜像

  • 从一个终端/提示引导到项目目录的root
  • 运行命令(包括周期结束):
docker build -t express-prod-i .

提示:Docker工具箱,从任何地方除了Docker 快速启动终端运行Docker命令,结果将会导致错误(基于不同操作系统)。为了在任意的终端/提示上运行,需要连接终端/提示到docker环境。运行docker-machine env,并且运行命令例如e.g. “ @FOR /f “tokens=*” %i IN (‘docker-machine env’) DO @%i”

我们做了什么?

  1. 从我们在步骤3中创建的Docker镜像文件,运行build命令来创建一个镜像。
  2. 使用tag切换-t,给镜像命名可以用来说明它,不必必须涉及Docker生成的ID (e.g. 50e8dde7e180)
  3. 指定镜像的路径,是当前本地目录指定的 “.”

2、核实镜像

如果所有如计划运行,我们可以看到(和下面的图片中一样)一个“成功的创建”信息。现在可以运行一个命令,你会牢记展示的图片:

docker images

20170206214641

在这个情况下,组合的镜像是61.26MB大小,由基础alpine-node镜像和express应用层组成。

3、回顾镜像文件层

如果想看文件层,可以运行以下命令:

docker history express-prod-i

20170206214649

第5步:运行一个实例

现在已经创建了一个镜像,我们准备为应用创建一个隔离的、模块化的环境。我已多次提到,这个环境是一个Docker容器。Docker容器是实际上镜像的运行实例。

仅仅在概念上,镜像和容器是非常类似于Javascript Prototype或OOP Class。所以,我们来运行下创建的镜像实例。

1、生成并运行镜像实例

运行命令:

docker run -d --name express-prod-app -p 7000:3000 express-prod-i

启动浏览器,打开http://localhost:7000.

20170206214657

我们做了什么?

我们创建并运行一个实例, express-prod-i镜像被认为是一个容器:

  • 使用run命令
  • 指定分离模式-d标志(所以不占用当前终端/提示)
  • 并且命名 “express-prod-app” 到容器,使用–name标志
  • 在主机上连同本地端口7000映射到内部容器端口,开放的3000使用-p标志
  • 最后,指定“express-prod-i”镜像为生产和运行实例

注意:我使用不同的本地7000端口来展示,你可以在容器中映射任何主机上未使用的端口到开放的内部端口。

提示:没有-d,我们将在连接模式下启动运行中容器。这意味着它将把所有从容器目录中的输出发送到执行命令的终端/提示中。在分离模式下启动的容器,可以继续在容器运行的终端/提示中运作。

有没有发现,我们没有安装本地Node.js或NPM。无需运行npm安装本地主要应用,并且无需从主机运行应用。所有这些都在主机中发生,这是个简单的experss.js demo站点。

2、核实运行中容器

1. 可以使用以下命令来观察运行中的容器:

docker ps

20170206214704

2. 这可以展示运行中的容器,还可以指定-a标志来看所有容器。在出错或运行中容器意外退出时很有用:

docker ps -a

第6步:起停容器

停止正在运行的容器:

docker stop express-prod-app

启动:

docker start express-prod-app

第7步:删除镜像和容器

当走完所有这些步骤,也许会放弃一个镜像并且重新开始。可以按下面的步骤。另外,下面的Bonus部分,有一些有用的快捷键。

1、删除容器

删除一个容器,可以用 “rm” 命令:

docker rm express-prod-app

恢复容器,可以用之前发布的命令:

docker run -d --name express-prod-app -p 7000:3000 express-prod-i

2、删除镜像

删除镜像,可以用“rmi” 命令:

docker rmi express-prod-i

恢复镜像,可以用之前发布的命令:

docker build -t express-prod-i .

提示:删除镜像和容器命令可以获得镜像或容器的ID,甚至是ID前几个少了字符。所以可以选择规定任意一个。

Bonus

除了删除镜像和容器的步骤,还可以利用一些有用的快捷键,总算派上用场了。

删除所有容器

删除所有容器,运行下面的“rm”命令,但是执行恢复所有容器的命令在其中:

docker rm $(docker ps -a -q)

Windows用户:将需要一个bash shell来运行接下来的命令。主要因为GNU让我们用的参考变量$( )。可以安装一些“Bash on Ubuntu on Windows” 或甚至是GIT bush。只要记住,需要通过docker-machine env连接中断,并且在最后运行eval命令。

我们做了什么?

  1. 发布了容器删除命令“rm”
  2. 但是代替提供tag或容器ID,我们提供了一个容器ID列表
  3. 提供所有ALL (-a)标志伴随着QUIET (-q),只有返回数字容器IDs

删除所有镜像

删除所有镜像,可以做一些类似的使用一出镜像命令“rmi”.

docker rmi $(docker images -q)

我们做了什么?

  1. 我们使用一出镜像命令,但是代替给他一个docker镜像IDs列表
  2. 通过使用docker镜像镜像列表
  3. 指定 QUIET (-q)标志,至返回数字Docker IDs

成果?我以为我们已经创建了一个应用开发容器?

我们刚刚创建的已通知express.js和Node.js,要在生产中运行的镜像。所以怎么了?

还记得我们需要一个基础镜像吗?并且谁想必须“重建”一个镜像,每次我们在应用开发中做出改变?所以我们要把生成镜像作为一个基础镜像,并且隔离开发改变到图层镜像指定开发。

结论

所以,我已经说了很多关于Docker的知识。创建一个镜像文件,创建一个镜像并用这个镜像生成一个运行中的容器。但是我们还有很多要做。

所以在这个系列的下一篇文章,我将解决一个镜像,将会成为我们开发版本或应用,但是根据生产镜像。我们也可以看看如何在容器中利用脚本来帮助设置本地环境,来改变资源代码。

K8S中文社区微信公众号
分享到:更多 ()