在常见的软件架构体系中,容器无疑是一个技术热点。有些开发者在工作中熟练使用容器技术,有些可能刚刚开始容器之旅。
面对容器使用经验不同的各类开发者,我们希望通过这个系列文章,由浅入深地介绍如何使用容器技术来构建,运维我们的软件应用程序。
贯穿整个系列,我们将持续构建一个名为 Picturesocial 的应用。
它是一个可以分享照片的社交媒体平台。通过 Picturesocial 应用的构建过程,我们将和开发者分享如何选择合适的应用架构心得和实践。
亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、活动与竞赛等。帮助中国开发者对接世界最前沿技术,观点,和项目,并将中国优秀开发者或技术推荐给全球云社区。如果你还没有关注/收藏,看到这里请一定不要匆匆划过,点 这里让它成为你的技术宝库!
在开始之前,我们需要先了解一些关于容器的概念,这样后面的学习会更轻松些。
请想象你正身处自己梦幻般的客厅:优雅的壁纸、可坐可卧的舒适沙发、精致的咖啡桌和几盏柔和的台灯。一切都如你所愿,但突然间你却不得不搬到另一处毛坯房,并且需要自己装修。所以你想要把卧室,以及客厅设置在邮轮海运的集装箱里。你的完美客厅和卧室就可以跟着你去到世界各地,也可以跟着你在汪洋大海里远航,还可以随着卡车在安第斯山脉中穿行,甚至可以在晴空万里中飞翔 ……
我们所说的容器就是这样一个概念:应用程序、运行时环境、文件系统都按照预先设计的逻辑进行编排打包(好比是你的精致客厅被打包进了集装箱),并在任何支持容器的环境中执行。这种设计让开发者们无比振奋,因为有了容器,应用就有了足够的灵活性,可以自由运行在任何需要它的地方。并且不用对它做任何更改。
应用的容器化,并没有将像数据库或队列管理器这样的依赖打包进去。所以,当我们计划将容器从一个环境转移到另一个环境运行时,应该预留一个位置来存放应用的环境配置,比如数据库连接字符串、时区设置等等。 这一点非常重要:它可以让应用从开发到质量安全审查,再到生产部署等各个阶段都能保持配置一致性。
当应用最终通过安全审查并进行部署时,我们就可以确信它配置了正确的数据库或依赖项。也正因为这种一致性,才不会出现高并发生产环境中的应用意外使用了开发环境的配置,使得整个应用连上了本地数据库,并最终导致所有用户的名字和内容都变成了开发过程中写的那些占位符。
现在我们已经对容器相关的概念有了一定的了解,接下来再深入了解容器最重要的文件之一:Dockerfile 文件。
以我的经历来看,Dockerfile 就好像是当年我刚参加工作当实习生时所写的东西。当年,我们一些实习生被分配了编写使用说明书的工作,就是写那种既没人读,出问题了也不管用的文档。一边编写,一边阅读手册的经历让我发现,我们写的说明书实用性差的主要问题在于,手册是人写给人看的,由于每个人的表达习惯不同以及阅读能力的局限性,它往往被诟病“描述得不清晰、不准确”。Dockerfile 则是人写给机器读的,所以它一定要写得无比准确,从而避免出现任何解释执行方面的问题。
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env WORKDIR /app # Copy everything COPY . ./ # Restore as distinct layers RUN dotnet restore # Build and publish a release RUN dotnet publish -c Release -o out # Build runtime image FROM mcr.microsoft.com/dotnet/aspnet:6.0 WORKDIR /app COPY --from=build-env /app/out . EXPOSE 5111 ENV ASPNETCORE_URLS=http://+:5111 ENTRYPOINT ["dotnet", "HelloWorld.dll"]
大部分的 Dockerfile 都会以 FROM 语句开始。这个语句说明了你自己的镜像是基于哪个基础镜像来构建的。举个例子,假如你想要创建一个需要往 Ubuntu 20.04 的实例上写入一个文件的容器,那么你可以选择这样写 FROM 语句:
FROM ubuntu:20.04
从上面的例子我们可以总结出,FROM 语句最基本的部分是它所使用的标签:
ubuntu 是镜像的名称。我们在 Docker Hub 可以找到数以百万的公有镜像来使用,而我们可以直接使用或是基于它们构建自己的镜像;
20.04 是 ubuntu 镜像的版本。从结构上来说,所有位于 “:” 之后的部分都是镜像的标签。你可以通过不同的标签来指定应用的版本、环境、语言等等。从 ubuntu 镜像的 Docker Hub 页面,我们可以找到许多不同的可用标签: https://hub.docker.com/_/ubuntu?tab=description?trk=cndc-detail
Dockerfile 中还有一些重要的命令:
RUN:用于在容器中执行多条 Bash 命令。你可以在同一个 Dockerfile 中多次使用 RUN 语句。
RUN mkdir demo
当这条语句被执行时,会在容器内创建一个名为 demo 的文件夹。
CMD:也可以执行 Bash 命令,但是只可以被使用一次。假如同一个 Dockerfile 中出现了多次,那么只有最后一条会被执行。CMD 只用于为容器提供默认的行为,比如:
CMD ["echo", "Hello World"]
在 Docker 构建时将输出 “Hello World” 这句话。
如果你希望更深入了解 Dockerfile 中的命令,Docker 官方提供的文档会非常有用:
https://docs.docker.com/engine/reference/builder/#cmd?trk=cnd...
如果你想为某种编程语言或是运行时环境找一些样例,可以访问另一则文档:
https://docs.docker.com/samples/?trk=cndc-detailDockerfile
就好比一本食谱,我们可以在任何相似的应用部署中重复使用它们。比如我会在 Picturesocial 所公开给外部的全部接口上使用同样的一个 .NET 6 Dockerfile 模板。
我们再来深入认识一下亚马逊云科技提供的容器注册库吧。
我们可以使用 Amazon Elastic Container Registry (Amazon ECR) 来存放自己的容器镜像,它们可以是公开的,也可以是私有的。这样做的好处是由 Amazon Identity and Access Management (Amazon IAM) 服务来管理所有对自己镜像的访问,而不是使用来自外部的凭证信息。
下面让我们通过一个具体的实验,了解如何将一个 API 容器化,然后推送到 Amazon ECR 中。
https://signin.amazonaws.cn/signup?request_type=register&nc2=...
https://docs.microsoft.com/en-us/windows/wsl/install?trk=cndc...
https://github.com/git-guides/install-git?trk=cndc-detail
https://docs.docker.com/engine/install/?trk=cndc-detail
https://docs.amazonaws.cn/cli/latest/userguide/getting-starte...
https://docs.amazonaws.cn/aws/latest/userguide/managing-aws.h...
我们会学习如何将一个用 C# 开发的 .NET 6 API 容器化封装。这个 API 将会把我们通过参数传递过去的文字返回。同时,此 API 还会作为 Picturesocial 所有 API 的模板来使用。这样从本地开发调试进展到云端部署时不再需要修改编排方案、脚本、依赖项,并且当应用的代码发生变化时,这些不相关项能保持一致性。这也是我们整个应用容器化的主要原因。
我们在 GitHub 上创建了一个仓库 https://github.com/aws-samples/picture-social-sample?trk=cndc-detail, 里面包含了完成接下来这些步骤需要用到的代码。在开始之前,请确保克隆后的分支切换到了 “ep1”。
git clone https://github.com/aws-samples/picture-social-sample --branch ep1
cd picture-social-sample/HelloWorld
RUN echo "Hello World"
docker build -t helloworld:latest .
docker buildx build —platform=linux/amd64 -t helloworld:latest .
现在,就可以在本地通过 docker run 命令启动容器了。使用 -d 选项能够让容器以后台服务形式运行,-p 选项可以将容器的端口与主机进行映射。此前在 Dockerfile 中我们制定了容器会使用 5111 端口,所以这里我们将同一个端口号进行映射执行。
docker run -d -p 5111:5111 helloworld:latest
aws ecr create-repository --repository-name helloworld
[aws account id].dkr.ecr.[aws region].amazonaws.com #for example for account id: 777777777777 on region: us-east-1 777777777777.dkr.ecr.us-east-1.amazonaws.com
aws ecr get-login-password --region us-east-1 \ | docker login --username AWS \ --password-stdin [aws account id].dkr.ecr.[aws region].amazonaws.com
docker tag helloworld:latest [aws account id].dkr.ecr.[aws region].amazonaws.com/helloworld:latest docker push [aws account id].dkr.ecr.[aws region].amazonaws.com/helloworld:latest
到了这里,说明已经成功了!恭喜成功容器化了自己的首个应用!
我们会持续更新这个系列内容,包括容器编排服务 (Container Orchestrator),是什么以及为什么我需要使用容器编排服务….
希望你开心工作,认真生活~
请持续关注 Build On Cloud 微信公众号,了解更多面向开发者的技术分享和云开发动态!
#Generative AI 新世界
#开发者生态
#亚马逊的开源文化
文章作者:
Ana Cunha、Jose Yapur,
Developer Advocate, Amazon Web Services
文章译者:
郑予彬
亚马逊云科技资深开发者布道师
文章来源:
https://dev.amazoncloud.cn/column/article/648c1546f3f2f7504c1f114b?sc_medium=regulartraffic&sc_campaign=crossplatform&sc_channel=CSDN