Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable service from cont-init.d #394

Closed
felipecrs opened this issue Feb 2, 2022 · 16 comments
Closed

Disable service from cont-init.d #394

felipecrs opened this issue Feb 2, 2022 · 16 comments

Comments

@felipecrs
Copy link

felipecrs commented Feb 2, 2022

I have two services, but depending on how the container is started (i.e. the environment variables), I don't need the second service.

This is how I'm planning to do as a work around:

/etc/cont-init.d/set_services.sh:

#!/bin/bash

# Ensure folder is not there from last container execution
rm -rf /etc/services.d/asterisk_mbox

if [[ -n "${ASTERISK_MAILBOX_ENABLED}" ]]; then
  cp -rf /usr/share/asterisk_mbox_service /etc/services.d/asterisk_mbox
fi

Then, instead of defining the service inside of /etc/services.d/asterisk_mbox in the Dockerfile, I define them at /usr/share/asterisk_mbox_service.

But it has some drawbacks, for example this only works if I start the container as root.

Any ideas, suggestions?

Refs TECH7Fox/asterisk-hass-addons#77 (comment)
Refs #86

@TECH7Fox
Copy link

TECH7Fox commented Feb 2, 2022

Now it checks if it should start in the service itself.

if bashio::var.true "$(bashio::config 'mailbox')"; then
    bashio::log.info "Starting Asterisk Mailbox"

    ## Run Asterisk_mbox
    exec /usr/local/bin/asterisk-mbox-server --cfg /etc/asterisk/asterisk_mbox.ini -U asterisk
fi

It does work, but is there a better way to do this?

@felipecrs
Copy link
Author

@TECH7Fox, yes, that's one option indeed. Just to better illustrate with the first example:

/etc/services.d/asterisk_mbox/run:

#!/bin/bash

if [[ -z "${ASTERISK_MAILBOX_ENABLED}" ]]; then
  exit 0
fi

echo "Starting Asterisk Mailbox"

exec /usr/local/bin/asterisk-mbox-server --cfg /etc/asterisk/asterisk_mbox.ini -U asterisk

I wonder what's the preferred approach, or if there is even a third.

@skarnet
Copy link
Contributor

skarnet commented Feb 3, 2022

The first approach is the best one. Testing inside the run script and exiting it is not good, because when the run script exits, it will be restarted one second later, so s6 will loop every second attempting to start a service that exits immediately.

To prevent that, however, you can tell the supervisor to stop restarting the service. So instead of just exit 0, you would do

s6-svc -O .
exit 0

which is code for "when I exit, do not restart me".

@felipecrs
Copy link
Author

felipecrs commented Feb 3, 2022

That's awesome. Thanks for the tip! We are using this, therefore:

#!/bin/bash

if [[ -z "${ASTERISK_MAILBOX_ENABLED}" ]]; then
  s6-svc -O .
  exit 0
fi

echo "Starting Asterisk Mailbox"

exec /usr/local/bin/asterisk-mbox-server --cfg /etc/asterisk/asterisk_mbox.ini -U asterisk

Do you still think there would be benefits of using the first approach?

@skarnet
Copy link
Contributor

skarnet commented Feb 3, 2022

Conceptually, the first approach is: "this service is not even in the list of supervised services", whereas the s6-svc one is "this service is in the list of supervised services, but down". So, if you're not planning to run asterisk_mbox during this container run, I'd say that the first approach is conceptually better, and the second one is more suited to dynamic state changes.

In practice, having asterix_mbox in the list of supervised services only means one extra supervisor process, which uses a negligible amount of resources, so it doesn't change anything in a noticeable way.

@felipecrs
Copy link
Author

felipecrs commented Feb 3, 2022

All right. Thank you very much.

Do you think there is anything that can be improved in s6-overlay like an API for disabling services that can be called from cont-init.d to streamline this process?

If not, I'm good and this issue can be closed.

@skarnet
Copy link
Contributor

skarnet commented Feb 3, 2022

cont-init.d and services.d is the legacy system and I'd rather keep it in maintenance mode.

The real, evolutive solution is to convert your services to the s6-rc format. A future version of s6-overlay (don't hold your breath!) will include a way for users to choose exactly what sets of services they want started - but unfortunately that cannot include services declared in cont-init.d or services.d.

@felipecrs
Copy link
Author

That makes sense!

@skarnet skarnet closed this as completed Feb 3, 2022
@felipecrs
Copy link
Author

A future version of s6-overlay (don't hold your breath!) will include a way for users to choose exactly what sets of services they want started

@skarnet I'm just wondering, was this feature implemented?

@skarnet
Copy link
Contributor

skarnet commented Aug 23, 2023

I'm not sure what I was thinking about when I wrote this. You can achieve dynamic service sets today, with the current version of s6-overlay: have a S6_STAGE2_HOOK script that adds services to, or removes services from, the user bundle. That should cover most use cases.

@felipecrs
Copy link
Author

Sounds good, thanks a lot!

@felipecrs
Copy link
Author

@skarnet do you think it would be worth implementing a new approach for this problem?

I'm thinking of something like:

If /etc/s6-overlay/s6-rc.d/<services>/condition exists, executes condition to determine whether the should be added to the supervision tree or not.

If condition exits with code 0, adds to supervision tree. Otherwise, ignore this .

Example implementation:

/etc/s6-overlay/s6-rc.d/sshd/condition:

#!/command/with-contenv bash

test "${SSHD_ENABLED}" == true

The reason why I propose this over S6_STAGE2_HOOK is because that approach would rely on "central" script for determining the services database, which does not play well when extending from a base image.

For example, let's say I build a base image that ships some optional services preconfigured through a script as S6_STAGE2_HOOK. If users want to change this selection of services, or even condition or more conditional services, they need to duplicate the original script at S6_STAGE2_HOOK and do their modifications -- certainly suboptimal.

@skarnet
Copy link
Contributor

skarnet commented Mar 11, 2024

If I was building a base image and I wanted to let users preconfigure some services, I would write a generic S6_STAGE2_HOOK that reads some user-modifiable configuration, such as the one you suggested, and performs the change.

In other words: there is no need for s6-overlay to do anything, because it is already possible via clever hook crafting. 😉

@felipecrs
Copy link
Author

felipecrs commented Mar 11, 2024

Oh sorry, I should have mentioned that I did exactly as you suggested here:

https://github.com/felipecrs/jenkins-agent-dind/pull/114/files#diff-e0a11c411e0ab57c483ae5c75941ef613c4db9be0c98bc778e5ea93b9ac5e15c

(which can also be a reference for other people interested)

But my point was that it sounds generic and useful enough to make it a feature of s6-overlay. No problem if you don't think it's a good idea or needed though. Just a suggestion. :)

@skarnet
Copy link
Contributor

skarnet commented Mar 11, 2024

Good on you to have done it, then! 😁

But for s6-overlay, and more generally s6-rc, I think it's more important to guarantee bootability of a container (and so, reproducibility) with a given set of services, and the more dynamism is introduced, the harder it is. Flexibility and reproducibility are directly opposed to each other here, unfortunately, and I'm uncomfortable with moving the cursor more towards flexibility.

@felipecrs
Copy link
Author

Fair enough. Thanks for always promptly replying btw. 🤝

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants