Docker - 在docker映像构建期间无法访问网络中的其他容器

时间:2018-04-08 22:01:52

标签: docker tcp docker-compose dockerfile

我有两个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

2 个答案:

答案 0 :(得分:1)

我看到你的困惑。

RUN声明并没有按照您的想法行事;它在容器构建时运行wait-for-it.sh,并且不受docker-compose的控制。 当您的容器运行时它不会运行! 您应该查看docker关于container start-up orderdocker-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;旗帜工作)