没有OOM异常时Docker-compose退出代码为137

use*_*888 22 docker docker-compose cypress

当我运行以下命令时,我希望退出代码为 0,因为我的combined容器运行了一个成功退出的测试,退出代码为 0。

docker-compose up --build --exit-code-from combined
Run Code Online (Sandbox Code Playgroud)

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

以下是我的 docker-compose 版本:

docker-compose version 1.25.0, build 0a186604
Run Code Online (Sandbox Code Playgroud)

根据这篇文章,137 的退出代码可能是由于两个主要问题。

  1. 容器收到一个docker stop,应用程序没有正常处理 SIGTERM
  2. 容器内存不足 (OOM)。

我知道 137 退出代码不是因为我的容器内存不足。当我运行时docker inspect <container-id>,我可以看到“OOMKilled”是假的,如下面的代码片段所示。我还为 Docker 引擎分配了 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"
        },
Run Code Online (Sandbox Code Playgroud)

我的容器没有从 a 退出,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:
Run Code Online (Sandbox Code Playgroud)

下面是Dockerfile的combined服务docker-compose.yml

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" ]
Run Code Online (Sandbox Code Playgroud)

以下是我的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"
Run Code Online (Sandbox Code Playgroud)

下面是我的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
Run Code Online (Sandbox Code Playgroud)

以下是mongo_restore.sh.

#!/bin/bash
# Creates db using copied data
mongorestore /tmp/dump
Run Code Online (Sandbox Code Playgroud)

下面是我运行时的最后几行输出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
Run Code Online (Sandbox Code Playgroud)

正如您在上面看到的,令人困惑的是,测试和脚本以退出代码 0 结束,因为我的所有测试都成功通过,但容器仍然以退出代码 137 退出。

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

NODE_ENV=test $(npm bin)/cypress run --config video=false --browser chrome
Run Code Online (Sandbox Code Playgroud)

下面是当我从 注释掉/删除上面的行时收到的输出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
Run Code Online (Sandbox Code Playgroud)

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

编辑:

在调试模式下运行以下 docker-compose 命令后,我注意到 b-db 似乎在关闭时遇到了一些问题,并且可能因此收到来自 Docker 的 SIGKILL 信号。

docker-compose --log-level DEBUG up --build --exit-code-from combined; echo $?
Run Code Online (Sandbox Code Playgroud)

根据以下输出,情况确实如此吗?

...
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
Run Code Online (Sandbox Code Playgroud)

小智 10

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

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


Jul*_*oHM 6

错误信息让我印象深刻: 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可以避免错误。

  • 是的,因为我使用的是 `--exit-code-from`,所以它意味着 `--abort-on-container-exit` - 文档[此处](https://docs.docker.com/compose/reference/向上/)。 (2认同)

cod*_*pic 5

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

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

转到 Docker 桌面应用程序 > 首选项 > 资源 > 高级并增加 MEMORY - 最好加倍。

  • 但是,退出代码 137 并不总是表示 OOM 问题。例如,在我的例子中,我正在处理退出代码 137,但具有以下详细信息: `"State":"Status":"exited","Running": false,"Paused": false,"Restarting": false,"OOMKilled": false,"Dead": false,"Pid": 0,"ExitCode": 137,"Error": "linux 运行时规范设备: 添加自定义设备时收集设备信息时出错 \"/dev/ttyUSB0 \": 没有这样的文件或目录",` (9认同)
  • 这个答案对我有帮助,尽管它与问题无关。截至撰写本文时,至少问题包括:“”“我知道 137 退出代码不是因为我的容器内存不足。当我运行 docker inform &lt;container-id&gt; 时,我可以看到“OOMKilled”是false,如下面的代码片段所示。我还为 Docker 引擎分配了 6GB 内存,这对于我的应用程序来说足够了。""" (3认同)
  • `dockerspect` 输出的重要部分是 `"OOMKilled": false` 和 `"ExitCode": 137`。如果“OOMKilled”为“false”,则内存限制不是退出代码 137 的原因。 (3认同)
  • 谢谢@DavidWiniecki - 不知道 137 错误可能还有 OOM 之外的其他原因。就您而言 - 如果 OOMKilled 为 false,那么 137 错误的原因是什么? (2认同)