我有以下 Dockerfile:
FROM ubuntu:22.04
COPY filebeat.yml /home/docker/filebeat.yml
RUN apt update && \
apt install -y sudo curl vim && \
adduser --disabled-password --gecos '' docker && \
adduser docker sudo && \
echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER docker
RUN sudo apt update && \
sudo apt install -y default-jdk && \
cd /home/docker/ && \
sudo curl -L -O --create-dirs https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.3.3-linux-x86_64.tar.gz && \
sudo tar xzvf filebeat-8.3.3-linux-x86_64.tar.gz && \
sudo nohup ./filebeat-8.3.3-linux-x86_64/filebeat -c ./filebeat.yml &
ENTRYPOINT ["tail", "-f", "/dev/null"]
尽管在第二个 RUN 命令中安装了 java,但当我连接终端并运行时,which java
我什么也得不到。同样 $JAVA_HOME 不存在等等。java去哪里了?我需要在这个容器中进行什么更改才能使 java 不消失?
这个 Dockerfile 有很多问题,甚至从哪里开始。
首先,高级问题:您正在尝试使用
RUN
. 这行不通。RUN
是构建时命令。它将在创建图像时运行一次。从该镜像启动容器时,它不会运行。如果你想让你的容器运行某些东西,它必须在ENTRYPOINT
or中CMD
。它必须在前台运行。接下来,关于分层。您应该在 Dockerfile 中对构建时命令进行排序,以便将不经常更改的“基本”步骤放在首位。这意味着所有
apt
的东西,基本配置,比如添加用户和安装 Filebeat。最后应该是 Filebeat 配置文件之类的东西。这样,当您更改配置文件时,只需重新构建一个层。About
sudo
:如果您允许您的用户使用 做任何事情sudo
,您还不如直接使用root。安全收益充其量是微不足道的。在您的情况下,根本不需要sudo
:只需先做系统工作,将 Filebeat 安装到用户无法写入的位置,也许还可以使配置文件仅可读。然后让 Docker 以受限用户启动 Filebeat。现在到了实际问题:永远不要在命令中使用
nohup
or 。& 符号将影响前面的整个命令,然后它不会运行到完成,而是立即被终止,因为构建步骤“完成”。&
RUN
顺便说一句,您还应该使用default-jdk-headless,其他一切都是浪费空间。
您的 Dockerfile 可能如下所示:
另请查看编写 Dockerfile 的最佳实践。