Stopping Apache2 is much slower when overriding ENTRYPOINT in Docker

末鹿安然 提交于 2021-02-08 10:52:09

问题


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

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

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:

Without my custom overriden ENTRYPOINT

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

With my custom script as ENTRYPOINT

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

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.

Why is my custom ENTRYPOINT so much slower on stopping and how could it be fixed?

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

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

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.

Calling the original 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.

Starting the Apache process with the RUN statement

I added a CMD directive to my Dockerfile

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

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

I tested passing the file directly

exec apache2-foreground

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


回答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.

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.

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 "$@"

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

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



来源:https://stackoverflow.com/questions/62596598/stopping-apache2-is-much-slower-when-overriding-entrypoint-in-docker

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!