前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在API网关和微服务开发中使用Docker

在API网关和微服务开发中使用Docker

作者头像
双愚
发布2018-06-20 11:18:19
2.8K0
发布2018-06-20 11:18:19
举报
文章被收录于专栏:重庆的技术分享区

原文作者:Everett Griffiths

原文地址:https://dzone.com/articles/using-docker-in-api-gateway-and-microservice-devel


随着您作为开发人员的教育进步,您迟早会了解像Docker这样的容器系统所带来的好处:您可以使用代码指定您的开发环境,而不必向系统工程师发送所有Slack消息或者遇到的麻烦站在一贯需要配置的服务器。同样,您可能已经理解了微服务作为解决单片应用程序自身债务缠身问题的解决方案的吸引力。

本文提供了一些关于如何在微服务的开发流程中利用Docker的见解。

Docker支持一个独立的微服务

开发微服务本身应该是相当直接的; 从环境的角度来看,开发一个微服务不应该像开发一个传统的应用程序那么不同。也许你的微服务需要支持一个或两个API端口 - 你需要它连接到几个数据模型,比如MySQL或Redis,并且你可以很快进入正轨。这是Docker 101的东西。您可以利用良好支持现有Docker项目,如LaradockNoDock(分别针对PHP和Node.js),它们为开发人员提供了一个集成的Docker环境,该环境支持通过docker-compose联网在一起的一系列常见技术。

快速迅速

我想告诉任何使用Docker的人的第一个提示是,它的开发速度非常快:即使是最近的课程也可能涉及到已经被弃用的命令或实用程序(例如docker-machine)。准备好咬紧牙关,然后浏览一些不熟悉的错误消息。然而,一旦你通过难关,在Docker俱乐部的会员资格是值得的。

Docker独立

当然,在我们开始之前,请确保您的计算机上有Docker工具箱。请参阅Docker.com为您的主机操作系统下载客户端(CE社区版本适用于我们的操作)。

如果您需要运行特定技术(如脚本语言或操作系统),那么很可能有人已经为其创建了Docker映像。DockerHub是您重复使用其他人如此慷慨分享的代码的朋友。记住:不要重复造轮子!请注意,出于某种原因,当您实际上搜索图像时,该网站会被标记为搜索容器。请记住:容器是模板 - 可以从单个图像模板创建多个容器实例。

简而言之,您在这里的交互应该围绕克隆容器(使用clone命令),然后运行它的一个实例(使用run命令)。例如,您只需要获取Postgres的工作副本即可:

代码语言:javascript
复制
docker pull postgres docker run --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword -d postgres

如果您查看任何容器的相应Git存储库,那么Dockerfile它包含从图像构建容器实例所需的步骤,例如,用于Postgres容器。

通常,Dockerfile中的第一条指令,使用命令FROM:这扩展了指定的容器,因此您可以从一开始就看到,对于作者来说,重用现有映像是一种巨大的激励。

Docker撰写

在很多情况下,您会发现将单独的Docker容器连接在一起很有用。如果您的应用程序需要特定版本的PHP和特定版本的Postgres,则没有任何问题:找到Docker镜像并在docker-compose.yml文件中引用它们。

对于许多使用案例来说,docker-compose将是将容器捆绑在一起的最重要的工具。对于每个微服务,您将能够引用新的和现有的Docker映像并通过您的docker-compose.yml文件定义它们的关系。

例如,下面是我们如何定义一个环境来在NGINX Web服务器上支持PHP 7和Postgres。假设我们的存储库根目录有一个名为的公用Web文件的文件夹public/和一个文件composer.json

代码语言:javascript
复制
# PHP + Postgres microservice docker-compose.yml version: '2' services: nginx: image: nginx:1.13-alpine ports: - 3000:80 volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf web: # This build command is what # builds the neighboring Dockerfile build: . ports: - 9000:9000 volumes: - .:/var/www - /var/www/vendor depends_on: - postgres environment: DATABASE_URL: postgres://todoapp@postgres/todos postgres: image: postgres:9.6.2-alpine environment: POSTGRES_USER: todoapp POSTGRES_DB: todos

其中大部分是端口和卷映射。那么PHP在哪里?build: .这个命令有点模糊。更详细地说,该命令运行docker build .,所以它期望在Dockerfile这个文件旁边有一个Dockerfiledocker-compose.yml。PHP Dockerfile可能看起来如下:

代码语言:javascript
复制
FROM php:7.1-fpm-alpine RUN apk update && apk add build-base RUN apk add postgresql postgresql-dev \ && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \ && docker-php-ext-install pdo pdo_pgsql pgsql RUN apk add zlib-dev git zip \ && docker-php-ext-install zip RUN curl -sS https://getcomposer.org/installer | php \ && mv composer.phar /usr/local/bin/ \ && ln -s /usr/local/bin/composer.phar /usr/local/bin/composer # References the virtual path COPY . /var/www WORKDIR /var/www RUN composer install --prefer-source --no-interaction ENV PATH="~/.composer/vendor/bin:./vendor/bin:${PATH}"

根据你的需求,你可能完全不需要Dockerfile。不是一个build命令,docker-compose.yml可能会引用一个image,但由于PHP是使用的服务器端语言,很可能它需要一些定制。这在Dockerfile最容易实现,因此通过build属性引用它可能是最好的方法。

你需要做的最后一件事是一个NGINX配置文件。像下面这行命令应该就足够了:

代码语言:javascript
复制
server { listen 80; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /var/www/public/; location / { try_files $uri /index.php$is_args$args; } location ~ ^/.+\.php(/|$) { fastcgi_pass web:9000; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } }

如果您正在关注在存储库根目录在容器内的对应位置上进行的映射,则可以看到按写入的方式,该文件位于存储库的根目录。docker-compose.yml/var/www/nginx.conf

你可能很容易被文件中的虚拟路径所迷惑,所以你必须将它与你的文件进行比较。具体而言,它将映射(存储库根目录)到虚拟机上。所以NGINX从这一点开始拿起并定义它的web根目录- 这是你的版本库中的文件夹。nginx.confdocker-compose.yml./var/www/var/www/public/public/

要下载这些图像并将它们构建到容器中,您可以运行。下载和构建图像可能需要一段时间,但如果一切顺利,您应该可以打开新的PHP应用程序docker-compose uphttp://localhost:3000

种子数据

在开发微服务时,您需要编写测试。当使用像Docker这样的技术,您可以很容易且一致地提供相关服务时,您应该认识到一个很好的机会,可以根据策划的种子数据集合进行集成测试和功能测试。

当您可以访问一个真实的数据库并得到真实的响应时,为什么仅仅依靠单元测试和模拟服务呢?尽管设置起来比较麻烦,但是集成测试的优点是它们测试更彻底全面——当然有时会有一些意外和细微的差别,而mock不能涵盖这些。

在这种情况下的测试运行将从重新启动您的容器开始,并使用您的策划种子数据加载它们。这确实需要比执行简单的单元测试更长的时间,但它不会比浏览器自动化或其他最终用户测试慢。

执行种子操作的最简单方法之一是使用docker-composeexec函数,该函数在指定的容器中执行命令。例如,如果我们的PHP应用程序是Laravel应用程序,那么我们可以利用其artisan命令行工具来迁移和生成我们的数据库。

代码语言:javascript
复制
docker-compose exec web php artisan migrate

无论您使用的是哪种语言,都应该有一种可行的方法来支持您的数据库迁移,并为您的集成测试使用一些可行的种子数据对数据库进行种子处理。

API网关的Docker

当你退一步,开始开发API网关本身时,或者如果你需要处理一个与多个数据源交互的更复杂的服务时,你最终可能会试图想出来您生态系统中所有相关应用程序的工作版本。

您的API网关应用程序的Docker镜像可能与我们针对单个微服务所讨论的内容并没有太大的不同。它需要一些环境来处理通过服务器端代码(可能是Go或Elixir)的请求和响应,并且它通常会附加到认证/授权服务,以便在将代理代理到微服务之前验证请求。

这可能就足够了:您可以在API Gateway内测试任何权限逻辑或错误处理方式,这与您在任何微服务应用程序中的方式几乎相同。如果您使用身份验证服务,您可以测试每条路线的适当权限。您还可以验证传入的请求是否代理了特定的服务,如果需要,您可以模拟响应。

但这并不代表端到端测试。如果我们想确定具体的请求能够产生特定的响应,我们将不得不做一些改进。这就是我们回到Docker和Docker Compose的地方。

如果我们将docker-compose.yml用作我们微服务的“记录文档”,您可以很容易想象它可能会列出大量服务(例如,每个微服务都有一个服务)。如果每个服务都构建为Docker镜像,那么您可以将这些镜像作为公共(或私人)存储库在Docker Hub上发布,以便其他开发人员可以轻松地克隆和构建应用程序所需的容器。

专用测试图像

解决播种数据和运行集成测试问题的一个解决方案是为该任务创建专用的Docker镜像。这个Docker映像可能会很好地利用您docker-compose.yml文件中的depends_on关键字。您用来编写测试的语言可以是最适合当前任务的语言:测试。只要您可以轻松地使用种子数据填充数据模型,编写使用HTTP请求访问API网关的测试,这就可以工作。

将这些测试放在相同的图像和代码库中作为API网关是完全可能的,但对于很多用例来说,将它们分开可能更有意义。最重要的是,对测试或种子数据的任何更改都不应要求升级和部署API网关本身。其次,API网关的语言可能不适合编写测试或使用种子数据填充模型。因此,为任务提供一个专用的映像应该有助于隔离更改并为任务提供最佳的工具。

这种安排有时可能需要更多的人力,但它确实促进了测试驱动开发和良好的测试覆盖,包括代码和服务,也包括环境本身。如果我们将每个微服务看作是应用程序“主体”中的某种处理“单元”,那么将集成测试和与之相关的种子数据与微服务分离开来就很有意义。

在某种程度上,这提供了网关和它的微服务之间的强契约。如果您更新服务或完全替换它,您的集成测试将为您提供更改兼容的可靠保证。

结论

这只触及到了联网、填充和测试相互连接的微服务可能遇到的复杂性的表面,里面的水还很深。本文概述的方法已经暗示了在某些场景中可能出现的一些缺点,因此您可能已经了解其他技术(如Kubernetes)可能对您有用。希望它为您提供了一些关于如何解决您自己的应用程序环境中的一些问题的想法。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Docker支持一个独立的微服务
    • 快速迅速
    • Docker独立
    • Docker撰写
    • 种子数据
    • API网关的Docker
    • 专用测试图像
    • 结论
    相关产品与服务
    容器镜像服务
    容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档