我有一个使用HealthCheck的Nginx Dockerimage,这样:

HEALTHCHECK --interval=3s --timeout=1s \
CMD nc -vz -w1 127.0.0.1 8080 || exit 1

出于安全原因,我也想删除shell,但是HealthCheck在此之后停止工作。我试图完全删除BusyBox (alpine-basilayout),单独删除/bin/sh的符号链接,用微小的等。

如何正确执行此操作,以免破坏容器中的应用程序并保存健康检查?

分析解答

CMD指令有两种形式。当您写这篇文章时:

CMD nc -vz -w1 127.0.0.1 8080 || exit 1

它被翻译成sh -c 'nc -vz -w1 127.0.0.1 8080 || exit 1。您可以通过使用"exec"形式CMD指令避免执行该shell执行,例如:

CMD ["nc", "-vz", "-w1", "127.0.0.1", "8080"]

这将直接执行nc,而无需涉及shell。请注意,您现有的HealthCheck使用shell语法(|| exit 1)部分明确进行了;如果您不使用shell,那将不起作用。


例如,使用此Dockerfile建造的容器永远不会健康:

FROM alpine

RUN apk add darkhttpd curl
RUN rm -f /bin/sh

ENTRYPOINT ["darkhttpd"]
CMD ["/var/www/localhost/htdocs", "--port", "8080"]

HEALTHCHECK --interval=3s --timeout=1s \
CMD nc -vz -w1 127.0.0.1 8080

但是,这是根据需要起作用的:

FROM alpine

RUN apk add darkhttpd curl
RUN rm -f /bin/sh

ENTRYPOINT ["darkhttpd"]
CMD ["/var/www/localhost/htdocs", "--port", "8080"]

HEALTHCHECK --interval=3s --timeout=1s \
CMD ["nc", "-vz", "-w1", "127.0.0.1", "8080"]