首页 > 解决方案 > Docker CMD commad 在运行启动容器时不执行,但在从容器内运行时工作

问题描述

我有一个 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 代码读取文件并将输出保存到结果.txt 在容器内的“home/output”中。

当我使用 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”时,它执行得非常好。

有人可以帮我弄这个吗?

标签: pythonbashdockerdockerfile

解决方案


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

启动容器时运行的最终命令如下所示

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

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

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

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

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

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

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

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

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

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

如果您在入口点做了很多工作,将其移至专用脚本并将此脚本作为入口点运行可能会更干净,您仍然可以在 shell 脚本的末尾调用 exec $@。

根据您的评论,您想先运行 python 然后在文件上运行 cat 。您可以删除入口点并仅使用命令执行此操作。

CMD ["/bin/sh", "-c", "python word_counter.py && cat ../output/result.txt"]

推荐阅读