我正在尝试使用docker swarm创建位于Haproxy之后的简单nodejs服务并连接到mysql。因此,我创建了这个docker compose文件:
我有几个问题:
version: '3'
services:
db:
image: test_db:01
ports:
- 3306
networks:
- db
test:
image: test-back:01
ports:
- 3000
environment:
- SERVICE_PORTS=3000
- DATABASE_HOST=localhost
- NODE_ENV=development
deploy:
replicas: 1
update_config:
parallelism: 1
delay: 5s
restart_policy:
condition: on-failure
max_attempts: 3
window: 60s
networks:
- web
- db
depends_on:
- db
extra_hosts:
- db:10.0.1.4
proxy:
image: dockercloud/haproxy
depends_on:
- test
environment:
- BALANCE=leastconn
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- 80:80
networks:
- web
deploy:
placement:
constraints: [node.role == manager]
networks:
web:
driver: overlay
db:
driver: bridge
我正在运行以下内容:
docker stack deploy --compose-file=docker-compose.yml prod
所有服务都在运行。
curl http://localhost/api/test <-- Not working
但是,正如我上面提到的,我遇到的问题。
Docker version 18.03.1-ce, build 9ee9f40
docker-compose version 1.18.0, build 8dd22a9
我想念什么?
答案 0 :(得分:0)
后端服务无法使用localhost或127.0.0.1连接到数据库,因此,我设法使用数据库容器的私有ip(10.0.1.4)连接到数据库。
请勿使用IP地址进行连接。仅使用DNS名称。
因此,您必须将连接更改为l <- list(`20014409-EA` = list(WEEK = structure(c(NA, 17448, 17455, 17462, 17469, 17476, 17483, 17490, 17497, 17504, 17511, 17518, 17546, 17553, 17560, 17567, 17574, 17581, 17588, 17595, 17602, 17609, 17616, 17623, 17630, 17637, 17644, 17651, 17658, 17665, 17672, 17679, 17686, 17693), class = "Date"), INTpercent = c(NA, 0, 0, 0, 0, 0, 0, 0, 0, -42.809364548495, 0, 0, 29.9765807962529, 0, 0, -42.809364548495, 0, 0, 0, 29.9765807962529, 2.28832951945081, 0, 0, 0, 2.34192037470727, 0, 0, 0, 0, 0, 0, 0, 0, 0), EXTpercent = c(NA, 0, -0.510204081632654, 0.50761421319797, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), `20015041-EA` = list(WEEK = structure(c(NA, 17448, 17455, 17462, 17469, 17476, 17483, 17490, 17497, 17504, 17511, 17518, 17546, 17553, 17560, 17567, 17574, 17581, 17588, 17595, 17602, 17609, 17616, 17623, 17630, 17637, 17644, 17651, 17658, 17665, 17672, 17679, 17686, 17693), class = "Date"), INTpercent = c(NA, 30.4609218436874, 0, 0, -0.402414486921538, 0, 0, 0, 0, 0, 0, 0, -24.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19.5171026156942, 0, 0, 0, 0, -24.25, 0, 0, 0, 19.5171026156942, 0), EXTpercent = c(NA, 0, 0, 0, 0, 0, -0.404858299595133, 0.403225806451604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -42.9394812680115, 0, 0, 30.0403225806452, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), `20016844-EA` = list(WEEK = structure(c(NA, 17448, 17455, 17462, 17469, 17476, 17483, 17490, 17497, 17504, 17511, 17518, 17546, 17553, 17560, 17567, 17574, 17581, 17588, 17595, 17602, 17609, 17616, 17623, 17630, 17637, 17644, 17651, 17658, 17665, 17672, 17679, 17686, 17693), class = "Date"), INTpercent = c(NA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.78468899521531,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), EXTpercent = c(NA, 0, -19.9195171026157, 16.3299663299663, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.507614213197974, 0.505050505050509, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), `20044140-EA` = list(WEEK = structure(c(NA, 17448, 17455, 17462, 17469, 17476, 17483, 17490, 17497, 17504, 17511, 17518, 17546, 17553, 17560, 17567, 17574, 17581, 17588,
17595, 17602, 17609, 17616, 17623, 17630, 17637, 17644, 17651, 17658, 17665, 17672, 17679, 17686, 17693), class = "Date"), INTpercent = c(NA, 0, 0, 0, 0, 0, 0, 0, 0, -59.5317725752508, 0, 0, -59.0425531914894, 0, 60.5870020964361, 0, 0, 0, 0, 0, 2.05338809034909, 0, -151.030927835052, 60.1642710472279, 0, 0, 0, 0, -143.5, 0, 58.9322381930185, -63.973063973064, 0, 0), EXTpercent = c(NA, 0, -17.632241813602, 14.9892933618844, 0, 0, -137.055837563452, 0, 57.8158458244111, -137.055837563452, 57.8158458244111, 0, 0, 0, 0, 0, 0, -91.3934426229508, 0, 47.7516059957173, 0, 0, -89.0688259109312, 0, 47.1092077087794, 0, 0, 0, 0, -153.804347826087, 60.5995717344754, 0, 0, 0)), `20067427-EA` = list(WEEK = structure(c(NA, 17448, 17455, 17462, 17469, 17476, 17483, 17490, 17497, 17504, 17511, 17518, 17546, 17553, 17560, 17567, 17574, 17581, 17588, 17595, 17602, 17609, 17616, 17623, 17630, 17637, 17644, 17651, 17658, 17665, 17672, 17679, 17686, 17693), class = "Date"), INTpercent = c(NA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34.3544857768053, 0, 0, 0, 2.14132762312633, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -23.8726790450928, 19.271948608137, -57.2390572390572), EXTpercent = c(NA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -87.7049180327869, 17.8451178451179, 0, -21.7213114754098, 0, 46.4912280701754, 0, 0, 0, -58.3333333333333, 0, 0, 0, 0, 0, 0, 4)), `20071339-EA` = list(WEEK = structure(c(NA, 17448, 17455, 17462, 17469, 17476, 17483, 17490, 17497, 17504, 17511, 17518, 17546, 17553, 17560, 17567, 17574, 17581, 17588, 17595, 17602, 17609, 17616, 17623, 17630, 17637, 17644, 17651, 17658, 17665, 17672, 17679, 17686, 17693), class = "Date"), INTpercent = c(NA, 0, 25.5639097744361, 0, 0, 0, 0, -61.5384615384615, 0, 0, 0, 0, 0, 38.0952380952381, -34.3434343434343, 0, -3.48432055749129, 0, 28.0701754385965, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -99.5, 49.874686716792, -34.3434343434343, 25.5639097744361, 0), EXTpercent = c(NA, 10.1010101010101, 0, 25.3768844221105, 0, -40.1408450704225, 0, 0, 0, 0, 28.643216080402, 0, -61.1336032388664, 14.2361111111111, -16.5991902834008, 14.2361111111111, 0, 0, 27.6381909547739, -34.006734006734, -11.2359550561798, 32.9145728643216, 0, -38.1944444444444, 0, 27.6381909547739, 0, 0, 0, 0, 0, -38.1944444444444, 0, 0)))
,因为这是您定义的服务名称。
Localhost是错误的,因为该服务与DATABASE_HOST=db
服务在不同的容器中运行。
即使后端依赖数据库,后端也会尝试过早连接到数据库。
test
不能按预期工作。请阅读https://docs.docker.com/compose/compose-file/#depends_on和信息框depends_on
TL; DR:在群集模式下使用版本3 Compose文件部署堆栈时,将忽略"There are several things to be aware of when using depends_on:"
选项。
无法从外部访问该应用程序。
当某人在depends_on
上请求haproxy时,必须为http://test:3000
请求的haproxy配置在哪里?
答案 1 :(得分:0)
对于DATABASE_HOST=localhost
-localhost
表示我的本地容器。您需要使用托管db的服务名称。 localhost
是一个特殊的DNS名称,始终指向应用程序主机。使用容器时-将是容器。在云开发中,您需要忘记使用localhost(将指向容器)或IP(每次运行容器时它们可能会更改,并且您将无法使用负载平衡)或IP,而只需使用服务名称。 / p>
关于准备情况-docker无法知道您在容器中启动的应用程序是否准备就绪。您需要使服务意识到数据库的不可用性,并让代码/脚本具有一些轮询/容错机制。
答案 2 :(得分:0)
马库斯是正确的,所以请听从他的建议。
这是一个组成/堆栈文件,假设您的应用在容器中的端口3000上侦听并且使用正确的密码,数据库等设置了db,该文件应该可以工作(您通常根据Docker将这些设置为compose中的环境变量)集线器自述文件)。
您的应用应设计为在无法正常使用数据库的情况下崩溃/重新启动/等待。这就是所有分布式计算的本质……任何“远程”(另一个容器,主机等)都不能被假定为始终可用。如果您的应用程序崩溃了,那么这对Docker来说是正常的过程,它将每次都重新创建Swarm Service任务。
如果您可以尝试使用公共Docker Hub映像进行此操作,那么我可以尝试为您进行测试。
请注意,在Swarm中,使用Traefik作为代理(Traefik on Swarm Mode Guide)可能会更容易,该代理将根据您给标签提供的主机名自动更新传入的请求并将其路由到正确的容器...但是注意您应该首先仅测试应用程序和数据库,然后在知道它们可行之后,尝试添加代理层。
此外,在Swarm中,您的所有网络都应该重叠,并且您无需指定,因为这是堆栈中的默认设置。
以下是使用traefik进行上述设置的示例。我没有给test
服务指定特定的traefik主机名,因此它应该接受所有来自80并进入测试服务3000的流量。
version: '3'
services:
db:
image: test_db:01
networks:
- db
test:
image: test-back:01
environment:
- SERVICE_PORTS=3000
- DATABASE_HOST=db
- NODE_ENV=development
networks:
- web
- db
deploy:
labels:
- traefik.port=3000
- traefik.docker.network=web
proxy:
image: traefik
networks:
- web
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- "80:80"
- "8080:8080" # traefik dashboard
command:
- --docker
- --docker.swarmMode
- --docker.domain=traefik
- --docker.watch
- --api
deploy:
placement:
constraints: [node.role == manager]
networks:
web:
db: