我们来聊聊Docker。如果你想容器化你的应用,这篇文章可以作一些指导,帮助你使用Dockerfiles和创建镜像。
作为一个开发者,我们经常在寻找捷径或者更简单的方法来取得成功。如果你是一个团队的负责人,那让你的团队也来看看这篇内容,安装、并且用最小的错误和痛苦来完成是非常重要的。Docker就能帮你做到。
在软件开发领域,模块化是逐渐强调的重点,从单一职责等一般原则到更具体的实施,模块化java脚本功能变为无状态组件。现在,我将展示我们为了一些优点,是如何使用Docker来模块化我们的开发环境,包括帮助我们取得成功。
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/)。
- 使用选择的IDE,增加一个文件,命名“Dockerfile”到项目root
- 复制下面的内容
注意:这个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镜像文件,规定了如何创建一个镜像的细节,我们停下先谈谈什么是镜像:
镜像是一个只读的分层文件系统。它构成了我们一直逃避的环境的基础文件系统。在之前步骤中创建的镜像文件会指导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”
我们做了什么?
- 从我们在步骤3中创建的Docker镜像文件,运行build命令来创建一个镜像。
- 使用tag切换-t,给镜像命名可以用来说明它,不必必须涉及Docker生成的ID (e.g. 50e8dde7e180)
- 指定镜像的路径,是当前本地目录指定的 “.”
2、核实镜像
如果所有如计划运行,我们可以看到(和下面的图片中一样)一个“成功的创建”信息。现在可以运行一个命令,你会牢记展示的图片:
docker images
在这个情况下,组合的镜像是61.26MB大小,由基础alpine-node镜像和express应用层组成。
3、回顾镜像文件层
如果想看文件层,可以运行以下命令:
docker history express-prod-i
第5步:运行一个实例
现在已经创建了一个镜像,我们准备为应用创建一个隔离的、模块化的环境。我已多次提到,这个环境是一个Docker容器。Docker容器是实际上镜像的运行实例。
仅仅在概念上,镜像和容器是非常类似于Javascript Prototype或OOP Class。所以,我们来运行下创建的镜像实例。
1、生成并运行镜像实例
运行命令:
docker run -d --name express-prod-app -p 7000:3000 express-prod-i
启动浏览器,打开http://localhost:7000.
我们做了什么?
我们创建并运行一个实例, 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
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命令。
我们做了什么?
- 发布了容器删除命令“rm”
- 但是代替提供tag或容器ID,我们提供了一个容器ID列表
- 提供所有ALL (-a)标志伴随着QUIET (-q),只有返回数字容器IDs
删除所有镜像
删除所有镜像,可以做一些类似的使用一出镜像命令“rmi”.
docker rmi $(docker images -q)
我们做了什么?
- 我们使用一出镜像命令,但是代替给他一个docker镜像IDs列表
- 通过使用docker镜像镜像列表
- 指定 QUIET (-q)标志,至返回数字Docker IDs
成果?我以为我们已经创建了一个应用开发容器?
我们刚刚创建的已通知express.js和Node.js,要在生产中运行的镜像。所以怎么了?
还记得我们需要一个基础镜像吗?并且谁想必须“重建”一个镜像,每次我们在应用开发中做出改变?所以我们要把生成镜像作为一个基础镜像,并且隔离开发改变到图层镜像指定开发。
结论
所以,我已经说了很多关于Docker的知识。创建一个镜像文件,创建一个镜像并用这个镜像生成一个运行中的容器。但是我们还有很多要做。
所以在这个系列的下一篇文章,我将解决一个镜像,将会成为我们开发版本或应用,但是根据生产镜像。我们也可以看看如何在容器中利用脚本来帮助设置本地环境,来改变资源代码。
评论前必须登录!
注册