当前位置: 首页 > 知识库问答 >
问题:

Docker CMD commad在启动容器时不执行,但在容器内运行时起作用

娄利
2023-03-14

我有一个python脚本,它计算给定文件的字数,并在执行后将输出保存到“result.txt”文件中。我希望docker容器在容器启动时执行此操作,并在控制台上显示输出。下面是我的docker文件和python文件

FROM python:3
RUN mkdir /home/data
RUN mkdir /home/output
RUN touch /home/output/result.txt
WORKDIR /home/code
COPY word_counter.py ./
CMD ["python", "word_counter.py"]
ENTRYPOINT cat ../output/result.txt
import glob
import os
from collections import OrderedDict
import socket
from pathlib import Path

dir_path = os.path.dirname(os.path.realpath(__file__))
# print(type(dir_path))
parent_path = Path(dir_path).parent
data_path = str(parent_path)+"/data"
# print(data_path)
os.chdir(data_path)
myFiles = glob.glob('*.txt')

output = open("../output/result.txt", "w")
output.write("files in home/data are : ")
output.write('\n')
for x in myFiles :
    output.write(x)
    output.write('\n')

output.close()

total_words = 0

for x in myFiles :
    file = open(x, "r")
    data = file.read()
    words = data.split()

    total_words = total_words + len(words)
    file.close()

output = open("../output/result.txt", "a")
output.write("Total number of words in both the files : " + str(total_words))
output.write('\n')
output.close()

frequency = {}
for x in myFiles :
    if x == "IF.txt" :
        curr_file = x

document_text = open(curr_file, 'r')
text_string = document_text.read()
words = text_string.split()
 
for word in words:
    count = frequency.get(word,0)
    frequency[word] = count + 1

frequency_list_desc_order = sorted(frequency, key=frequency.get, reverse=True)

output = open("../output/result.txt", "a")
output.write("Top 3 words in IF.txt are :")
output.write('\n')

ip_addr = socket.gethostbyname(socket.gethostname())

for word in frequency_list_desc_order[:3]:
    line = word + " : " + str(frequency[word])
    output.write(line)
    output.write('\n')

output.write("ip address of the machine : " + ip_addr + "\n")
output.close()

我正在映射一个本地目录,它有两个文本文件IF. txt和Limerick1.txt从主机到容器内的目录/home/data,容器内的python代码读取文件并将输出保存到result.txt在容器内部的“主/输出”中。

当我使用docker run命令启动容器时,我希望容器将“result.txt”中的输出打印到控制台。

问题:使用docker run启动容器时,docker不执行以下语句。

CMD ["python", "word_counter.py"]

运行容器的命令:

docker run -it -v /Users/xyz/Desktop/project/docker:/home/data proj2docker bash

但是,当我在容器中运行相同的命令“python word_counter.py”时,它执行得非常好。

有人能帮我吗?

共有1个答案

吴凯泽
2023-03-14

您在Dockerfile中有一个入口点。此入口点将运行并基本上将CMD作为附加参数。

启动容器时运行的最后一个命令如下

cat ../output/result.txt python word_counter.py

这可能不是你想要的。我建议移除入口点。或者根据您的需要进行修复。

如果您想打印该文件并仍然执行该命令,可以执行如下操作。

CMD ["python", "word_counter.py"]
ENTRYPOINT ["/bin/sh", "-c", "cat ../output/result.txt; exec $@"]

它将运行一些命令作为入口点,在本例中打印该文件的输出,然后执行CMD,该命令作为其标准posix shell行为提供为$@。在任何shell脚本中,访问传递给脚本的所有参数都是一样的。这里使用exec的好处是,它将运行进程id为1的python,这在您希望将信号发送到容器中到python进程(例如kill)时非常有用。

最后,当您使用显示的命令启动容器时

docker run -it -v /Users/xyz/Desktop/project/docker:/home/data proj2docker bash

您正在重写Dockerfile中的CMD。因此,在这种情况下,预计它不会运行python。即使你的入口点没有前面提到的问题。如果希望始终运行python程序,则需要将该部分作为入口点。您可能遇到的问题是,它将首先运行entrypoint直到完成,然后运行您的命令,在本例中是bash。

如果你想的话,你可以在后台运行它。请注意,没有默认的CMD,但仍然是exec$@,这将允许您在Python在后台运行时运行任意命令,如bash。

ENTRYPOINT ["/bin/sh", "-c", "cat ../output/result.txt; python word_counter.py &; exec $@"]

如果您在entrypoint中做了大量工作,那么将其移动到专用脚本并作为entrypoint运行该脚本可能会更干净,您仍然可以在shell脚本的末尾调用exec$@。

根据你的评论,你想先运行python,然后在文件上运行cat。您可以删除入口点,只需使用命令即可。

CMD ["/bin/sh", "-c", "python word_counter.py && cat ../output/result.txt"]
 类似资料:
  • 问题内容: 我在CI和CD上创建了Jenkinsfile,Dockerfile,Dockerfile.test到CI和CD,在GitHub上构建了我的服务器API,我在Jenkins上构建了该构建,并且构建成功,并且我的docker在Jenkinsfile阶段也在容器上运行,我创建了用于测试和部署在服务器API上,并使用docker作为容器 我也使用docker-compose在docker上运行

  • 我成功地在ubuntu 18.04上安装了docker和nvidia-docker,我从NVIDIA的GPU云中提取了这个图像 用这个命令运行它 例如,容器给了我一个shell提示,它似乎可以工作 导致 它看到了我脆弱的gpu。我尝试用这个命令运行jupyter 但我明白了 我知道Jupyter安装在容器里因为当我打字的时候 我得到 打字 给予 在连接到容器的主机目录中,我有几个笔记本 但似乎什么

  • 问题内容: 我准备了一个docker-compose文件来部署带有数据库的容器: 没关系。但是现在我需要创建一个数据库并建立其结构。我需要执行一些sql命令。为了检查我是否能够做到这一点,我将其添加到服务中: 但是我遇到以下错误: 我感觉命令是在Sql Server实例启动之前执行的。我该如何解决?Sql Server启动后如何执行一些sql? 问题答案: 问题是在容器中仅执行一个命令。当您在其中

  • 容器运行时(Container Runtime)是Kubernetes最重要的组件之一,负责真正管理镜像和容器的生命周期。Kubelet通过Container Runtime Interface (CRI)与容器运行时交互,以管理镜像和容器。 CRI Container Runtime Interface (CRI)是Kubelet 1.5/1.6中主要负责的一块项目,它重新定义了Kubelet

  • 我不能和docker一起经营jenkins的形象。它在运行时卡住: afik@ubuntu:~$docker run——名称myjenkins-p8080:8080-p50000:50000-v/var/jenkins_home jenkins

  • 问题内容: 假设我在Spring容器中定义了一个bean(例如BeanA),并且此bean被注入到对象中。(例如BeanAUser) 在运行时,我可以使用另一个bean实例替换spring容器中的原始BeanA吗?并且还将这个新的bean实例重新注入BeanAUser中以替换原始的BeanA吗? 问题答案: 使用代理可以轻松实现。创建接口的委派实现,并切换要委派的对象。