我有一个相当简单的 dockerfile,我需要将服务公开到端口,以便用户可以通过 netcat 进入它。
FROM ubuntu:16.04
RUN apt-get update
RUN apt-get install -y socat
# Change to strict permissions
RUN chmod 770 /bin/* /usr/bin/*
RUN chmod 771 /bin/cat /bin/ls /bin/sh /usr/bin/socat
# Add user bob
RUN useradd -m -s /bin/sh bob
EXPOSE 9000
# Add dir and change to working
RUN mkdir /home/bob/monster
WORKDIR /home/bob/monster
# copy working files and change permissions
COPY /files files
CMD ["sh","/home/bob/monster/files/start.sh"]
然后我使用以下两个命令构建并运行:
$ sudo docker build -t intmonster .
$ sudo docker run -p 9000:9000 --rm intmonster
这一切似乎都有效,除了我在主机系统上尝试通过 netcat 连接到该服务的那一刻:
$ nc 0.0.0.0 9000
这会在容器运行的终端中触发此打印:
$ sudo docker run -p 9000:9000 --rm intmonster
2022/01/01 22:59:53 socat[9] E execvp("./monster", "./monster"): No such file or directory
2022/01/01 22:59:53 socat[8] W waitpid(): child 9 exited with status 1
看起来好像找不到“monster”目录。
这对我来说似乎很奇怪,因此我想做一些测试。为了进行测试,我删除了最后一个“CMD”行,然后再次构建。我现在再次带着标志运行-it
,以便在容器内玩耍。
我 cd 到我想要运行的 sh 文件,并尝试运行它:
root@e3b83ca56f0b:/home/bob/monster/files# sh start.sh
这行得通,我可以通过 netcat 找到它。然后我尝试cd ..
从那里运行该文件。乍一看它有效,但是当我尝试通过 netcat 连接到该服务时,出现以下错误:
root@e3b83ca56f0b:/home/bob/monster# sh files/start.sh
2022/01/01 23:51:15 socat[46] E execvp("./monster", "./monster"): No such file or directory
2022/01/01 23:51:15 socat[45] W waitpid(): child 46 exited with status 1
我的理论是,这个问题发生是因为 bash 文件运行一个名为“monster”的可执行文件。当从主目录运行时,程序会查找调用文件的相对路径,而不是从 bash 文件本身。
如何从主 Firector 调用 bash 文件,但仍然在 bash 文件中使用相对路径?
编辑:
“文件”目录如下所示:
└── files
├── flag.txt
├── monster
└── start.sh
答案1
您已经提到,当您从目录运行该脚本时,该脚本会起作用/home/bob/monster/files
。这与错误消息一致,因为脚本似乎在与其自身相同的目录中寻找可执行文件 ( execvp("./monster", "./monster")
)。
但是,在 dockerfile 中,您只有WORKDIR /home/bob/monster
,它高一级。添加第二WORKDIR
条指令应该可以解决问题:
COPY /files files
WORKDIR files
这将使您进入其中/home/bob/monster/files
,从而使脚本能够按预期工作。
指导文档WORKDIR
:https://docs.docker.com/engine/reference/builder/#workdir