我有两个docker容器:简单的rest api和一个数据库。我想在数据库准备就绪时启动其余的api。当我发现问题出在网络中时,我尝试了几种解决方案。
当我在没有等待数据库的情况下启动rest api然后执行docker exec -it <api-container-name> bash
并从那里运行它时, wait-for-it.sh脚本完全正常。当我尝试在Dockerfile中将其作为CMD
运行时,它无法与数据库建立连接。当我在数据库已经运行时启动api时,会发生同样的事情。
Api dockerfile:
FROM microsoft/aspnetcore-build:2.0
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN chmod +x Scripts/wait-for-it.sh
RUN Scripts/wait-for-it.sh -t 30 172.20.1.2:3306 #times out when waiting for database
RUN dotnet publish -c Release -o out
ENTRYPOINT ["dotnet", "out/Atlanta.dll"]
搬运工-撰写:
version: '3'
networks:
backend:
driver: bridge
ipam:
config:
- subnet: 172.20.1.0/24
services:
main-db:
container_name: main-db
image: mysql
environment:
MYSQL_DATABASE: Main
MYSQL_ROOT_PASSWORD: root
ports:
- "5000:3306"
networks:
backend:
ipv4_address: 172.20.1.2
atlanta-ms:
container_name: atlanta
build:
context: ./Atlanta
dockerfile: Dockerfile
image: atlanta:ms
ports:
- "5001:80"
networks:
backend:
ipv4_address: 172.20.1.3
答案 0 :(得分:1)
我看到你的困惑。
RUN
声明并没有按照您的想法行事;它在容器构建时运行wait-for-it.sh
,并且不受docker-compose的控制。 当您的容器运行时它不会运行! 您应该查看docker关于container start-up order和docker-compose
的文档。
数据库的分离模式对构建/运行过程没有影响;期望你无法与之互动。
默认情况下,使用docker-compose会使所有容器处于非交互模式;但这很好,因为you can still attach/detach to the containers。
您应该向depends-on
添加docker-compose.yml
选项,并将wait-for-it.sh
添加到command
中的docker-compose.yml
选项,而不是Dockerfile
}。
version: '3'
networks:
backend:
driver: bridge
ipam:
config:
- subnet: 172.20.1.0/24
services:
main-db:
container_name: main-db
image: mysql
environment:
MYSQL_DATABASE: Main
MYSQL_ROOT_PASSWORD: root
ports:
- "5000:3306"
networks:
backend:
ipv4_address: 172.20.1.2
atlanta-ms:
container_name: atlanta
build:
context: ./Atlanta
dockerfile: Dockerfile
# Add this `depends-on`
depends-on:
- "main-db"
# Add this `command` option
command: ["Scripts/wait-for-it.sh", "-t", "30", "172.20.1.2:3306"]
image: atlanta:ms
ports:
- "5001:80"
networks:
backend:
ipv4_address: 172.20.1.3
我建议将wait-for-it.sh
移至WORKDIR
,并确保将其"./wait-for-it.sh"
传递给command
,以使您的生活更轻松。
不要忘记从RUN Scripts/wait-for-it.sh -t 30 172.20.1.2:3306
删除 Dockerfile
! (因为docker-compose
现在正在处理它。)
请记住,使用docker-compose
的命令是docker-compose up
,除非您希望改为使用docker swarm
。
答案 1 :(得分:0)
好。我设法解决了我的问题。我猜这不是一个干净的方式,但它现在有效。
我先建立并运行两个容器。然后,当api和db都启动时,我使用docker exec
远程执行迁移命令。
wait-for-it
脚本。
run.sh
#!/bin/bash
docker-compose up -d --build atlanta-ms main-db
docker exec atlanta bash -c "dotnet ef migrations add InitialMigration && dotnet ef database update"
rest api Dockerfile
FROM microsoft/aspnetcore-build:2.0
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out
ENTRYPOINT ["dotnet", "out/Atlanta.dll"]
搬运工-compose.yml
version: '3'
networks:
backend:
driver: bridge
ipam:
config:
- subnet: 172.20.1.0/24
services:
main-db:
container_name: main-db
image: mysql
environment:
MYSQL_ROOT_PASSWORD: root
ports:
- "5000:3306"
networks:
backend:
ipv4_address: 172.20.1.2
atlanta-ms:
container_name: atlanta
build:
context: ./Atlanta
dockerfile: Dockerfile
image: atlanta:ms
ports:
- "5001:80"
networks:
backend:
ipv4_address: 172.20.1.3
这个解决方案的缺点是rest api在分离模式下运行,所以我不能仅仅通过在控制台中执行ctrl + c
来阻止它。在docker attach atlanta
脚本末尾添加run.sh
行有效(我可以通过简单的ctrl + c
停止容器),但它不适用于多个容器(不能连接到多个容器)容器)因此我必须编写简单的停止脚本并从run.sh
独立调用它来停止容器,这有点不方便。
如果有人能告诉我如何附加到几个容器,我将非常感激,所以我可以用ctrl + c
来阻止它们(这就是docker-compose up service1 service2 service3
没有&#34; -d&#的方式34;旗帜工作)