无法从 dockerfile 在后台运行 linux 命令?

Posted

技术标签:

【中文标题】无法从 dockerfile 在后台运行 linux 命令?【英文标题】:Not able to run linux command in background from dockerfile? 【发布时间】:2022-01-18 03:36:39 【问题描述】:

这是我的 docker 文件,

FROM ubuntu:20.04

ARG DEBIAN_FRONTEND=noninteractive
RUN apt update && apt upgrade -y
RUN apt install -y -q software-properties-common
RUN apt install -y -q build-essential python3-pip python3-dev
RUN apt-get install -y gcc make apt-transport-https ca-certificates build-essential
RUN apt-get install -y curl autoconf automake libtool pkg-config git libreoffice wget
RUN apt-get install -y g++
RUN apt-get install -y autoconf automake libtool
RUN apt-get install -y pkg-config
RUN apt-get install -y libpng-dev
RUN apt-get install -y libjpeg8-dev
RUN apt-get install -y libtiff5-dev
RUN apt-get install -y zlib1g-dev
RUN apt-get install -y libleptonica-dev
RUN apt-get install -y libicu-dev libpango1.0-dev libcairo2-dev

# python dependencies
RUN pip3 install -U pip setuptools wheel
RUN pip3 install gunicorn uvloop httptools dvc[s3]
RUN pip3 install nltk
RUN python3 -c "import nltk;nltk.download('stopwords')" 

# copy required files
RUN bash -c 'mkdir -p /app/app,models,requirements'
COPY ./config.yaml /app
COPY ./models /app/models
COPY ./requirements /app/requirements
COPY ./app /app/app


# tensorflow serving for models
RUN echo "deb [arch=amd64] http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal" | tee /etc/apt/sources.list.d/tensorflow-serving.list && \
    curl https://storage.googleapis.com/tensorflow-serving-apt/tensorflow-serving.release.pub.gpg | apt-key add -
RUN apt-get update && apt-get install tensorflow-model-server
RUN tensorflow_model_server --port=8500 --rest_api_port=8501 --model_config_file=/app/models/model.conf --model_base_path=/app/models &

ENTRYPOINT /usr/local/bin/gunicorn \
    -b 0.0.0.0:80 \
    -w 1 \
    -k uvicorn.workers.UvicornWorker app.main:app \
    --timeout 120 \
    --chdir /app \
    --log-level 'info' \
    --error-logfile '-'\
    --access-logfile '-'

无论我在运行 docker 映像时执行以下操作,都不会执行以下操作,

运行 tensorflow_model_server --port=8500 --rest_api_port=8501 --model_config_file=/app/models/model.conf --model_base_path=/app/models &

为什么会这样?如何在后台运行上述命令并转到 docker 文件中的入口点。任何帮助表示赞赏。

【问题讨论】:

这不是容器应该运行的方式。容器旨在运行only one process。如果你还想运行多个进程,你必须dig into installing a supervisor and how it can be used in your use case。 【参考方案1】:

这是为什么呢?

因为您的 docker 容器被配置为运行 /usr/local/bin/gunicorn,正如 ENTRYPOINT 指令所定义的那样。

如何在后台运行上述命令并转到 docker 文件中的入口点。

执行此操作的标准方法是编写一个包装脚本来执行您需要的所有程序。所以对于这个例子,类似run.sh:

#!/bin/bash

# Start tensorflow server
tensorflow_model_server --port=8500 --rest_api_port=8501 --model_config_file=/app/models/model.conf --model_base_path=/app/models &

# Start gunicorn
/usr/local/bin/gunicorn \
    -b 0.0.0.0:80 \
    -w 1 \
    -k uvicorn.workers.UvicornWorker app.main:app \
    --timeout 120 \
    --chdir /app \
    --log-level 'info' \
    --error-logfile '-'\
    --access-logfile '-'

然后在 Dockerfile 中:

ADD run.sh /usr/local/bin/run.sh
RUN chmod +x /usr/local/bin/run.sh
ENTRYPOINT /usr/local/bin/run.sh

【讨论】:

执行此操作的标准方法是启动多个容器。您展示的方法在几个方面很脆弱:很难仅从 tensorflow_model_server 获取日志,如果失败,您的组合应用程序会出错但您不会注意到。 @DavidMaze The standard way to do this is to launch multiple containers,是的,确实如此,但可能存在需要操作要求的有效场景。这真的值得投反对票吗?【参考方案2】:

您应该能够创建一个单独的 Dockerfile,运行 TensorFlow 服务器:

FROM ubuntu:20.04

# Install the server
RUN echo "deb [arch=amd64] http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal" | tee /etc/apt/sources.list.d/tensorflow-serving.list \
 && curl https://storage.googleapis.com/tensorflow-serving-apt/tensorflow-serving.release.pub.gpg | apt-key add - \
 && apt-get update \
 && DEBIAN_FRONTEND=noninteractive \
    apt-get install --no-install-recommends --assume-yes \
      tensorflow-model-server

# Copy our local models into the image
COPY ./models /models

# Make the server be the main container command
CMD tensorflow_model_server --port=8500 --rest_api_port=8501 --model_config_file=/models/model.conf --model_base_path=/models

然后,您可以从主应用程序的 Dockerfile 中删除类似的行。

完成此操作后,您可以设置启动两个容器的 Docker Compose 设置:

version: '3.8'
services:
  application:
    build: .
    ports: ['8000:80']
    environment:
      - TENSORFLOW_URL=http://tf:8500
  tf:
    build:
      context: .
      dockerfile: Dockerfile.tensorflow
    # ports: ['8500:8500', '8501:8501']

您的应用程序需要知道要查找该os.environ['TENSORFLOW_URL']。现在您有两个容器,每个容器都有其CMD 来运行单个前台进程。

在较低级别,Docker 映像不包含任何正在运行的进程;把它想象成一个 tar 文件加上一个要运行的命令行。在RUN 命令中在后台启动的任何操作都将在RUN 命令完成后立即终止。

【讨论】:

以上是关于无法从 dockerfile 在后台运行 linux 命令?的主要内容,如果未能解决你的问题,请参考以下文章

无法运行rake db:使用docker-compose在Dockerfile中创建

ENTRYPOINT和CMD

无法在 Dockerfile 中运行 sysctl 命令

dockerfile部署tomcat+jdk

无法在 Raspberry Pi 上从 Dockerfile 安装 dlib

基于Dockerfile制作tomcat镜像