使用 Kool 在本地开发环境中同时运行多个 Docker 应用程序
我们越来越多地在微服务架构中使用 Docker 容器,这些架构包含多个松耦合的应用程序和服务,或者由两个或多个独立应用程序并行运行并通过 API 相互通信的项目。对于从事此类项目的开发人员来说,他们深知同时配置本地开发环境以运行多个Docker 应用程序可能非常麻烦。使用 Kool 和 Docker Compose单独开发每个应用程序轻而易举。但是,当需要同时运行多个应用程序时,配置不同容器之间的路由和通信就可能充满挑战。
在本教程中,我们将向您展示如何使用 Kool 和 Caddy Web 服务器设置本地环境,以便同时运行多个 Docker 应用程序。当然,这只是解决此用例的几种方法之一,但我们认为这种方法对大多数项目都非常有效。
要求
开始之前,如果您还没有安装 Docker 和Kool CLI,则需要先安装它们。此外,快速熟悉Kool CLI 命令也很有帮助。
koolKool CLI 是一款命令行工具,可让您轻松使用 Docker 进行本地开发。Kool CLI 将提升您的开发工作流程,并帮助您和您的团队改进云原生应用程序的开发和部署方式。请务必运行以下命令来确保始终使用最新版本kool self-update。
一切总是从简单开始。
您有一个应用程序及其 Docker Compose 环境。我们称之为应用程序 1。
$ mkdir -p ~/multiple-apps/app-1
$ cd ~/multiple-apps/app-1
创建我们需要的两个文件:
# App 1
# ~/multiple-apps/app-1/docker-compose.yml
services:
app:
image: kooldev/php:8.0-nginx
ports:
- 80:80
volumes:
- .:/app/public
# App 1
# ~/multiple-apps/app-1/index.php
<?php
echo "Welcome to App 1!\n";
有了这两个文件,现在就可以使用以下命令启动并运行应用程序 1kool start,并使用以下命令检查其服务容器的状态kool status:
$ kool start
Creating network "app-1_default" with the default driver
Creating app-1_app_1 ... done
$ kool status
+---------+---------+---------------------------------------------+---------------+
| SERVICE | RUNNING | PORTS | STATE |
+---------+---------+---------------------------------------------+---------------+
| app | Running | 0.0.0.0:80->80/tcp, :::80->80/tcp, 9000/tcp | Up 4 seconds |
+---------+---------+---------------------------------------------+---------------+
[done] Fetching services status
$ curl localhost
Welcome to App 1!
太棒了!您的app服务容器正在运行,kool status显示端口 80 已从您的主机映射到容器,并成功返回应用程序 1curl localhost的输出。
但接下来事情就变得棘手了。
随着项目的不断发展,您需要添加第二个应用程序,名为App 2 ,它与App 1并行运行。换句话说,要进行项目开发,您需要同时运行这两个应用程序。
让我们快速设置应用程序 2。
$ mkdir -p ~/multiple-apps/app-2
$ cd ~/multiple-apps/app-2
让我们再次创建所需的两个文件(在app-2目录内):
# App 2
# ~/multiple-apps/app-2/docker-compose.yml
services:
app:
image: kooldev/php:8.0-nginx
ports:
- 80:80
volumes:
- .:/app/public
# App 2
# ~/multiple-apps/app-2/index.php
<?php
echo "Welcome to App 2!\n";
这一次,当您尝试启动并运行应用程序 2(使用kool start)时,您遇到了一个问题。
$ kool start
Creating network "app-2_default" with the default driver
Creating app-2_app_1 ...
Creating app-2_app_1 ... error
ERROR: for app-2_app_1 Cannot start service app: driver failed programming external connectivity on endpoint app-2_app_1 (24719704f55491122a18f051d3f1e789b6afc3f34ccf7bfe3d7eac510117ef42):
Bind for 0.0.0.0:80 failed: port is already allocated
ERROR: for app Cannot start service app: driver failed programming external connectivity on endpoint app-2_app_1 (24719704f55491122a18f051d3f1e789b6afc3f34ccf7bfe3d7eac510117ef42):
Bind for 0.0.0.0:80 failed: port is already allocated
ERROR: Encountered errors while bringing up the project.
根据错误信息,您存在端口冲突(Bind for 0.0.0.0:80 failed: port is already allocated)。您的主机上不能有两个不同的容器绑定到同一个端口。
在继续之前,请先停止App 2和App 1容器:
$ cd ~/multiple-apps/app-2 # you should already be here
$ kool stop
$ cd ~/multiple-apps/app-1
$ kool stop
别那么快!
要解决这个问题,你首先想到的可能是为每个服务使用不同的端口。例如,你可以让应用 1运行在 1000 个端口上localhost:8081,应用 2运行在 2000 个端口上localhost:8082。然而,你很快就会意识到这种方案不可行,因为它不够灵活,无法在共享的 Docker 网络上实现应用程序之间的通信。
代理人前来救援
代理设计模式为在本地开发环境中同时运行多个 Docker 应用程序提供了一个更好的解决方案。
向 Docker Compose 添加全球网络
首先,你需要改进每个应用程序使用的 Docker Compose 环境。利用Kool Presets中包含的 Docker 配置中内置的众多最佳实践之一,让我们在 Docker 容器之间创建一个共享网络。
默认情况下,docker-compose.yml文件中的所有容器将共享同一个虚拟网络。这意味着两个不同的应用程序将无法建立通信通道。因此,Kool Presets 通常会为每个容器配置两个网络kool_local:` 1` 和 `2` kool_global。
kool_local这是一个本地网络,仅对docker-compose.yml文件中指定的容器组可用。它与默认网络相同(如果我们没有自己指定网络的话)。kool_global这是一个全局网络,它独立于任何特定的docker-compose.yml文件之外创建。它在整个系统范围内可用,主机上运行的任何容器都可以加入它。
让我们kool_global在每个 Docker Compose 环境中创建一个外部网络,并将每个应用程序添加到该网络中。
# App 1
# ~/multiple-apps/app-1/docker-compose.yml
services:
app:
image: kooldev/php:8.0-nginx
expose:
- 80
volumes:
- .:/app/public
networks:
kool_global:
aliases:
- app-1
networks:
kool_global:
external: true
# App 2
# ~/multiple-apps/app-2/docker-compose.yml
services:
app:
image: kooldev/php:8.0-nginx
expose:
- 80
volumes:
- .:/app/public
networks:
kool_global:
aliases:
- app-2
networks:
kool_global:
external: true
请注意,我们已将配置替换ports为。为了避免冲突,expose您不再希望这些容器绑定到主机。相反,您希望将单个容器绑定到主机,该容器通过其网络将每个请求内部代理到正确的服务容器。appkool_globalalias
aliases容器网络中的密钥就像域名一样,在同一网络内使用时会解析到该容器的地址。这是一种规范化需要相互通信的服务容器名称的绝佳方法。
设置代理
如前所述,我们将使用Caddy Web 服务器作为反向代理。这是我们的首选,因为它拥有简洁的配置界面和丰富的功能集。Traefik或Nginx 也非常适用,因此在实际项目中实施此方案时,您可以根据自己的喜好选择最合适的服务器。
我们先Caddyfile在新proxy目录中创建一个配置文件:
$ mkdir ~/multiple-apps/proxy
$ cd ~/multiple-apps/proxy
# ~/multiple-apps/proxy/Caddyfile
{
auto_https off
}
http://a.localhost {
reverse_proxy / http://app-1
}
http://b.localhost {
reverse_proxy / http://app-2
}
请注意,我们使用app-1容器网络别名来根据传入的请求(vs. )app-2指向每个目标。您还应该将这些本地域名添加到您的文件中:。Hosta.localhostb.localhost/etc/hostsecho "127.0.0.1 a.localhost b.localhost" | sudo tee -a /etc/hosts
默认情况下,Caddy 会尝试
HTTPS对所有主机使用 TLS。在本教程中,我们将禁用此功能。我们将在后续文章中介绍本地 TLS 的使用。
接下来,我们docker-compose.yml为 Caddy 本身创建一个新的:
# ~/multiple-apps/proxy/docker-compose.yml
services:
proxy:
image: caddy:2-alpine
ports:
- 80:80
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
networks:
- kool_global
networks:
kool_global:
external: true
好了,代理配置完成。
现在,您只需启动您的App 1、App 2和Proxy服务容器(kool start当然要使用 ),并通过发送几个测试请求来验证它是否有效。
# Proxy
$ cd ~/multiple-apps/proxy # you should already be here
$ kool start
Creating proxy_proxy_1 ... done
# App 1
$ cd ~/multiple-apps/app-1
$ kool start
# App 2
$ cd ~/multiple-apps/app-2
$ kool start
$ curl -H "Host: a.localhost" http://localhost
Welcome to App 1!
$ curl -H "Host: b.localhost" http://localhost
Welcome to App 2!
太棒了!现在两个应用程序可以同时运行了。您可以使用不同的主机名访问它们,它们之间也可以相互通信。
要清理本地环境,您需要进入每个目录(
app-1、、app-2和proxy),然后运行kool stop,并删除您创建的目录:rm -r ~/multiple-apps。
下一步
Kool 的核心团队已经在着手开发一套新的命令,以使上述步骤更加流畅透明,您无需担心任何细节。我们诚邀您参与讨论并贡献力量。
如果您喜欢我们正在做的事情,请在 GitHub 上给我们点赞以示支持!
支持 Kool 开源项目
Kool是开源软件,完全免费使用。如果您想了解更多关于该项目的信息,请访问kool.dev。如果您有任何疑问、需要支持或想参与其中,请加入我们的 Slack 频道。
文章来源:https://dev.to/kooldev/use-kool-to-run-multiple-docker-applications-at-the-same-time-in-your-local-development-environment-5ec6