just-containers / s6-overlay

s6 overlay for containers (includes execline, s6-linux-utils & a custom init)
Other
3.67k stars 207 forks source link

πŸ™‹β€β™‚οΈQuestion: How to get CTRL+C to exit faster and correctly? #586

Closed jaydrogers closed 1 month ago

jaydrogers commented 1 month ago

Problem

When I run images with S6 Overlay, it takes about 5-10 seconds for them to quit when I press CTRL + C.

Expected Result

Example

Here is a quick demo of my project that has two variations:

You will notice the FPM image (that does NOT run S6 Overlay) exits almost immediately and correctly. It's not until I introduce S6 Overlay is where the container changes behavior.

Video example

https://github.com/just-containers/s6-overlay/assets/3174134/c389622a-9bc3-4552-9467-6c687b8e9a3d

My code

Here's examples if this helps

Related issue (other projects)

What I'm looking for

I'm not expecting anyone to go fix anything in my code. I just wanted to ask the community if they have seen anything that I can do to learn from and improve.

If there is a better channel to ask this question on instead of issues, let me know. Thank you and I appreciate your help!

skarnet commented 1 month ago

Two questions:

jaydrogers commented 1 month ago

Thanks for chiming in!

Are you running nginx with the daemon off option? (you should)

My run script calls nginx but I do have daemon off; set in the NGINX conf.

What messages do you get when running your container with a higher value for S6_VERBOSITY? 1 isn't ideal for debugging πŸ˜‰

Thanks for the tip! I forgot about that.

Running this:

docker run --rm -e S6_VERBOSITY=5 serversideup/php:beta-8.3-fpm-nginx

This is my output:

Screenshot 2024-07-10 at 18 01 53@2x

What I still notice

It still takes 5 seconds for the container to shutdown and it's showing a 111 exit code.

jaydrogers commented 1 month ago

Additional thought

I see my "one off" scripts running as services. I wonder if I need an explicit exit 0 in my script so S6 Overlay does not try to monitor my scripts?

Viewing my scripts

docker run --rm --entrypoint='' serversideup/php:beta-8.3-fpm-nginx ls -al /etc/s6-overlay/scripts/
image

Example script

These are scripts that run before the services start. For example, here is the 50-laravel-automations script:

#!/command/with-contenv sh
script_name="laravel-automations"

test_db_connection() {
    php -r "
        require '$APP_BASE_DIR/vendor/autoload.php';
        use Illuminate\Support\Facades\DB;

        \$app = require_once '$APP_BASE_DIR/bootstrap/app.php';
        \$kernel = \$app->make(Illuminate\Contracts\Console\Kernel::class);
        \$kernel->bootstrap();

        \$driver = DB::getDriverName();

            if( \$driver === 'sqlite' ){
                echo 'SQLite detected';
                exit(0); // Assume SQLite is always ready
            }

        try {
            DB::connection()->getPdo(); // Attempt to get PDO instance
            if (DB::connection()->getDatabaseName()) {
                exit(0); // Database exists and can be connected to, exit with status 0 (success)
            } else {
                echo 'Database name not found.';
                exit(1); // Database name not found, exit with status 1 (failure)
            }
        } catch (Exception \$e) {
            echo 'Database connection error: ' . \$e->getMessage();
            exit(1); // Connection error, exit with status 1 (failure)
        }
    "
}

# Set default values for Laravel automations
: "${AUTORUN_ENABLED:=false}"
: "${AUTORUN_LARAVEL_MIGRATION_TIMEOUT:=30}"

if [ "$DISABLE_DEFAULT_CONFIG" = "false" ]; then
    # Check to see if an Artisan file exists and assume it means Laravel is configured.
    if [ -f "$APP_BASE_DIR/artisan" ] && [ "$AUTORUN_ENABLED" = "true" ]; then
        echo "Checking for Laravel automations..."
        ############################################################################
        # artisan migrate
        ############################################################################
        if [ "${AUTORUN_LARAVEL_MIGRATION:=true}" = "true" ]; then
            count=0
            timeout=$AUTORUN_LARAVEL_MIGRATION_TIMEOUT

            echo "πŸš€ Clearing Laravel cache before attempting migrations..."
            php "$APP_BASE_DIR/artisan" config:clear

            while [ $count -lt "$timeout" ]; do
                test_db_connection > /dev/null 2>&1
                status=$?
                if [ $status -eq 0 ]; then
                    echo "βœ… Database connection successful."
                    break
                else
                    echo "Waiting on database connection, retrying... $((timeout - count)) seconds left"
                    count=$((count + 1))
                    sleep 1
                fi
            done

            if [ $count -eq "$timeout" ]; then
                echo "Database connection failed after multiple attempts."
                exit 1
            fi

            echo "πŸš€ Running migrations..."
            if [ "${AUTORUN_LARAVEL_MIGRATION_ISOLATION:=false}" = "true" ]; then
                php "$APP_BASE_DIR/artisan" migrate --force --isolated
            else
                php "$APP_BASE_DIR/artisan" migrate --force
            fi
        fi

        ############################################################################
        # artisan storage:link
        ############################################################################
        if [ "${AUTORUN_LARAVEL_STORAGE_LINK:=true}" = "true" ]; then
            if [ -d "$APP_BASE_DIR/public/storage" ]; then
                echo "βœ… Storage already linked..."
            else
                echo "πŸ” Linking the storage..."
                php "$APP_BASE_DIR/artisan" storage:link
            fi
        fi
        ############################################################################
        # artisan config:cache
        ############################################################################
        if [ "${AUTORUN_LARAVEL_CONFIG_CACHE:=true}" = "true" ]; then
            echo "πŸš€ Caching Laravel config..."
            php "$APP_BASE_DIR/artisan" config:cache
        fi

        ############################################################################
        # artisan route:cache
        ############################################################################
        if [ "${AUTORUN_LARAVEL_ROUTE_CACHE:=true}" = "true" ]; then
            echo "πŸš€ Caching Laravel routes..."
            php "$APP_BASE_DIR/artisan" route:cache
        fi

        ############################################################################
        # artisan view:cache
        ############################################################################
        if [ "${AUTORUN_LARAVEL_VIEW_CACHE:=true}" = "true" ]; then
            echo "πŸš€ Caching Laravel views..."
            php "$APP_BASE_DIR/artisan" view:cache
        fi

        ############################################################################
        # artisan event:cache
        ############################################################################
        if [ "${AUTORUN_LARAVEL_EVENT_CACHE:=true}" = "true" ]; then
            echo "πŸš€ Caching Laravel events..."
            php "$APP_BASE_DIR/artisan" event:cache
        fi
    fi
else
    if [ "$LOG_OUTPUT_LEVEL" = "debug" ]; then
        echo "πŸ‘‰ $script_name: DISABLE_DEFAULT_CONFIG does not equal 'false', so automations will NOT be performed."
    fi
fi

Question

Do I need an exit 0 so I don't see this message anymore?

s6-rc: info: service 50-laravel-automations successfully stopped
skarnet commented 1 month ago

I have a few additional questions to help orient my diagnosis:

I can see your nginx service all right but there's something more to it. The scripts you put in /etc/s6-overlay/scripts should not be run by s6-rc; the only way they'll be started and stopped like this is if you somehow make service definition directories out of them in /etc/s6-overlay/s6-rc.d and add them to the user bundle, which I can't see anywhere in your repository.

jaydrogers commented 1 month ago

Thanks for asking more! I greatly appreciate your help.

Just a note

These are public images that I'm using, so feel free to run these same commands on your local machine if you'd like.

> What happens if you start the container with ENV S6_KILL_GRACETIME=1?

Command:

docker run --rm -e S6_KILL_GRACETIME=1 -e S6_VERBOSITY=5 serversideup/php:beta-8.3-fpm-nginx

Results:

Output:

S6_KILL_GRACETIME=1 Results ```txt #################### # Start #################### s6-rc-compile: tracing: from s6-rc-compile internals: adding identifier s6rc-oneshot-runner of type longrun s6-rc-compile: tracing: from s6-rc-compile internals: adding identifier s6rc-fdholder of type longrun s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/0-container-info s6-rc-compile: info: 0-container-info has type oneshot s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier 0-container-info of type oneshot s6-rc-compile: tracing: dependency from 0-container-info to s6rc-oneshot-runner (0) s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/1-debug-mode s6-rc-compile: info: 1-debug-mode has type oneshot s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier 1-debug-mode of type oneshot s6-rc-compile: tracing: from 1-debug-mode: adding identifier 0-container-info of type unknown s6-rc-compile: tracing: identifier 0-container-info was already declared with type oneshot s6-rc-compile: tracing: dependency from 1-debug-mode to 0-container-info (34) s6-rc-compile: tracing: dependency from 1-debug-mode to s6rc-oneshot-runner (0) s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/10-init-webserver-config s6-rc-compile: info: 10-init-webserver-config has type oneshot s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier 10-init-webserver-config of type oneshot s6-rc-compile: tracing: from 10-init-webserver-config: adding identifier 1-debug-mode of type unknown s6-rc-compile: tracing: identifier 1-debug-mode was already declared with type oneshot s6-rc-compile: tracing: dependency from 10-init-webserver-config to 1-debug-mode (51) s6-rc-compile: tracing: dependency from 10-init-webserver-config to s6rc-oneshot-runner (0) s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/50-laravel-automations s6-rc-compile: info: 50-laravel-automations has type oneshot s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier 50-laravel-automations of type oneshot s6-rc-compile: tracing: from 50-laravel-automations: adding identifier 10-init-webserver-config of type unknown s6-rc-compile: tracing: identifier 10-init-webserver-config was already declared with type oneshot s6-rc-compile: tracing: dependency from 50-laravel-automations to 10-init-webserver-config (64) s6-rc-compile: tracing: dependency from 50-laravel-automations to s6rc-oneshot-runner (0) s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/nginx s6-rc-compile: info: nginx has type longrun s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier nginx of type longrun s6-rc-compile: tracing: from nginx: adding identifier php-fpm of type unknown s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/php-fpm s6-rc-compile: info: php-fpm has type longrun s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier php-fpm of type longrun s6-rc-compile: tracing: previously encountered identifier php-fpm now has type longrun s6-rc-compile: tracing: from php-fpm: adding identifier 50-laravel-automations of type unknown s6-rc-compile: tracing: identifier 50-laravel-automations was already declared with type oneshot s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/user s6-rc-compile: info: user has type bundle s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier user of type bundle s6-rc-compile: tracing: from user: adding identifier php-fpm of type unknown s6-rc-compile: tracing: identifier php-fpm was already declared with type longrun s6-rc-compile: tracing: from user: adding identifier nginx of type unknown s6-rc-compile: tracing: identifier nginx was already declared with type longrun s6-rc-compile: tracing: from user: adding identifier 0-container-info of type unknown s6-rc-compile: tracing: identifier 0-container-info was already declared with type oneshot s6-rc-compile: tracing: from user: adding identifier 1-debug-mode of type unknown s6-rc-compile: tracing: identifier 1-debug-mode was already declared with type oneshot s6-rc-compile: tracing: from user: adding identifier 50-laravel-automations of type unknown s6-rc-compile: tracing: identifier 50-laravel-automations was already declared with type oneshot s6-rc-compile: tracing: from user: adding identifier 10-init-webserver-config of type unknown s6-rc-compile: tracing: identifier 10-init-webserver-config was already declared with type oneshot s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/user2 s6-rc-compile: info: user2 has type bundle s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier user2 of type bundle s6-rc-compile: info: parsing /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources/base s6-rc-compile: info: base has type bundle s6-rc-compile: tracing: from /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources: adding identifier base of type bundle s6-rc-compile: tracing: from base: adding identifier fix-attrs of type unknown s6-rc-compile: tracing: from base: adding identifier legacy-cont-init of type unknown s6-rc-compile: info: parsing /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources/fix-attrs s6-rc-compile: info: fix-attrs has type oneshot s6-rc-compile: tracing: from /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources: adding identifier fix-attrs of type oneshot s6-rc-compile: tracing: previously encountered identifier fix-attrs now has type oneshot s6-rc-compile: tracing: dependency from fix-attrs to s6rc-oneshot-runner (0) s6-rc-compile: info: parsing /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources/legacy-cont-init s6-rc-compile: info: legacy-cont-init has type oneshot s6-rc-compile: tracing: from /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources: adding identifier legacy-cont-init of type oneshot s6-rc-compile: tracing: previously encountered identifier legacy-cont-init now has type oneshot s6-rc-compile: tracing: from legacy-cont-init: adding identifier fix-attrs of type unknown s6-rc-compile: tracing: identifier fix-attrs was already declared with type oneshot s6-rc-compile: tracing: dependency from legacy-cont-init to fix-attrs (142) s6-rc-compile: tracing: dependency from legacy-cont-init to s6rc-oneshot-runner (0) s6-rc-compile: info: parsing /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources/legacy-services s6-rc-compile: info: legacy-services has type oneshot s6-rc-compile: tracing: from /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources: adding identifier legacy-services of type oneshot s6-rc-compile: tracing: from legacy-services: adding identifier user of type unknown s6-rc-compile: tracing: identifier user was already declared with type bundle s6-rc-compile: tracing: from legacy-services: adding identifier base of type unknown s6-rc-compile: tracing: identifier base was already declared with type bundle s6-rc-compile: tracing: dependency from legacy-services to user (126) s6-rc-compile: tracing: dependency from legacy-services to base (137) s6-rc-compile: tracing: dependency from legacy-services to s6rc-oneshot-runner (0) s6-rc-compile: info: parsing /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources/top s6-rc-compile: info: top has type bundle s6-rc-compile: tracing: from /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources: adding identifier top of type bundle s6-rc-compile: tracing: from top: adding identifier user2 of type unknown s6-rc-compile: tracing: identifier user2 was already declared with type bundle s6-rc-compile: tracing: from top: adding identifier user of type unknown s6-rc-compile: tracing: identifier user was already declared with type bundle s6-rc-compile: tracing: from top: adding identifier legacy-services of type unknown s6-rc-compile: tracing: identifier legacy-services was already declared with type oneshot s6-rc-compile: tracing: from top: adding identifier base of type unknown s6-rc-compile: tracing: identifier base was already declared with type bundle s6-rc-compile: info: making bundles for pipelines s6-rc-compile: info: resolving bundle names s6-rc-compile: info: converting bundle array s6-rc-compile: info: resolving service names s6-rc-compile: tracing: nginx depends on longrun php-fpm (3) s6-rc-compile: tracing: php-fpm depends on oneshot 50-laravel-automations (7) s6-rc-compile: tracing: 0-container-info depends on longrun s6rc-oneshot-runner (0) s6-rc-compile: tracing: 1-debug-mode depends on oneshot 0-container-info (4) s6-rc-compile: tracing: 1-debug-mode depends on longrun s6rc-oneshot-runner (0) s6-rc-compile: tracing: 10-init-webserver-config depends on oneshot 1-debug-mode (5) s6-rc-compile: tracing: 10-init-webserver-config depends on longrun s6rc-oneshot-runner (0) s6-rc-compile: tracing: 50-laravel-automations depends on oneshot 10-init-webserver-config (6) s6-rc-compile: tracing: 50-laravel-automations depends on longrun s6rc-oneshot-runner (0) s6-rc-compile: tracing: fix-attrs depends on longrun s6rc-oneshot-runner (0) s6-rc-compile: tracing: legacy-cont-init depends on oneshot fix-attrs (8) s6-rc-compile: tracing: legacy-cont-init depends on longrun s6rc-oneshot-runner (0) s6-rc-compile: tracing: legacy-services depends on bundle user s6-rc-compile: tracing: legacy-services depends on bundle base s6-rc-compile: tracing: legacy-services depends on longrun s6rc-oneshot-runner (0) s6-rc-compile: info: converting service dependency array s6-rc-compile: info: checking database correctness s6-rc-compile: info: writing compiled information to /run/s6/db s6-rc-compile: info: writing /run/s6/db/n s6-rc-compile: info: writing /run/s6/db/resolve.cdb s6-rc-compile: info: writing /run/s6/db/db s6-rc-compile: info: writing /run/s6/db/servicedirs s6-rc: info: bringing selected services up s6-rc: info: service s6rc-oneshot-runner: starting s6-rc: info: service s6rc-oneshot-runner successfully started s6-rc: info: service fix-attrs: starting s6-rc: info: service 0-container-info: starting s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service fix-attrs successfully started -------------------------------------------------------------------- ____ ____ _ _ _ _ / ___| ___ _ ____ _____ _ __ / ___|(_) __| | ___ | | | |_ __ \___ \ / _ \ __\ \ / / _ \ __| \___ \| |/ _` |/ _ \ | | | | _ \ ___) | __/ | \ V / __/ | ___) | | (_| | __/ | |_| | |_) | |____/ \___|_| \_/ \___|_| |____/|_|\__,_|\___| \___/| .__/ |_| Brought to you by serversideup.net -------------------------------------------------------------------- s6-rc: info: service legacy-cont-init: starting s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service legacy-cont-init successfully started πŸ™Œ To support Server Side Up projects visit: https://serversideup.net/sponsor ------------------------------------- ℹ️ Container Information ------------------------------------- Docker user: www-data Docker uid: 33 Docker gid: 33 OPcache: ❌ Disabled πŸ‘‰ [NOTICE]: Improve PHP performance by setting PHP_OPCACHE_ENABLE=1 (recommended for production). s6-rc: info: service 0-container-info successfully started s6-rc: info: service 1-debug-mode: starting s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service 1-debug-mode successfully started s6-rc: info: service 10-init-webserver-config: starting s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s (init-webserver-config): Processing /etc/nginx/nginx.conf.template β†’ /etc/nginx/nginx.conf... (init-webserver-config): Processing /etc/nginx/site-opts.d/http.conf.template β†’ /etc/nginx/site-opts.d/http.conf... (init-webserver-config): Processing /etc/nginx/site-opts.d/https.conf.template β†’ /etc/nginx/site-opts.d/https.conf... ℹ️ NOTICE (init-webserver-config): Enabling NGINX site with SSL "off"... s6-rc: info: service 10-init-webserver-config successfully started s6-rc: info: service 50-laravel-automations: starting s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service 50-laravel-automations successfully started s6-rc: info: service php-fpm: starting [11-Jul-2024 22:15:29] NOTICE: fpm is running, pid 122 [11-Jul-2024 22:15:29] NOTICE: ready to handle connections 127.0.0.1 - 11/Jul/2024:22:15:29 +0000 "GET /status" 200 s6-rc: info: service php-fpm successfully started s6-rc: info: service nginx: starting 127.0.0.1 - 11/Jul/2024:22:15:29 +0000 "GET /ping" 200 βœ… NGINX + PHP-FPM is running correctly. s6-rc: info: service nginx successfully started s6-rc: info: service legacy-services: starting s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service legacy-services successfully started #################### # CTRL + C Pressed #################### s6-rc: info: bringing selected services down s6-rc: info: service legacy-services: stopping s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service legacy-services successfully stopped s6-rc: info: service legacy-cont-init: stopping s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service nginx: stopping s6-rc: info: service legacy-cont-init successfully stopped s6-rc: info: service fix-attrs: stopping s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service fix-attrs successfully stopped s6-rc: info: service nginx successfully stopped s6-rc: info: service php-fpm: stopping [11-Jul-2024 22:15:30] NOTICE: Terminating ... [11-Jul-2024 22:15:30] NOTICE: exiting, bye-bye! s6-rc: info: service php-fpm successfully stopped s6-rc: info: service 50-laravel-automations: stopping s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service 50-laravel-automations successfully stopped s6-rc: info: service 10-init-webserver-config: stopping s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service 10-init-webserver-config successfully stopped s6-rc: info: service 1-debug-mode: stopping s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service 1-debug-mode successfully stopped s6-rc: info: service 0-container-info: stopping s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service 0-container-info successfully stopped s6-rc: info: service s6rc-oneshot-runner: stopping s6-rc: info: service s6rc-oneshot-runner successfully stopped ```

> What happens if you start the container without defining S6_KILL_GRACETIME, but with ENV S6_KILL_FINISH_MAXTIME=1 instead?

Command:

docker run --rm -e S6_KILL_FINISH_MAXTIME=1 -e S6_VERBOSITY=5 serversideup/php:beta-8.3-fpm-nginx

Results:

Output:

S6_KILL_FINISH_MAXTIME=1 Results ```txt #################### # Start #################### s6-rc-compile: tracing: from s6-rc-compile internals: adding identifier s6rc-oneshot-runner of type longrun s6-rc-compile: tracing: from s6-rc-compile internals: adding identifier s6rc-fdholder of type longrun s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/0-container-info s6-rc-compile: info: 0-container-info has type oneshot s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier 0-container-info of type oneshot s6-rc-compile: tracing: dependency from 0-container-info to s6rc-oneshot-runner (0) s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/1-debug-mode s6-rc-compile: info: 1-debug-mode has type oneshot s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier 1-debug-mode of type oneshot s6-rc-compile: tracing: from 1-debug-mode: adding identifier 0-container-info of type unknown s6-rc-compile: tracing: identifier 0-container-info was already declared with type oneshot s6-rc-compile: tracing: dependency from 1-debug-mode to 0-container-info (34) s6-rc-compile: tracing: dependency from 1-debug-mode to s6rc-oneshot-runner (0) s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/10-init-webserver-config s6-rc-compile: info: 10-init-webserver-config has type oneshot s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier 10-init-webserver-config of type oneshot s6-rc-compile: tracing: from 10-init-webserver-config: adding identifier 1-debug-mode of type unknown s6-rc-compile: tracing: identifier 1-debug-mode was already declared with type oneshot s6-rc-compile: tracing: dependency from 10-init-webserver-config to 1-debug-mode (51) s6-rc-compile: tracing: dependency from 10-init-webserver-config to s6rc-oneshot-runner (0) s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/50-laravel-automations s6-rc-compile: info: 50-laravel-automations has type oneshot s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier 50-laravel-automations of type oneshot s6-rc-compile: tracing: from 50-laravel-automations: adding identifier 10-init-webserver-config of type unknown s6-rc-compile: tracing: identifier 10-init-webserver-config was already declared with type oneshot s6-rc-compile: tracing: dependency from 50-laravel-automations to 10-init-webserver-config (64) s6-rc-compile: tracing: dependency from 50-laravel-automations to s6rc-oneshot-runner (0) s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/nginx s6-rc-compile: info: nginx has type longrun s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier nginx of type longrun s6-rc-compile: tracing: from nginx: adding identifier php-fpm of type unknown s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/php-fpm s6-rc-compile: info: php-fpm has type longrun s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier php-fpm of type longrun s6-rc-compile: tracing: previously encountered identifier php-fpm now has type longrun s6-rc-compile: tracing: from php-fpm: adding identifier 50-laravel-automations of type unknown s6-rc-compile: tracing: identifier 50-laravel-automations was already declared with type oneshot s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/user s6-rc-compile: info: user has type bundle s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier user of type bundle s6-rc-compile: tracing: from user: adding identifier php-fpm of type unknown s6-rc-compile: tracing: identifier php-fpm was already declared with type longrun s6-rc-compile: tracing: from user: adding identifier nginx of type unknown s6-rc-compile: tracing: identifier nginx was already declared with type longrun s6-rc-compile: tracing: from user: adding identifier 0-container-info of type unknown s6-rc-compile: tracing: identifier 0-container-info was already declared with type oneshot s6-rc-compile: tracing: from user: adding identifier 1-debug-mode of type unknown s6-rc-compile: tracing: identifier 1-debug-mode was already declared with type oneshot s6-rc-compile: tracing: from user: adding identifier 50-laravel-automations of type unknown s6-rc-compile: tracing: identifier 50-laravel-automations was already declared with type oneshot s6-rc-compile: tracing: from user: adding identifier 10-init-webserver-config of type unknown s6-rc-compile: tracing: identifier 10-init-webserver-config was already declared with type oneshot s6-rc-compile: info: parsing /etc/s6-overlay/s6-rc.d/user2 s6-rc-compile: info: user2 has type bundle s6-rc-compile: tracing: from /etc/s6-overlay/s6-rc.d: adding identifier user2 of type bundle s6-rc-compile: info: parsing /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources/base s6-rc-compile: info: base has type bundle s6-rc-compile: tracing: from /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources: adding identifier base of type bundle s6-rc-compile: tracing: from base: adding identifier fix-attrs of type unknown s6-rc-compile: tracing: from base: adding identifier legacy-cont-init of type unknown s6-rc-compile: info: parsing /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources/fix-attrs s6-rc-compile: info: fix-attrs has type oneshot s6-rc-compile: tracing: from /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources: adding identifier fix-attrs of type oneshot s6-rc-compile: tracing: previously encountered identifier fix-attrs now has type oneshot s6-rc-compile: tracing: dependency from fix-attrs to s6rc-oneshot-runner (0) s6-rc-compile: info: parsing /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources/legacy-cont-init s6-rc-compile: info: legacy-cont-init has type oneshot s6-rc-compile: tracing: from /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources: adding identifier legacy-cont-init of type oneshot s6-rc-compile: tracing: previously encountered identifier legacy-cont-init now has type oneshot s6-rc-compile: tracing: from legacy-cont-init: adding identifier fix-attrs of type unknown s6-rc-compile: tracing: identifier fix-attrs was already declared with type oneshot s6-rc-compile: tracing: dependency from legacy-cont-init to fix-attrs (142) s6-rc-compile: tracing: dependency from legacy-cont-init to s6rc-oneshot-runner (0) s6-rc-compile: info: parsing /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources/legacy-services s6-rc-compile: info: legacy-services has type oneshot s6-rc-compile: tracing: from /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources: adding identifier legacy-services of type oneshot s6-rc-compile: tracing: from legacy-services: adding identifier user of type unknown s6-rc-compile: tracing: identifier user was already declared with type bundle s6-rc-compile: tracing: from legacy-services: adding identifier base of type unknown s6-rc-compile: tracing: identifier base was already declared with type bundle s6-rc-compile: tracing: dependency from legacy-services to user (126) s6-rc-compile: tracing: dependency from legacy-services to base (137) s6-rc-compile: tracing: dependency from legacy-services to s6rc-oneshot-runner (0) s6-rc-compile: info: parsing /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources/top s6-rc-compile: info: top has type bundle s6-rc-compile: tracing: from /package/admin/s6-overlay-3.1.6.2/etc/s6-rc/sources: adding identifier top of type bundle s6-rc-compile: tracing: from top: adding identifier user2 of type unknown s6-rc-compile: tracing: identifier user2 was already declared with type bundle s6-rc-compile: tracing: from top: adding identifier user of type unknown s6-rc-compile: tracing: identifier user was already declared with type bundle s6-rc-compile: tracing: from top: adding identifier legacy-services of type unknown s6-rc-compile: tracing: identifier legacy-services was already declared with type oneshot s6-rc-compile: tracing: from top: adding identifier base of type unknown s6-rc-compile: tracing: identifier base was already declared with type bundle s6-rc-compile: info: making bundles for pipelines s6-rc-compile: info: resolving bundle names s6-rc-compile: info: converting bundle array s6-rc-compile: info: resolving service names s6-rc-compile: tracing: nginx depends on longrun php-fpm (3) s6-rc-compile: tracing: php-fpm depends on oneshot 50-laravel-automations (7) s6-rc-compile: tracing: 0-container-info depends on longrun s6rc-oneshot-runner (0) s6-rc-compile: tracing: 1-debug-mode depends on oneshot 0-container-info (4) s6-rc-compile: tracing: 1-debug-mode depends on longrun s6rc-oneshot-runner (0) s6-rc-compile: tracing: 10-init-webserver-config depends on oneshot 1-debug-mode (5) s6-rc-compile: tracing: 10-init-webserver-config depends on longrun s6rc-oneshot-runner (0) s6-rc-compile: tracing: 50-laravel-automations depends on oneshot 10-init-webserver-config (6) s6-rc-compile: tracing: 50-laravel-automations depends on longrun s6rc-oneshot-runner (0) s6-rc-compile: tracing: fix-attrs depends on longrun s6rc-oneshot-runner (0) s6-rc-compile: tracing: legacy-cont-init depends on oneshot fix-attrs (8) s6-rc-compile: tracing: legacy-cont-init depends on longrun s6rc-oneshot-runner (0) s6-rc-compile: tracing: legacy-services depends on bundle user s6-rc-compile: tracing: legacy-services depends on bundle base s6-rc-compile: tracing: legacy-services depends on longrun s6rc-oneshot-runner (0) s6-rc-compile: info: converting service dependency array s6-rc-compile: info: checking database correctness s6-rc-compile: info: writing compiled information to /run/s6/db s6-rc-compile: info: writing /run/s6/db/n s6-rc-compile: info: writing /run/s6/db/resolve.cdb s6-rc-compile: info: writing /run/s6/db/db s6-rc-compile: info: writing /run/s6/db/servicedirs s6-rc: info: bringing selected services up s6-rc: info: service s6rc-oneshot-runner: starting s6-rc: info: service s6rc-oneshot-runner successfully started s6-rc: info: service fix-attrs: starting s6-rc: info: service 0-container-info: starting s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s -------------------------------------------------------------------- ____ ____ _ _ _ _ / ___| ___ _ ____ _____ _ __ / ___|(_) __| | ___ | | | |_ __ \___ \ / _ \ __\ \ / / _ \ __| \___ \| |/ _` |/ _ \ | | | | _ \ ___) | __/ | \ V / __/ | ___) | | (_| | __/ | |_| | |_) | |____/ \___|_| \_/ \___|_| |____/|_|\__,_|\___| \___/| .__/ |_| Brought to you by serversideup.net -------------------------------------------------------------------- s6-rc: info: service fix-attrs successfully started s6-rc: info: service legacy-cont-init: starting s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service legacy-cont-init successfully started πŸ™Œ To support Server Side Up projects visit: https://serversideup.net/sponsor ------------------------------------- ℹ️ Container Information ------------------------------------- Docker user: www-data Docker uid: 33 Docker gid: 33 OPcache: ❌ Disabled πŸ‘‰ [NOTICE]: Improve PHP performance by setting PHP_OPCACHE_ENABLE=1 (recommended for production). s6-rc: info: service 0-container-info successfully started s6-rc: info: service 1-debug-mode: starting s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service 1-debug-mode successfully started s6-rc: info: service 10-init-webserver-config: starting s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s (init-webserver-config): Processing /etc/nginx/nginx.conf.template β†’ /etc/nginx/nginx.conf... (init-webserver-config): Processing /etc/nginx/site-opts.d/http.conf.template β†’ /etc/nginx/site-opts.d/http.conf... (init-webserver-config): Processing /etc/nginx/site-opts.d/https.conf.template β†’ /etc/nginx/site-opts.d/https.conf... ℹ️ NOTICE (init-webserver-config): Enabling NGINX site with SSL "off"... s6-rc: info: service 10-init-webserver-config successfully started s6-rc: info: service 50-laravel-automations: starting s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service 50-laravel-automations successfully started s6-rc: info: service php-fpm: starting [11-Jul-2024 22:21:11] NOTICE: fpm is running, pid 122 [11-Jul-2024 22:21:11] NOTICE: ready to handle connections 127.0.0.1 - 11/Jul/2024:22:21:11 +0000 "GET /status" 200 s6-rc: info: service php-fpm successfully started s6-rc: info: service nginx: starting 127.0.0.1 - 11/Jul/2024:22:21:11 +0000 "GET /ping" 200 βœ… NGINX + PHP-FPM is running correctly. s6-rc: info: service nginx successfully started s6-rc: info: service legacy-services: starting s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service legacy-services successfully started #################### # CTRL + C Pressed #################### s6-rc: info: bringing selected services down s6-rc: info: service legacy-services: stopping s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service legacy-services successfully stopped s6-rc: info: service legacy-cont-init: stopping s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service nginx: stopping s6-rc: info: service legacy-cont-init successfully stopped s6-rc: info: service fix-attrs: stopping s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service fix-attrs successfully stopped s6-rc: info: service nginx successfully stopped s6-rc: info: service php-fpm: stopping [11-Jul-2024 22:21:12] NOTICE: Terminating ... [11-Jul-2024 22:21:12] NOTICE: exiting, bye-bye! s6-rc: info: service php-fpm successfully stopped s6-rc: info: service 50-laravel-automations: stopping s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service 50-laravel-automations successfully stopped s6-rc: info: service 10-init-webserver-config: stopping s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service 10-init-webserver-config successfully stopped s6-rc: info: service 1-debug-mode: stopping s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service 1-debug-mode successfully stopped s6-rc: info: service 0-container-info: stopping s6-ipcclient: info: s6-ipcclient: connected to /run/s6-rc/servicedirs/s6rc-oneshot-runner/s s6-rc: info: service 0-container-info successfully stopped s6-rc: info: service s6rc-oneshot-runner: stopping s6-rc: info: service s6rc-oneshot-runner successfully stopped ```

> Where and how is your service database in /etc/s6-overlay/s6-rc.d, in particular the user bundle, constructed?

Don't kill me on this one πŸ˜ƒ

I had a very special use case for my project where I needed my entrypoint scripts to run in non-S6 variations AND s6-variations.

My solution was creating a script that I call at build time (docker-php-serversideup-s6-init) that copies my basic entrypoint scripts and puts them into the S6 Overlay structure as one-shot scripts. This allows me to keep a single source of truth in my repo.

To Inspect My Images

If you're interested in exploring the structure, you can inspect it yourself if you'd like:

docker run --rm --entrypoint='' --workdir=/etc/s6-overlay --user root -it serversideup/php:beta-8.3-fpm-nginx bash

(In the command above, I switch you to the root user since the containers are unprivileged by default. Since S6 wants to start FPM and there is a weird config FPM needs to run as root, I just disable S6 from running with setting the entrypoint to null, but you can browse around easily)

Tree of /etc/s6-overlay

/etc/s6-overlay/
|-- s6-rc.d
|   |-- 0-container-info
|   |   |-- type
|   |   `-- up
|   |-- 1-debug-mode
|   |   |-- dependencies
|   |   |-- type
|   |   `-- up
|   |-- 10-init-webserver-config
|   |   |-- dependencies
|   |   |-- type
|   |   `-- up
|   |-- 50-laravel-automations
|   |   |-- dependencies
|   |   |-- type
|   |   `-- up
|   |-- nginx
|   |   |-- data
|   |   |   `-- check
|   |   |-- dependencies
|   |   |-- notification-fd
|   |   |-- run
|   |   `-- type
|   |-- php-fpm
|   |   |-- data
|   |   |   `-- check
|   |   |-- dependencies
|   |   |-- notification-fd
|   |   |-- run
|   |   `-- type
|   |-- user
|   |   |-- contents.d
|   |   |   |-- 0-container-info
|   |   |   |-- 1-debug-mode
|   |   |   |-- 10-init-webserver-config
|   |   |   |-- 50-laravel-automations
|   |   |   |-- nginx
|   |   |   `-- php-fpm
|   |   `-- type
|   `-- user2
|       |-- contents.d
|       `-- type
`-- scripts
    |-- 0-container-info -> /etc/entrypoint.d/0-container-info.sh
    |-- 1-debug-mode -> /etc/entrypoint.d/1-debug-mode.sh
    |-- 10-init-webserver-config -> /etc/entrypoint.d/10-init-webserver-config.sh
    `-- 50-laravel-automations -> /etc/entrypoint.d/50-laravel-automations.sh
skarnet commented 1 month ago

OK, so here's what's happening:

jaydrogers commented 1 month ago

> I can't run containers at the moment; I should be able to do so over the week-end and then tell you more

No problem! I greatly appreciate your efforts to help with a limited toolset available.

> So one of the mysteries is: why are you experiencing a ~5 second wait instead of a 3 second one? Are you using the latest version of s6-overlay?

Yes, I am using v3.2.0.0.

The S6 env settings I have set in the container are:

S6_BEHAVIOUR_IF_STAGE2_FAILS=2
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0
S6_KEEP_ENV=1
S6_VERBOSITY=1

> Do you get the same container exit code when you stop the container with docker stop instead of Ctrl-C?

So this is where it gets more interesting. I was going to mention that most times it takes 10 seconds for the container to exit (specifically with Docker Compose).

With docker stop

Screenshot 2024-07-12 at 07 58 13@2x

Command I'm running

docker run --rm --name=s6-php serversideup/php:beta-8.3-fpm-nginx
docker stop s6-php
skarnet commented 1 month ago

I am getting very weird results.

With my version of Docker - Docker version 27.0.3, build 7d4bcd863a4c863e650eed02a550dfeb98560b83 - when I ^C the docker run invocation, I get context canceled and I cannot see the outputs. I'll keep investigating what's happening there, but apparently they changed the behaviour of docker run. I can say, however, that s6-svscan correctly gets a SIGINT, so everything is working properly on that front and it's just the exit code that needs to be fixed (but the change of behaviour interferes with my ability to debug).

However, when I docker stop, s6-svscan is getting a SIGQUIT. Is there something in your scripts or various configurations that changes the STOPSIGNAL for Docker? I can see no STOPSIGNAL directive in the Dockerfile I run (the php-fpm one with s6-overlay), so what I should be seeing is a SIGTERM, which would work as expected. A SIGQUIT will not work, so please check that nothing is messing with the STOPSIGNAL.

jaydrogers commented 1 month ago

Thanks for researching this more!

Is there something in your scripts or various configurations that changes the STOPSIGNAL for Docker?

Since I base my images off of PHP's official images, they do have a line to set the STOPSIGNAL: https://github.com/docker-library/php/blob/f5a51b67da6ae457bcf89238f5cf0bf73444a760/8.3/bookworm/fpm/Dockerfile#L270-L272

Should I change this in my fpm-nginx (with S6 Overlay) image since I'm using a totally different init system compared to the official PHP image?

I can set STOPSIGNAL in the Dockerfile: https://docs.docker.com/reference/dockerfile/#stopsignal

skarnet commented 1 month ago

Yes. The PHP-FPM Dockerfile is meant for a container where the php-fpm process itself runs as process 1, alone in the container, so they adapt the stop signal to accommodate php-fpm. But when you're running a container with an init system (s6-overlay being only one of many), then you should use the default stop signal, i.e. SIGTERM. If you do so, you'll be able to get the expected results from docker stop.

jaydrogers commented 1 month ago

That worked! Wow, what a stack of code to dive into.

I greatly appreciate your help on this. I learned a lot. Thank you for putting together this amazing project and maintaining it πŸ™Œ

skarnet commented 1 month ago

np, glad you could make it work!

jaydrogers commented 1 week ago

I don't mean to wake up an old thread, but I figured keeping this organized on a single thread would be helpful.

Problem

Screenshot 2024-08-08 at 11 00 18@2x

Background

I found this article explaining their solution:

Screenshot 2024-08-08 at 10 51 36@2x

The official PHP images even highlight this in their source code:

https://github.com/docker-library/php/blob/b9433900bb5e6d14658ea96afc2270e58a13ebab/8.3/alpine3.19/fpm/Dockerfile#L254-L256

My question

Thanks so much for your help! I hope the Olympics have been a good thing to have in town than a burden. πŸ‡«πŸ‡·

skarnet commented 1 week ago
jaydrogers commented 1 week ago

But if you're running php-fpm as a regular supervised service, add a down-signal file containing SIGQUIT in the php-fpm service definition directory.

I think this is the ticket! Thanks for pointing this out, I was not aware of this option. I do have some issues trying to get this to work though.

My S6 service structure

Here is a link to my S6 service structure: https://github.com/serversideup/docker-php/tree/main/src/s6/etc/s6-overlay/s6-rc.d/php-fpm

My confusion

When I did a Google search for "down-signal s6", it brought up this page for s6-svc:

https://skarnet.org/software/s6/s6-svc.html

What I tried

I attempted the following steps:

I created a .down-signal file at /etc/s6-overlay/s6-rc.d/php-fpm/down-signal

Inside of that file is:

SIGQUIT

I updated the run script to use s6-svc

#!/command/execlineb -P
with-contenv
s6-notifyoncheck -d
s6-svc -d /etc/s6-overlay/s6-rc.d/php-fpm
/usr/local/sbin/php-fpm --nodaemonize

This fails with:

php-1      | s6-svc: warning: ignoring extra arguments
php-1      | s6-svc: fatal: unable to control /etc/s6-overlay/s6-rc.d/php-fpm/: supervisor not listening

My Question

My gut feeling is I can only use one option of s6-notifyoncheck or s6-svc? I think I previously used s6-notifyoncheck so I can use php-fpm as a dependency in my S6 configuration for NGINX.

Thanks a ton for your help!

skarnet commented 1 week ago

Please don't play sorcerer's apprentice.