在Docker中覆盖ENTRYPOINT时,停止Apache2的速度要慢得多 [英] Stopping Apache2 is much slower when overriding ENTRYPOINT in Docker

查看:76
本文介绍了在Docker中覆盖ENTRYPOINT时,停止Apache2的速度要慢得多的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在对PHP应用程序进行容器化,并希望根据环境变量来修改Apache配置.这是在覆盖默认 ENTRYPOINT

I'm containerizing a PHP application and would like to modify the Apache configuration based on environment variables. This is done in a script overriding the default ENTRYPOINT:

FROM php:7.2-apache
# ...
COPY prepare-docker-configs.sh .
RUN chmod +x prepare-docker-configs.sh
ENTRYPOINT ./prepare-docker-configs.sh

这些修改之后,Apache无法启动. apache2-foreground a>似乎是丢失的命令,因此我在 prepare-docker-configs.sh

After those modifications, Apache doesn't start. apache2-foreground seems to be the missing command, so I run it at the end of prepare-docker-configs.sh

#!/bin/bash
# ... Some config substitution
apache2-foreground

现在Apache开始了,一切都能按预期进行.但是我注意到停止容器比以前慢了许多.我为两个星座运行了 time docker-compose down :

Now Apache got started and everything works as expected. But I noticed that stopping the container is much slower than before. I ran time docker-compose down for both constellations:

real    0m2,080s
user    0m0,449s
sys 0m0,064

使用我的自定义脚本为 ENTRYPOINT

real    0m12,247s
user    0m0,491s
sys 0m0,067s

因此,大约需要10秒钟的时间.尤其是在进行大量测试的开发过程中,这将使您花费大量时间.

So it takes about 10 seconds longer. Especially during development where a lot of testing is done, this would waist a lot of time in total.

我尝试从原始Dockerfile添加 STOPSIGNAL SIGWINCH ,并且还运行 docker-php-entrypoint ,但这都无济于事.

I tried adding STOPSIGNAL SIGWINCH from the original Dockerfile and also run docker-php-entrypoint, both doesn't help.

docker-compose.yml 文件没有什么特别的.由于内部冲突,它只是定义服务并覆盖默认网络:

The docker-compose.yml file is nothing special. It just defines the services and override the default network because of internal conflicts:

version: '2' 
services: 
  app: 
    build:
      context: .
      args:
        http_proxy: ${http_proxy}
    env_file: docker.env
    ports:
      - 80:80
      
networks:
  default:
    driver: bridge
    ipam:
      config:
       - subnet: 10.10.8.0/28

什么不起作用

资源问题

我正在具有SSD,i7 Quadcore和32GB RAM的Ubuntu工作站上运行此文件.它不会运行任何东西,负载也很低.资源问题极不可能发生.而且性能问题是可以重现的:在另一台装有Ryzen 5 3600和48GB内存的Ubuntu计算机上,它用了11秒的时间覆盖了 ENTRYPOINT .在Debian上,i3的运行速度要慢得多.

What doesn't work

Ressource issues

I'm running this on my Ubuntu workstation with SSD, i7 Quadcore and 32GB RAM. It doesn't run anything large, the load is quite low. A ressource issue is very unlikely. And the performance issue is reproduceable: On another Ubuntu machine with Ryzen 5 3600 and 48GB memory it took 11 seconds with overriden ENTRYPOINT. The same result on Debian with a much slower i3.

在我的脚本中,我最后调用 docker-php-entrypoint ,该代码执行

In my script, I call docker-php-entrypoint at the end, which executes the original entrypoint script from the PHP image. It doesn't start Apache successfully, I had to call apache2-foreground instead.

我在 Dockerfile

ENTRYPOINT ./prepare-docker-configs.sh
CMD apache2-foreground

prepare-docker-configs.sh 末尾的 exec 语句,假设已通过 CMD 条目

and an exec statement at the end of prepare-docker-configs.sh assuming that the CMD entry got passed

set -x
exec "$@"

但是容器退出了,因为什么都没通过

But the container exited because nothing was passed

app_1     | + set -x
app_1     | + exec
test_app_1 exited with code 0

我测试了直接传递文件

exec apache2-foreground

现在Apache已启动,但仍需要10秒钟以上的时间才能停止.

Now Apache is started, but it still takes 10+ seconds to stop.

推荐答案

一个Docker容器运行一个进程.在Dockerfile中声明 ENTRYPOINT 时,就是这个过程.当您 docker stop 一个容器时,它会将SIGTERM发送到该进程(仅),并且如果它在10秒钟内没有自行停止,它将发送SIGKILL强制将其杀死.由于容器进程的进程ID为1,因此在信号处理方面也有一些特殊条件.

A Docker container runs a single process; when you declare an ENTRYPOINT in the Dockerfile, that is the process. When you docker stop a container, it sends SIGTERM to that process (only), and if it doesn't stop itself within 10 seconds, it sends SIGKILL to forcibly kill it off. Since the container process has process ID 1, there are also some special conditions on signal handling.

在您的情况下,运行入口点脚本的 bash 实例是根进程,它以子进程的形式运行 apache2-foreground .您可以使用Bourne shell exec 命令,用您要运行的进程替换外壳;然后 apache2-foreground 代替主容器进程,并且 docker stop 信号直接进入该进程.

In your case, the bash instance running the entrypoint script is the root process, and it's running apache2-foreground as a child process. You can use the Bourne shell exec command to replace the shell with the process you're trying to run; then apache2-foreground the main container process instead, and the docker stop signals go straight to that process.

入口点脚本的典型模式是遵守Docker的"command"命令.部分.这将作为附加参数传递给入口点,因此入口点脚本通常看起来像

A typical pattern for entrypoint scripts is to honor the Docker "command" part. This gets passed to the entrypoint as additional arguments, so your entrypoint script typically looks like

#!/bin/sh
# ... Some config substitution
exec "$@"

然后在您的Dockerfile中,需要提供默认命令来运行

and then in your Dockerfile you need to provide the default command to run

# NOTE! ENTRYPOINT must be JSON-array syntax for this to work
ENTRYPOINT ["./prepare-docker-configs.sh"]
CMD apache2-foreground

由于入口点脚本仍是命令的 exec ,因此它将shell命令包装程序替换为进程1,并将接收 docker stop 信号.

Since the entrypoint script still execs the command, it replaces the shell command wrapper as process 1 and will receive the docker stop signals.

这篇关于在Docker中覆盖ENTRYPOINT时,停止Apache2的速度要慢得多的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆