如何使用 Docker 管理云中的部署
在Twitter上关注我,很高兴接受您对主题或改进的建议/Chris
如今,在一个或多个容器中开发和交付应用程序变得越来越普遍。Docker 是最常见的容器化软件之一。它是一款非常棒的工具,可以轻松创建镜像和容器,并对其进行监控。如果我们能够继续使用 Docker 并将我们的应用程序迁移到云端,那岂不是很棒?
Azure 容器实例支持将 Docker 容器部署到 Azure 基础架构上,而无需配置任何虚拟机或采用更高级别的服务。
在本文中,我们将执行以下操作:
- 解释一下我们为什么需要云
- 从 GitHub克隆应用程序源代码,让我们更专注于将应用程序迁移到云端,而不是从头开始编写,因此让我们采用现有的应用程序
- 从应用程序源创建容器镜像,这是我们需要做的准备步骤
- 在本地 Docker 环境中测试镜像,在将软件推送到云端之前,在本地试用软件始终是一个好习惯
- 创建一个容器注册表,这是 Azure 上存储 Docker 镜像的东西
- 部署我们的应用程序,我们可以从容器注册表中的一个镜像创建一个容器实例
资源
如果你错过了我们在本文中提到的链接,请查看:
-
安装 Azure CLI
Azure CLI 是一款出色的终端工具
,它几乎可以让你完成在门户中可以做的所有事情 -
az 容器命令
该az container
命令有多种调用方式。请参阅上面的链接,了解这些调用方式。 -
学习容器注册表模块
本模块将教您有关容器注册表的所有知识 -
Docker 教程系列
本系列包含 5 部分,带您从零开始学习 Docker Compose 和多种服务。如果您需要学习 Docker 或巩固相关知识,本系列将是您的理想之选。 -
VS Code 的 Docker 扩展
我的优秀同事 Shayne Boyer 解释了如何使用 VS Code 的扩展,以及如何在不离开 VS Code 的情况下完成我即将向您展示的操作
云计算的前景
使用容器技术,我们可以将应用程序拆分成多个服务。此外,它还提供了一种安全可靠的应用程序交付方式。接下来的问题是,我们应该将应用程序交付到哪里?本地部署还是云端?
本文探讨的是将应用程序交付到云端,因此我们当然会有些偏见。让我简要解释一下为什么我们认为云端是应用程序的理想选择:
- 成本效益,它指的是您只需为实际使用的内容付费。在本地部署场景中,您可能会为服务器、CPU、内存等付费,因为您认为用户和使用量会增加。这会是一笔很大的现金支出,您需要问问自己,我是否愿意花时间去了解我的需求,并且随着时间的推移,还要花费时间和金钱去升级它?
- 可扩展性,云可以轻松地进行水平和垂直扩展,添加新员工不是问题,添加更多服务器、数据库也不是问题,我们可以在几分钟内完成
- Elastic,想象一下你是一家电商公司,在节假日或黑色星期五等节假日用户量突然激增。云可以动态地添加你所需的额外资源来应对这种情况,当然,当用户数量下降到更正常的水平时,它也可以动态地缩减规模。
先决条件
您需要安装以下内容
克隆应用程序
我们最初说过,我们将更多地关注如何部署而不是编写应用程序,因此,我们将使用一个预制的应用程序,您可以从这里下载:
观察它,你会发现这是一个Node.js
正在运行的非常简单的应用程序Express
。为了演示,我们在 Repository 中关注了两个文件:
- app/index.js,这是应用程序的入口点
- Dockerfile,它将
Dockerfile
帮助我们将应用程序构建成一个镜像,并最终成为一个包含应用程序的容器。
让我们看一下 app/index.js 文件:
// app.js
const express = require('express');
const morgan = require('morgan');
const app = express();
app.use(morgan('combined'));
app.get('/', (req, res) => { res.sendFile(__dirname + '/index.html') });
var listener = app.listen(process.env.PORT || 80, function() {
console.log('listening on port ' + listener.address().port);
});
上面我们可以看到它是非常标准的 Node.js + Express 应用程序,这里没有什么魔法。
现在让我们看一下 Dockerfile:
// Dockerfile
FROM node:8.9.3-alpine
RUN mkdir -p /usr/src/app
COPY ./app/ /usr/src/app/
WORKDIR /usr/src/app
RUN npm install
CMD node /usr/src/app/index.js
它执行以下操作:
- 选择一个操作系统映像
Node.js
,简而言之,我们基于 Ubuntu 和预装的名为 alpine 的版本来创建操作系统。 - 使用以下命令创建目录mkdir -p /usr/src/app
- 将所有文件从 ./app/ 复制到 /usr/src/app/
- 将工作目录设置为 /usr/src/app
- 使用 npm install安装我们的节点依赖项
- 使用 node /usr/src/app/index.js启动我们的应用程序
总而言之,这是一个非常标准的 Dockerfile。
构建映像
构建镜像是我们应用程序实际启动之前需要做的准备步骤。构建步骤会加载我们所需的操作系统镜像,下载依赖库,并将我们的应用代码复制到镜像位置等等。
我们可以使用 docker build 命令来构建镜像。我们需要使用的具体命令是:
docker build./aci-helloworld-t aci-tutorial-app
上述命令在目录 /aci-helloworld 中查找 Dockerfile,并创建一个名为 aci-tutorial-app 的镜像。运行该命令应产生如下输出:
上面向我们展示了我们在 Dockerfile 中设置的所有步骤,例如:
- 关闭节点:8.9.3-alpine OS 映像,复制我们的应用程序
- 设置 WORKDIR,
- 通过运行 NPM INSTALL 安装依赖项,
- 使用 CMD node /user/scr/app/index.js 启动应用程序
如果我们运行以下命令,我们可以看到我们创建的图像:
Docker 镜像
好的,那么,我们有一个图像,这意味着我们已经准备好进行下一步了;在本地测试它。
通过实例化容器来测试镜像
现在我们有了镜像,可以使用 docker run 命令从中创建一个容器。完整命令如下:
docker run -d -p 8080:80 aci-tutorial-app
让我们看一下论点:
- -d,这告诉容器在后台运行
- -p,这允许我们映射端口,参数值应该像这样解释[外部端口]:[容器内部端口]
我们可以看到外部端口是 8080,这意味着我们可以导航到
http://localhost:8080 以确保我们的应用程序正常运行。
这是我们得到的图像,所以我想说我们的容器正在工作:
使用以下命令我们可以列出所有正在运行的容器:
docker ps 它应该显示以下结果:
我们不希望容器运行并耗尽资源,所以让我们关闭它。我们想运行命令 docker kill 来关闭容器,但是该命令需要一个参数,也就是容器 ID。还记得我们运行 docker kill 的时候docker ps
吗?第一列是 docker kill container id
。不过,我们不需要完整的 ID,只要前 4 个字符就足够了。所以,让我们开始执行命令吧。
docker kill [容器 id, 前 4 个字符] docker ps // 它应该是一个空列表 就是这样。这是我们刚刚运行的命令的屏幕截图:
创建容器注册表
Azure 容器注册表是您在 Azure 中的私有 Docker 注册表。
要实现此功能,我们需要 Docker、Docker Engine 和 Azure CLI。目前我们已经安装了 Docker,接下来看看如何安装 Azure CLI:
https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest
在创建上述注册表之前,我们需要一个Resource Group
。 它Resource Group
是一个逻辑容器,我们需要将所有资源(例如应用程序、数据库以及现在的 )放置在其中Resource Group
。同一组中的所有内容都可以轻松安全地进行通信。
因此我们先创建它:
az group create --name [your name for a resource group] --location westeurope
一旦Resource Group
创建完成,我们就可以回去创建我们的了Container Registry
。
该命令如下所示:
az acr create --resource-group [your name for your resource group] --name [your name for a registry] --sku Basic --admin-enabled true
让我们稍微分析一下。
az acr 创建
是创建我们的实际命令Container Registry
。然后我们需要一些参数:
- --resource-group,这需要一个参数,该参数应该是我们新创建的资源组
- --name,这是我们为注册表指定的名称,例如 containerregistry
- --sku,这是价格计划,我们选择最便宜的,称为 Basic
您应该得到如下所示的输出:
{
"adminUserEnabled": true,
"creationDate": "2018-03-16T21:54:47.297875+00:00",
"id": "/subscriptions/<Subscription ID>/resourceGroups/myResourceGroup/providers/Microsoft.ContainerRegistry/registries/mycontainerregistry082",
"location": "eastus",
**"loginServer": "[your container registry name].azurecr.io"**,
**"name": "containerregistry"** ,
"provisioningState": "Succeeded",
"resourceGroup": "myResourceGroup",
"sku": { "name": "Basic", "tier": "Basic" },
"status": null,
"storageAccount": null,
"tags": {},
"type": "Microsoft.ContainerRegistry/registries"
}
重要的是获得provisionState
有价值的回报Succeededed
。
登录我们的注册表
我们需要先登录到镜像仓库,然后才能将 Docker 镜像推送到其中。因此,让我们登录:
az acr login --name [name of container registry]
这应该告诉你Login Succeeded
一切是否顺利
您的输出应该类似于以下内容:
从上面您可以看到,我选择调用注册表chriscontainerregistry
,但您必须将其替换为您选择的名称。
标记容器镜像
要将容器镜像推送到像 这样的私有注册表Azure Container Registry
,您必须首先使用注册表的登录服务器的全名标记该镜像。
您可以通过查看创建注册表时的 JSON 输出来找到答案。您正在寻找一个名为 的属性"loginServer"
。它的格式为[your registry name].azurecr.io
。在我的例子中,它的格式是chriscontainerregistry.azurecr.io
。
loginServer
因此,您可以记住我们创建容器注册表时的名称,也可以随时loginServer
通过调用以下命令来检索后者:
az acr show --name [container registry name] --query loginService --output table
这将loginServer
在终端中打印出名称。当然,在我们的例子中,[容器注册表名称] 就是值chriscontainerregistry
,因此请根据您选择的名称进行相应调整。
现在让我们回到 Docker。我们需要使用容器注册表的 loginServer标记aci-tutorial-app 镜像。
我们使用以下命令对其进行标记:
docker tag aci-tutorial-app /aci-tutorial-app:v1
让我们来分析一下。
- aci-tutorial-app,这是我们镜像的名称,如果你想验证的话,请运行 docker image
- /aci-tutorial-app:v1,这会以某种方式标记镜像,以便将其推送到我们的容器注册表。不过需要注意的是,:v1 是一个版本号,但我们可以轻松地将其称为 LATEST 或今天的日期。关键在于建立一个系统,以便您知道是否要使用特定的镜像。
因此,在我们的例子中,使用正确值的正确命令是:
docker tag aci-tutorial-app [容器注册表名称].azurecr.io/aci-tutorial-app:v1
此时运行 docker images 命令,验证镜像是否正确创建。镜像内容应该类似如下:
将镜像推送到存储库
现在我们可以将镜像推送到仓库了。执行以下命令:
docker push /aci-tutorial-app:v1
并且所有正确的值都到位后,它将是:
docker push chriscontainerregistry.azurecr.io/aci-tutorial-app:v1
您可能需要先登录,在这种情况下,您可以运行以下命令:
az acr login — name [容器注册表名称]
执行 docker push 应该会呈现以下结果:
列出存储库中的图像
好的,现在我们实际上想看看里面有什么图像,剧透一下,里面应该是我们刚刚上传的图像;)
我们可以运行以下命令:
az acr repository list --name --output table
使用正确的 acrName 值它将如下所示:
az acr repository list --name [name of container registry] --output table
这就是我们唯一推送的图像:)
部署应用程序
现在我们在存储库中有了我们的镜像,我们可以告诉存储库从我们的镜像创建一个容器,从而部署我们的应用程序。
要运行我们的部署命令,我们首先需要一些信息,即以下内容:
- 登录服务器,我们可以为其运行以下命令
az acr show --name --query loginServer
- 用户名和密码,为此我们运行以下命令:
az acr credential show --name --query "passwords[0].value"
这将返回密码
好的,现在我们来看看部署命令,它可能看起来有点吓人:
az container create --resource-group myResourceGroup --name aci-tutorial-app --image <acrLoginServer>/aci-tutorial-app:v1 --cpu 1 --memory 1 --registry-login-server <acrLoginServer> --registry-username <acrName> --registry-password <acrPassword> --dns-name-label <aciDnsLabel> --ports 80
创建容器的方法有很多种,如果您对其他方法感兴趣,请查看此链接az container create
检查进度和日志
如果部署需要一段时间,您可以同时使用以下命令检查状态:
az container show --resource-group [name or resource group] --name aci-tutorial-app --query instanceView.state
在收到很长的 JSON 响应后,查找provisioningState: Succeded
,如果有,那就很好了。
让我们使用以下命令查看我们的容器:
az container show --resource-group [name of resource group] --name aci-tutorial-app --query ipAddress.fqdn
我们可以通过运行以下命令来查看应用程序中的日志:
az container logs --resource-group [name of resource group] --name aci-tutorial-app
这将告诉我们在端口 80 上运行
访问已部署的应用程序
一旦部署完成,我们就可以通过 --dns-name-label 值访问该应用程序,如下所示:
概括
我们打算部署一个应用程序。这次我们想部署一个 Docker 容器。为此,我们首先需要创建一个 Docker 镜像。所以我们使用 docker build 命令创建了一个。
然后我们意识到我们需要一个Container Registry
,因为我们将从那里部署我们的图像,即实例化一个 docker 容器并部署它。
为了使其最终完成,Container Registry
我们首先需要用 loginServer 名称对其进行标记,然后我们推送标记的图像。
最后,我们告诉它Container Registry
从镜像创建一个容器并进行部署。部署完成后,我们可以在浏览器中验证应用是否已部署完成,成功了 :))
其实步骤并不多。假设我们的应用包含 3 个其他服务,我们只需要为每个服务构建一个镜像、打标签、推送,然后创建一个容器。
鏂囩珷鏉ユ簮锛�https://dev.to/azure/how-you-can-use-docker-to-manage-deployments-in-the-cloud-2k4i