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
Environment variable for Broker URL is prioritized over app settings #4284
Comments
I have added a test to demonstrate the issue: |
I don't see an issue here, many software prioritizes environment variable over conffile when both exist. Things to eventually improve:
|
This is not the current issue: there is no |
@thomas-riccardi is correct. My main concern would be that it seems like your settings are being taken when you explicitly set them, but Celery is "magically" picking up environment variables that you might not even be aware that you have set. The issue I'm raising is a personal issue I guess, where I feel that any explicit setting in your code should take priority over automatic settings (like those from environment variables). I have since realized that prioritizing Environment variables is by design so I have closed my pull request regarding the issue, however I have a few thoughts on mitigating confusion in the future: On the PR adding tests demonstrating this issue ( #4285 ) @georgepsarakis brought up a point that would at least remove the confusion for anybody else in the future.
If your @ant31 's improvements ( #4284 (comment) ) would also be much appreciated. |
may be doc changes worth mention it? |
Sorry for bumping this, but if the |
Multiple broker URLs should be specified with a semicolon. |
I also stumbled on this problem when configuring pytest to use another broker. According to the docs here, we can override the broker and backend specifically for testing purposes. After hours debugging why my changes weren't being picked, I discovered env variables had precedence over any custom settings. In my case, For anyone stumbling on this via pytest fixtures, here's the hack I'm using:
It essentially overwrites the env key if it was set, and resets it to the original during cleanup |
I was very surprised by this behavior because I didn't find any mention of prioritizing ENV variables in the documentation. My use-case is as follows: I need several instances of Celery because I need to connect to multiple VHOSTs (dynamically). So I set the global ENV variable Here is a minimal code sample: import os
from celery import Celery
os.environ["CELERY_BROKER_URL"] = "amqp://aaa:aaa@localhost:5672"
vhost = "bbb"
app = Celery(broker="%s/%s" % (os.environ['CELERY_BROKER_URL'], vhost))
assert app.conf.broker_url == "amqp://aaa:aaa@localhost:5672/bbb"
|
Thank you @illagrenan for this example. My current worker file looks like that import os
from celery import Celery
from django.conf import settings
if not settings.configured:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings") # pragma: no cover
# https://github.com/celery/celery/issues/4284#issuecomment-1067196398
os.environ["CELERY_BROKER_URL"] = os.environ["SOME_ENV_VAR"]
os.environ["CELERY_RESULT_BACKEND"] = os.environ["REDIS_URL"]
app = Celery(
"project_name",
# broker=settings.CELERY_BROKER_URL, # doesn't matter what you set here
)
app.config_from_object("django.conf:settings", namespace="CELERY") I was so confused as to why it doesn't work as
I use |
I'm experiencing the same precedence issues when using Docker secrets, .e.g deploying using With Docker secrets, values are obtained as follows:
With environment variables having higher precedence, Celery uses the following invalid broker URL: As a workaround, I'm manually overriding the Celery env vars with the values read from the secrets, as suggested in #4284 (comment) and #4284 (comment) This was surprising to me - I expected the priority to be something along the lines of (highest to lowest):
As an aside, evaluating the environment variables of a running container shows that the updated values are not exposed. EDIT: turns out that even official Docker images rewrite secrets to environment variables, and Kubernetes supports this out of the box: |
I came here looking for the opposite: a way to configure Celery with env vars. Setting an env var with an absolute path to a config file (#5303) would be fine. Setting an env var per setting is fine, too. I'd keep the behaviour and document it. I don't buy the "celery picks stuff from random forgotten vars in my env" argument. When deploying, environments are supposed to be clean. And using env vars is a common way of overriding stuff. Sure, logging where each value is picked up could be nice, to save people from the issues described in comments above (not knowing an env var is overriding an explicit value). |
I would be happy to review any contributions in this area. |
Checklist
celery -A proj report
in the issue.(if you are not able to do this, then at least specify the Celery
version affected).
master
branch of Celery.Steps to reproduce
Celery version: 4.0.2 (latentcall)
Issue is about the celery python app, which we are currently using with django (not django-celery).
Issue can be seen here: https://github.com/celery/celery/blob/master/celery/app/utils.py#L85-L106
My team had a misunderstanding about Celery settings and environment variables (we thought the celery app would set the config from environment variables automatically using
config_from_object
). We had CELERY_RESULT_BACKEND and CELERY_BROKER_URL set in our environment variables. This worked perfectly for a while, until we started doing operations that relied on the result backend.It took a while to figure out why the broker url was working fine but the backend was not. After some investigation, I realized that the broker url wasn't set at all, and that the call to
broker_url
was actually using the environment variable we had set instead of the app settings.Expected behavior
Celery broker settings should take priority. Currently, even if we had properly configured celery, a stray environment variable could break our application.
Ideally, the broker url would not be read from environment variables at all, at least not at the level in which it is currently read, as this only causes confusion. I am not familiar with why it is implemented this way, but it looks like it is probably a bit of legacy code.
Actual behavior
Celery broker url is read from environment variables before app settings.
The text was updated successfully, but these errors were encountered: