Docker Compose。调用自定义脚本

Docker Compose. Call a custom script

提问人:Unnamed 提问时间:5/31/2023 最后编辑:Unnamed 更新时间:6/3/2023 访问量:1044

问:

我有一个简单的定义,我想运行一个简单的/命令:docker-composecmdbash

basictests:
  image: ${DOCKER_REGISTRY-}mytests
  build:
    context: .
    dockerfile: MyTests/Dockerfile
  container_name: "mytestscontainer"
  command: 
    - echo "test"
  depends_on:
    dependent_env:
      condition: service_healthy 

注意:这是一个简化的测试。与其调用,我实际上想运行一些更复杂的脚本。echo

但是,当我运行此配置时,它会抛出以下错误:

 ==> /dev/null <==
 tail: cannot open 'echo "test"' for reading: No such file or directory

不知道从哪里来以及如何修复。看看这个,它应该可以工作。如果我删除,它可以正常工作。任何帮助都将得到赞赏。tailcommand

更新:DockerFile 除了安装和构建我的库外不做任何事情。dotnet

UPDATE2:基础 docker 文件为:

    FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
    WORKDIR /app
    EXPOSE 80
    EXPOSE 443

    FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
    WORKDIR /src
    # restore
    COPY ["MyTests/MyTests.csproj", "MyTests/"]
    RUN dotnet restore "MyTests/MyTests.csproj"
    # build
    COPY . .
    WORKDIR "/src/MyTests"
    RUN dotnet build "MyTests.csproj" -c Release -o /app/build

在上面的 docker 文件的末尾添加建议无济于事。 注意:我是 docker 和 docker-compose 的新手。ENTRYPOINT ["/bin/bash", "-c"]

UPDATE3: 添加到docketfile的末尾并更改我调用命令的方式,这无济于事。总的来说,我很好奇这是怎么回事?为什么会出现这种情况?ENTRYPOINT ["tail", "-f", "/dev/null"]command: [echo, test]tail

注意:对于上下文,我想配置适用于少数容器的集成测试,因此我想为我的集成测试运行,而不是echo ..dotnet test ..

UPDATE4:配置如下:

    FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
    WORKDIR /src
    EXPOSE 80
    EXPOSE 443
    # restore
    COPY ["MyTests/MyTests.csproj", "MyTests/"]
    RUN dotnet restore "MyTests/MyTests.csproj"
    # build
    COPY . .
    WORKDIR "/src/MyTests"
    RUN dotnet build "MyTests.csproj" -c Release -o /app/build

    ENTRYPOINT ["/bin/bash"]

如果我在本地从 cmd 运行它,效果很好:

    %SomePath%\Demo>docker build -f MyTests/Dockerfile  -t mytest .
    [+] Building 0.3s (12/12) FINISHED
     => [internal] load build definition from Dockerfile
     => => transferring dockerfile: 32B
     => [internal] load .dockerignore
     => => transferring context: 35B
     => [internal] load metadata for mcr.microsoft.com/dotnet/sdk:6.0
     => [1/7] FROM mcr.microsoft.com/dotnet/sdk:6.0
     => [internal] load build context
     => => transferring context: 2.00kB
     => CACHED [2/7] WORKDIR /src 
     => CACHED [3/7] COPY [MyTests/MyTests.csproj, MyTests/] 
     => CACHED [4/7] RUN dotnet restore "MyTests/MyTests.csproj"
     => CACHED [5/7] COPY . .
     => CACHED [6/7] WORKDIR /src/MyTests
     => CACHED [7/7] RUN dotnet build "MyTests.csproj" -c Release -o /app/build
     => exporting to image
     => => exporting layers
     => => writing image sha256:9c...
     => => naming to docker.io/library/mytest

    %SomePath%\Demo>docker run -it mytest
    root@999afef78716:/src/MyTests# ls
    MyTests.csproj  ApiTests.cs  Properties  obj

因此,看起来问题仅在于如何从 docker-compose 配置正确调用它。我还尝试设置以下选项

..
image: ${DOCKER_REGISTRY-}mytests
stdin_open: true # docker run -i
tty: true        # docker run -t
..

没有运气。

UPDATE5: 我试图用新的控制台应用程序简化我对这 2 个文件的所有逻辑:

Docker文件:

 FROM alpine:3.14
 WORKDIR "/src"
 CMD ["/bin/bash"]

 # same behavior if I use `CMD ["/bin/sh"]`

docker-compose:

version: '3.4'

services:
  consoleappdocker:
    image: ${DOCKER_REGISTRY-}consoleappdocker
    build:
      context: .
      dockerfile: ConsoleAppDocker/Dockerfile
    container_name: "consoleappdocker"
    command: ["/bin/bash", "-c", "echo test"]

仍然失败并出现错误,但是我刚刚注意到以下输出:tail: invalid number 'echo test'

 docker ps -a  --no-trunc
 CONTAINER ID    IMAGE                  COMMAND                                        CREATED         STATUS                     PORTS     NAMES
 %id%            consoleappdocker:dev   "tail -f /dev/null /bin/bash -c 'echo test'"   7 minutes ago   Exited (1) 7 minutes ago             consoleappdocker

所以看起来@VonC是对的,但是我不知道这部分最初是在哪里添加的tail

UPDATE6 : 显然,该部分是由我用来构建和运行应用程序的 Visual Studio 添加的,我在日志中找到了它:tail

    docker-compose  -f "%PATH%\docker-compose.yml" -f "%PATH%\docker-compose.override.yml" -f "%PATH%\obj\Docker\docker-compose.vs.debug.g.yml" -p dockercompose14997374556887134345 --ansi never --profile "*" config
    name: dockercompose14997374556887134345
    services:
      consoleappdocker:
        build:
          context: %PATH%
          dockerfile: ConsoleAppDocker/Dockerfile
          labels:
            com.microsoft.created-by: visual-studio
            com.microsoft.visual-studio.project-name: ConsoleAppDocker
        command:
        - /bin/bash
        - -c
        - echo test
        container_name: consoletest
        entrypoint:
        - tail
        - -f
        - /dev/null
        environment:
    ..
        image: consoleappdocker:dev
        labels:
    ..
        networks:
          default: null
        tty: true
        volumes:
    ..
    networks:
      default:
        name: dockercompose14997374556887134345_default
    docker-compose  -f "%PATH%\docker-compose.yml" -f "%PATH%\docker-compose.override.yml" -f "%PATH%\obj\Docker\docker-compose.vs.debug.g.yml" -p dockercompose14997374556887134345 --ansi never build

相当出乎意料的情况,但我认为下一步该怎么做或多或少是清楚的

bash docker-compose cmd tail

评论

0赞 Turing85 5/31/2023
什么是?有效的是设置和(假设我们使用;如果我们有 bash,我们可以代替)。ENTRYPOINTDockerfileENTRYPOINT ["/bin/sh", "-c"]CMD ["echo foo"]sh"/bin/bash"
0赞 larsks 5/31/2023
这个问题需要一个最小的可重复的例子。您至少需要更新问题,以显示要在其上构建自定义映像的基础映像。
1赞 David Maze 5/31/2023
错误消息建议类似“使容器保持活动状态”;我倾向于不认为这是最佳实践。在你的列表中,如果你有一个数组,你需要将单个单词放在单独的列表项中,;另请参阅 Docker compose executable file not found in $PATH“: unknownENTRYPOINT ["tail", "-f", "/dev/null"]command:command: [echo, test]
0赞 Unnamed 5/31/2023
这无济于事。如果我添加到 dockerfile 的末尾并更改我的 on .它仍然给出相同的错误。总的来说,这是怎么回事?为什么它会出现在错误中?ENTRYPOINT ["tail", "-f", "/dev/null"]commandcommand: [echo, test]tail
1赞 VonC 6/3/2023
@Unnamed 是的,我看到了,我已经相应地更新了答案,并提供了一些文档来说明这种行为。

答:

3赞 VonC 6/3/2023 #1

文件中的 command 指令用于覆盖 中指定的缺省值。
该指令等同于您将在 之后传递的命令。
docker-compose.ymlCMDDockerfilecommanddocker run <image> <command>

你看到一个错误,因为你的 Dockerfile 可能配置为运行一个命令,该命令涉及其执行结束时,并且当您覆盖文件中的命令时,该命令正在尝试读取一个名为 的文件,该文件不存在。tailtaildocker-compose.ymltailecho "test"

在本例中,您希望在容器内运行命令。应如下所示:docker-compose.yml

    basictests:
      image: ${DOCKER_REGISTRY-}mytests
      build:
        context: .
        dockerfile: MyTests/Dockerfile
      container_name: "mytestscontainer"
      command: ["/bin/bash", "-c", "echo test"]
      depends_on:
        dependent_env:
          condition: service_healthy 

这将在容器内执行命令。echo test

要运行复杂的命令或脚本,您可以:

  1. 在生成过程中将脚本添加到 Docker 映像,然后从指令调用脚本。command

  2. 在构建过程中将脚本添加到 Docker 映像中,然后从 或 中调用该脚本。CMDENTRYPOINTDockerfile

  3. 将包含脚本的卷挂载到容器中,然后从 中的指令调用脚本。commanddocker-compose.yml

对于有关运行集成测试的最后说明,可以将运行测试的脚本添加到 Docker 映像,然后在指令中调用该脚本。脚本可能如下所示:command

#!/bin/bash

# Run the tests
dotnet test MyTests/MyTests.csproj

然后在你的 :docker-compose.yml

    basictests:
      image: ${DOCKER_REGISTRY-}mytests
      build:
        context: .
        dockerfile: MyTests/Dockerfile
      container_name: "mytestscontainer"
      command: ["/bin/bash", "-c", "/path/to/your/script.sh"]
      depends_on:
        dependent_env:
          condition: service_healthy 

请将“”替换为 Docker 容器中脚本的实际路径。/path/to/your/script.sh

并确保脚本具有执行权限。您可以在 Docker 构建期间使用以下指令设置这些内容:RUN

COPY ./host/path/to/your/script.sh /path/to/your/script.sh
RUN chmod +x /path/to/your/script.sh

请将“”替换为主机上脚本的路径。./host/path/to/your/script.sh


这是一个很好的猜测,但不,我没有在任何地方配置/看到它

您提供的 Dockerfile 不显示涉及该命令的 or 指令。但是,您看到的错误消息表明该命令正在运行,并尝试将“echo ”test“作为文件打开,这表明该命令正在某处调用。CMDENTRYPOINTtailtailtail

也有可能作为基础映像或父映像的一部分运行,或者由容器中的某个进程运行。如果基础映像或父映像具有包含 的 或,并且您没有在 Dockerfile 中覆盖它,则可以解释为什么您会在错误消息中看到该命令。tailCMDENTRYPOINTtailtail

在 Dockerfile 中的一个常见用途是让容器无限期地运行,即使其主进程已终止(就像我在这里所做的那样)。这有时用于开发环境或需要保持运行但可能并不总是有进程要运行的服务。
如果以这种方式调用,则尝试将命令替换为其他内容(例如 )可能会导致您看到的错误消息。
tail -f /dev/nulltailtail -f /dev/nullecho "test"

若要确认这一点,可以检查基本映像或父映像,或者在 Dockerfile 或文件中运行的任何脚本或命令。docker-compose.yml


当我使用命令应用配置时,我看到此错误:,这仍然是关于......docker-composecommand: ["/bin/bash", "-c", "echo test"]tail: invalid number of bytes: 'echo test'tail

如果 在 Dockerfile 或基础映像中设置为命令,并且您正在使用 docker-compose 文件中的指令运行 ,则 Docker 将尝试将 附加到命令中。
在这种情况下,它会尝试执行类似 的东西,这不是一个有效的命令,会导致您看到的错误。
ENTRYPOINTtailcommandbash -c "echo test"commandENTRYPOINTtail bash -c "echo test"


您会在此处发现类似的“无效编号”错误,其中基础映像 alpine 没有 bash,并且内置命令没有所有更常见的选项。
BUSYBOX脚本是错误的”中的相同想法
"


显然,尾部部分是由我用来构建和运行应用程序的 Visual Studio 添加的,我在日志中找到了它:

docker-compose  -f "%PATH%\docker-compose.yml" -f "%PATH%\docker-compose.override.yml" -f "%PATH%\obj\Docker\docker-compose.vs.debug.g.yml" -p dockercompose14997374556887134345 --ansi never --profile "*" config
    name: dockercompose14997374556887134345
    services:
      consoleappdocker:
        build:
          context: %PATH%
          dockerfile: ConsoleAppDocker/Dockerfile
          labels:
            com.microsoft.created-by: visual-studio
            com.microsoft.visual-studio.project-name: ConsoleAppDocker
        command:
        - /bin/bash
        - -c
        - echo test
        container_name: consoletest
        entrypoint:
        - tail
        - -f
        - /dev/null
        environment:
    ..
        image: consoleappdocker:dev
        labels:
    ..
        networks:
          default: null
        tty: true
        volumes:
    ..
    networks:
      default:
        name: dockercompose14997374556887134345_default
    docker-compose  -f "%PATH%\docker-compose.yml" -f "%PATH%\docker-compose.override.yml" -f "%PATH%\obj\Docker\docker-compose.vs.debug.g.yml" -p dockercompose14997374556887134345 --ansi never build

您可以看到之前(VS 2019)此处提到的实践。
如“Docker 容器中的 Azure 函数在 Visual Studio 中运行,但不从命令行执行任何操作”中所述:

发布的命令仅用于 Visual Studios 调试功能。它用 tail -f /dev/null 覆盖入口点,这基本上是“永远循环”。

官方文档

入口点是 ,这是保持容器运行的无限等待。
当通过调试器启动应用时,调试器负责运行应用(即 )。
如果在未调试的情况下启动,则工具将运行 a 以运行应用。
tail -f /dev/nulldotnet webapp.dlldocker exec -i {containerId} dotnet webapp.dll

若要修改仅用于调试的容器,请创建一个阶段,然后使用 MSBuild 属性 DockerfileFastModeStage 告知 Visual Studio 在调试时使用自定义阶段。有关 Dockerfile 命令的信息,请参阅 Docker 文档中的 Dockerfile 参考

因此,请检查您的项目属性文件中是否有如下部分:

<PropertyGroup>
     <!-- other property settings -->
     <DockerfileFastModeStage>debug</DockerfileFastModeStage>
</PropertyGroup>

评论

0赞 Unnamed 6/3/2023
'可能配置为运行涉及尾巴的命令' - 这是一个很好的猜测,但不,我没有在任何地方配置/看到它。在UPDATE4中查看我的 docker 文件。
0赞 Unnamed 6/3/2023
当我使用命令应用配置时,我看到此错误:这仍然是关于..docker-composecommand: ["/bin/bash", "-c", "echo test"]tail: invalid number of bytes: 'echo test'tail
0赞 Unnamed 6/3/2023
如果它有效,我可以用这个问题创建一个小的重现
1赞 VonC 6/3/2023
@Unnamed我已经编辑了答案以解决您的意见。
0赞 Andres 9/21/2023
因此,阅读所有帖子和评论对我来说仍然不清楚在我的 docker-compose.yml 文件中放入什么,以启用使用 Visual Studio 运行脚本后容器启动和调试的方案。有什么帮助吗?