我有以下 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 不消失?
答案1
这个 Dockerfile 存在很多问题,简直不知道从何说起。
首先,高层次的问题:你正试图使用 启动守护进程RUN
。这行不通。RUN
是构建时命令。它将运行一次,当图像被创建时。它将不是从此映像启动容器时运行。如果您希望容器运行某些内容,则它必须位于ENTRYPOINT
或中CMD
。它必须在前台运行。
接下来,关于分层。您应该在 Dockerfile 中对构建时命令进行排序,以便不经常更改的步骤和“基本”步骤首先出现。这意味着所有apt
内容,基本配置(例如添加用户以及安装 Filebeat)。接下来应该做什么最后的是类似于 Filebeat 配置文件的东西。这样,当您更改配置文件时,只需重建单个层。
关于sudo
:如果你允许用户使用做任何事情sudo
,你不妨只使用根直接。安全优势充其量只是微不足道的。对于您来说,根本不需要sudo
:只需先进行系统操作,将 Filebeat 安装到用户无法写入的位置,也许还可以使配置文件仅可读。然后让 Docker 使用受限用户启动 Filebeat。
现在来看看实际问题:切勿在命令中使用nohup
或。& 符号会影响&
RUN
整个命令前面的那个将不会运行完成,而是会立即被终止,因为构建步骤已经“完成”。
你也应该使用默认 jdk-headless顺便说一句,其他一切都是浪费空间。
你的 Dockerfile 可能如下所示:
FROM ubuntu:22.04
RUN apt update \
&& apt install -y curl default-jdk-headless vim \
&& adduser --disabled-password --gecos '' docker \
&& cd /opt \
&& curl -SL -o filebeat.tar.gz https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.3.3-linux-x86_64.tar.gz \
&& mkdir filebeat \
&& tar --strip-components 1 -xf filebeat.tar.gz -C filebeat/ \
&& rm filebeat.tar.gz \
&& rm -rf /var/lib/apt/lists/*
COPY filebeat.yml /etc/filebeat.yml
USER docker
ENTRYPOINT ["/opt/filebeat/filebeat", "-c", "/etc/filebeat.yml"]
另请查看编写 Dockerfile 的最佳实践。