当没有OOM异常时,Docker-compose的退出代码为137。

86
当我运行以下命令时,我希望退出代码为0,因为我的combined容器运行一个成功退出并返回退出代码为0的测试。
docker-compose up --build --exit-code-from combined

不幸的是,即使在我的combined容器中成功运行测试并以退出代码0退出该容器,我仍然会持续收到退出代码137(有关如何发生的更多详细信息在下面指定)。

以下是我的docker-compose版本:

docker-compose version 1.25.0, build 0a186604

根据这篇文章,退出代码137可能由两个主要问题引起。
1.容器收到docker stop,但应用程序没有优雅地处理SIGTERM。 2.容器已经耗尽了内存(OOM)。 我知道137退出代码不是因为我的容器已经耗尽了内存。当我运行docker inspect <container-id>时,我可以看到“OOMKilled”为false,如下面的片段所示。我还为Docker Engine分配了6GB的内存,这对于我的应用程序来说足够了。
[
    {
        "Id": "db4a48c8e4bab69edff479b59d7697362762a8083db2b2088c58945fcb005625",
        "Created": "2019-12-12T01:43:16.9813461Z",
        "Path": "/scripts/init.sh",
        "Args": [],
        "State": {
            "Status": "exited",
            "Running": false,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false, <---- shows container did not run out of memory
            "Dead": false,
            "Pid": 0,
            "ExitCode": 137,
            "Error": "",
            "StartedAt": "2019-12-12T01:44:01.346592Z",
            "FinishedAt": "2019-12-12T01:44:11.5407553Z"
        },

我的容器没有从docker stop退出,所以我认为第一个原因与我的情况无关。

我的Docker容器设置方式

我有两个Docker容器:

  1. b-db - 包含我的数据库
  2. b-combined - 包含我的Web应用程序和一系列测试,在容器启动后运行。

我使用docker-compose.yml文件启动这两个容器。

version: '3'
services:
    db:
        build:
            context: .
            dockerfile: ./docker/db/Dockerfile
        container_name: b-db
        restart: unless-stopped
        volumes:     
            - dbdata:/data/db
        ports:
            - "27017:27017"
        networks:
            - app-network

    combined:
        build:
            context: .
            dockerfile: ./docker/combined/Dockerfile
        container_name: b-combined
        restart: unless-stopped
        env_file: .env
        ports:
            - "5000:5000"
            - "8080:8080"
        networks:
            - app-network
        depends_on:
            - db

networks:
    app-network:
        driver: bridge

volumes:
    dbdata:
    node_modules:

以下是docker-compose.ymlcombined服务的Dockerfile。
FROM cypress/included:3.4.1

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 5000

RUN npm install -g history-server nodemon

RUN npm run build-test

EXPOSE 8080

COPY ./docker/combined/init.sh /scripts/init.sh

RUN ["chmod", "+x", "/scripts/init.sh"]

ENTRYPOINT [ "/scripts/init.sh" ]

以下是我的init.sh文件的内容。

#!/bin/bash
# Start front end server
history-server dist -p 8080 &
front_pid=$!

# Start back end server that interacts with DB
nodemon -L server &
back_pid=$!

# Run tests
NODE_ENV=test $(npm bin)/cypress run --config video=false --browser chrome

# Error code of the test
test_exit_code=$?

echo "TEST ENDED WITH EXIT CODE OF: $test_exit_code"

# End front and backend server
kill -9 $front_pid
kill -9 $back_pid

# Exit with the error code of the test
echo "EXITING SCRIPT WITH EXIT CODE OF: $test_exit_code"
exit "$test_exit_code"

以下是我的db服务的Dockerfile。它所做的就是将一些本地数据复制到Docker容器中,然后使用这些数据初始化数据库。

FROM  mongo:3.6.14-xenial

COPY ./dump/ /tmp/dump/

COPY mongo_restore.sh /docker-entrypoint-initdb.d/

RUN chmod 777 /docker-entrypoint-initdb.d/mongo_restore.sh

以下是在mongo_restore.sh文件中的内容。
#!/bin/bash
# Creates db using copied data
mongorestore /tmp/dump

当我运行docker-compose up --build --exit-code-from combined; echo $?时,以下是输出的最后几行。
...
b-combined | user disconnected
b-combined | Mongoose disconnected
b-combined | Mongoose disconnected through Heroku app shutdown
b-combined | TEST ENDED WITH EXIT CODE OF: 0 ===========================
b-combined | EXITING SCRIPT WITH EXIT CODE OF: 0 =====================================
Aborting on container exit...
Stopping b-combined   ... done
137

如你所见,令人困惑的是,由于所有测试都成功通过,测试和脚本以退出码0结束,但容器仍以137的退出码退出。

更加令人困惑的是,当我从我的init.sh文件中注释掉以下代码行(运行Cypress集成测试),容器以0的退出码退出,如下所示。

NODE_ENV=test $(npm bin)/cypress run --config video=false --browser chrome

当我注释掉/删除init.sh文件中的上述行时,下面是我收到的输出结果,该命令运行我的Cypress集成测试。
...
b-combined | TEST ENDED WITH EXIT CODE OF: 0 ===========================
b-combined | EXITING SCRIPT WITH EXIT CODE OF: 0 =====================================
Aborting on container exit...
Stopping b-combined   ... done
0

如何让docker-compose在测试成功时返回零退出代码,在测试失败时返回非零退出代码?

编辑:

在调试模式下运行以下docker-compose命令后,我注意到b-db似乎有些关闭困难,可能是因为收到了Docker的SIGKILL信号。

docker-compose --log-level DEBUG up --build --exit-code-from combined; echo $?

根据以下输出结果,这是否确实是情况?

...
b-combined exited with code 0
Aborting on container exit...
http://localhost:None "GET /v1.25/containers/196f3e622847b4c4c82d8d761f9f19155561be961eecfe874bbb04def5b7c9e5/json HTTP/1.1" 200 None
http://localhost:None "GET /v1.25/containers/json?limit=-1&all=1&size=0&trunc_cmd=0&filters=%7B%22label%22%3A+%5B%22com.docker.compose.project%3Db-property%22%2C+%22com.docker.compose.oneoff%3DFalse%22%5D%7D HTTP/1.1" 200 3819
http://localhost:None "GET /v1.25/containers/196f3e622847b4c4c82d8d761f9f19155561be961eecfe874bbb04def5b7c9e5/json HTTP/1.1" 200 None
http://localhost:None "GET /v1.25/containers/0626d6bf49e5236440c82de4e969f31f4f86280d6f8f555f05b157fa53bae9b8/json HTTP/1.1" 200 None
http://localhost:None "GET /v1.25/containers/196f3e622847b4c4c82d8d761f9f19155561be961eecfe874bbb04def5b7c9e5/json HTTP/1.1" 200 None
http://localhost:None "GET /v1.25/containers/json?limit=-1&all=0&size=0&trunc_cmd=0&filters=%7B%22label%22%3A+%5B%22com.docker.compose.project%3Db-property%22%2C+%22com.docker.compose.oneoff%3DFalse%22%5D%7D HTTP/1.1" 200 4039
http://localhost:None "POST /v1.25/containers/196f3e622847b4c4c82d8d761f9f19155561be961eecfe874bbb04def5b7c9e5/attach?logs=0&stdout=1&stderr=1&stream=1 HTTP/1.1" 101 0
http://localhost:None "GET /v1.25/containers/196f3e622847b4c4c82d8d761f9f19155561be961eecfe874bbb04def5b7c9e5/json HTTP/1.1" 200 None
http://localhost:None "GET /v1.25/containers/196f3e622847b4c4c82d8d761f9f19155561be961eecfe874bbb04def5b7c9e5/json HTTP/1.1" 200 None
http://localhost:None "GET /v1.25/containers/0626d6bf49e5236440c82de4e969f31f4f86280d6f8f555f05b157fa53bae9b8/json HTTP/1.1" 200 None
Stopping b-combined   ...
Stopping b-db         ...
Pending: {<Container: b-db (0626d6)>, <Container: b-combined (196f3e)>}
Starting producer thread for <Container: b-combined (196f3e)>
http://localhost:None "GET /v1.25/containers/196f3e622847b4c4c82d8d761f9f19155561be961eecfe874bbb04def5b7c9e5/json HTTP/1.1" 200 None
http://localhost:None "GET /v1.25/containers/196f3e622847b4c4c82d8d761f9f19155561be961eecfe874bbb04def5b7c9e5/json HTTP/1.1" 200 None
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
http://localhost:None "GET /v1.25/containers/196f3e622847b4c4c82d8d761f9f19155561be961eecfe874bbb04def5b7c9e5/json HTTP/1.1" 200 None
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
Pending: {<Container: b-db (0626d6)>}
http://localhost:None "POST /v1.25/containers/196f3e622847b4c4c82d8d761f9f19155561be961eecfe874bbb04def5b7c9e5/wait HTTP/1.1" 200 32
http://localhost:None "POST /v1.25/containers/196f3e622847b4c4c82d8d761f9f19155561be961eecfe874bbb04def5b7c9e5/stop?t=10 HTTP/1.1" 204 0
http://localhost:None "GET /v1.25/containers/196f3e622847b4c4c82d8d761f9f19155561be961eecfe874bbb04def5b7c9e5/json HTTP/1.1" 200 None
http://localhost:None "POST /v1.25/containers/196f3e622847b4c4c82d8d761f9f19155561bStopping b-combined   ... done
Finished processing: <Container: b-combined (196f3e)>
Pending: {<Container: b-db (0626d6)>}
Starting producer thread for <Container: b-db (0626d6)>
http://localhost:None "GET /v1.25/containers/196f3e622847b4c4c82d8d761f9f19155561be961eecfe874bbb04def5b7c9e5/json HTTP/1.1" 200 None
http://localhost:None "GET /v1.25/containers/0626d6bf49e5236440c82de4e969f31f4f86280d6f8f555f05b157fa53bae9b8/json HTTP/1.1" 200 None
Pending: set()
Pending: set()
Pending: set()
Pending: set()
Pending: set()
Pending: set()
http://localhost:None "GET /v1.25/containers/0626d6bf49e5236440c82de4e969f31f4f86280d6f8f555f05b157fa53bae9b8/json HTTP/1.1" 200 None
http://localhost:None "POST /v1.25/containers/0626d6bf49e5236440c82de4e969f31f4f86280d6f8f555f05b157fa53bae9b8/stop?t=10 HTTP/1.1" 204 0
http://localhost:None "POST /v1.25/containers/0626d6bf49e5236440c82de4e969f31f4f86280d6f8f555f05b157fa53bae9b8/wait HTTP/1.1" 200 30
Stopping b-db         ... done
Pending: set()
http://localhost:None "GET /v1.25/containers/0626d6bf49e5236440c82de4e969f31f4f86280d6f8f555f05b157fa53bae9b8/json HTTP/1.1" 200 None
http://localhost:None "GET /v1.25/containers/196f3e622847b4c4c82d8d761f9f19155561be961eecfe874bbb04def5b7c9e5/json HTTP/1.1" 200 None
137
9个回答

86

Docker退出码137可能意味着Docker没有足够的RAM来完成工作。

不幸的是,Docker消耗大量RAM。

前往Docker桌面应用程序>首选项>资源>高级设置,并增加内存-最好将其加倍。


8
然而,退出码137并不总是指示OOM问题。例如,在我的情况下,我处理的是退出码137,但具体细节如下: "State":"Status":"exited","Running": false,"Paused": false,"Restarting": false,"OOMKilled": false,"Dead": false, "Pid": 0,"ExitCode": 137,"Error": "linux runtime spec devices: error gathering device information while adding custom device \"/dev/ttyUSB0\": no such file or directory"。 - Benyamin Jafari
3
这个答案虽然与问题无关,但对我很有帮助。截至本文撰写时,该问题包括:"""我知道 137 退出代码不是因为我的容器已经用完了内存。当我运行 docker inspect <container-id> 时,我可以看到“OOMKilled”是 false,如下面的代码片段所示。此外,我还将 6GB 内存分配给 Docker 引擎,这对于我的应用程序来说足够了。""" - David Winiecki
3
docker inspect 输出的重要部分是 "OOMKilled": false"ExitCode": 137。如果 OOMKilledfalse,那么内存限制不是导致退出码 137 的原因。 - David Winiecki
2
感谢@DavidWiniecki - 我不知道137错误可能有除OOM外的其他原因。在您的情况下 - 如果OOMKilled为false,那么137错误的原因是什么? - codeepic
1
在我的情况下,我有一个容器,在超时时间结束之前永远不会退出(它的Dockerfile具有CMD python3 -c 'input()'),因此docker inspect在杀死容器后始终报告“ExitCode:137”。OP的问题与此答案中所见的类似。(尽管这对我没有造成任何痛苦。实际上,我遇到了一个不同容器的OOM问题,这就是为什么这个答案对我有帮助,即使它与OP的问题并不完全相关。) - David Winiecki

20
错误信息是:Aborting on container exit... 来自docker-compose 文档--abort-on-container-exit 当任何容器被停止时停止所有容器。
你是否在运行 docker-compose 命令时使用了这个标志?如果是这样,请思考一下它的含义。
一旦 b-combined 完成,它就会直接退出。这意味着,容器b-db将被强制停止。即使 b-combined 返回退出代码为0,b-db 强制关闭可能不会被mongodb优雅地处理。
编辑:我刚刚意识到你在命令行中使用了 --exit-code-from。这意味着使用了 --abort-on-container-exit解决方案:让 b-db 有足够的时间来正常退出。使用 docker-compose up --timeout 600 来避免错误。

2
是的,因为我正在使用 --exit-code-from,它意味着 --abort-on-container-exit - 文档在这里(https://docs.docker.com/compose/reference/up/)。 - ptk
我进行的调试工作之一是单独启动 b-db,然后在该容器上运行 docker stop 命令,该容器以 0 的退出代码退出,这使我相信 b-db 不是问题所在。此外,如果我注释掉 NODE_ENV=test $(npm bin)/cypress run --config video=false --browser chrome 并在 init.sh 的最后一行中使用 exit 12,那么我收到的退出代码就是 12... - ptk
1
好的,这里有一个更简单但类似的compose。服务b依赖于服务a。使用相同的命令行运行,注意到有一个消息为容器a停止Stopping tmp_a_1 ... done。你的例子没有显示出来。Docker允许默认的10秒优雅停止期间。可能是因为mongodb在那段时间内没有优雅地停止吗?尝试使用docker-compose up --timeout 600 - JulioHM
关于超时问题,您是100%正确的。问题在于b-db没有在默认宽限期内退出,并且使用--timeout 600选项完全解决了该问题。谢谢 :) - ptk

15

可能是内存问题,我已经使用Docker首选项增加了内存。使用 docker-compose up 启动我的服务。服务器对我来说没有任何问题。

https://www.petefreitag.com/item/848.cfm


1
这对我来说是个问题,将内存从2GB增加到4GB。 - Sibish

3

我在设置Python代码时遇到了类似的问题。这个错误是由于内存分配引起的。在我的情况下,内存分配为2 GB。我把它改成了4 GB,就解决了问题。对于Mac用户,打开屏幕顶部工具栏上的Docker图标 -> 首选项 -> 资源 -> 内存。


0

我分配了足够的RAM,但在Mac M1上,docker compose并没有告诉我真实的情况(即使使用了--verbose)。 但是当我使用docker run运行时,我收到了以下输出:

WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Killed

这对我来说是个问题——需要注意图像架构。


对我来说也一样 - 我之前在终端设置中玩过,因为之前遇到过 Rosetta 的问题,所以我禁用了“使用 Rosetta 打开”的选项。启用它解决了问题。 - Jordan

0

如果您为Docker共享了足够的内存,并且它之前可以正常工作,请尝试使用

docker system prune

0

不确定这是否能解决您的问题,但您可以尝试在组合的Dockerfile中添加FROM scratch

Docker按顺序运行Dockerfile中的指令。 Dockerfile必须以FROM指令开头。 FROM指令指定了您正在构建的基础映像。 FROM只能由一个或多个ARG指令前置,这些指令声明在Dockerfile中的FROM行中使用的参数。 参考:https://docs.docker.com/v17.09/engine/reference/builder/#format

此外,不要使用docker-compose up,而是尝试分两步进行,以收集有关问题发生位置的更多信息。

  1. docker-compose --log-level DEBUG build
  2. docker-compose --log-level DEBUG run

https://docs.docker.com/compose/reference/overview/ [根据评论编辑]


抱歉,我意识到我在Dockerfile的顶部漏掉了两行。我已经更新了我的问题,以反映我完整的combined Dockerfile。感谢您提醒我使用--log-level命令。我现在正在查看。请注意,命令应该是docker-compose --log-level DEBUG build - ptk
1
我很高兴它能够帮助你获取更多信息! :) - Avanti Patil
1
注意,--log-level 已被弃用,在 2.0 版本中不再起作用。 - mushipao

0
在 Docker 中,前往“设置”->“Docker 引擎”->将“defaultKeepStorage”更新为30GB以解决此问题。
{
  "builder": {
    "gc": {
      "defaultKeepStorage": "30GB",
      "enabled": true
    }
  },
  "debug": false,
  "experimental": false,
  "features": {
    "buildkit": false
  },
  "insecure-registries": [],
  "registry-mirrors": []
}

-1

Docker 将 Linux 内核默认设置为 docker-desktop-data(默认)

请使用 PowerShell 运行以下命令:

wsl -l 

如果"wsl"不是一个被识别的命令,请浏览以下位置:
c:\windows\system32\

现在运行以下命令:
.\wsl.exe -l

您应该看到以下内容:

List of Distributions

如果您在列表中没有看到Ubuntu,可以使用以下命令进行安装:
.\wsl.exe --install -d Ubuntu-22.04

运行以下命令将您的发行版设置为Ubuntu:

.\wsl.exe --set-version Ubuntu-22.04 2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接