I'm trying to deploy a Discord Bot I've written in python to a VM (running Portainer) on my home server. However, I'm running into the issue of having Portainer correctly evaluate the bot token secret. I have defined the secret with the name HU3BOT_DISCORD_TOKEN
, and am using the following compose file:
version: "3.9"
services:
hu3bot:
image: drak3/hu3bot:latest
environment:
- DISCORD_TOKEN=/run/secrets/HU3BOT_DISCORD_TOKEN
- DISCORD_CHANNEL="3d_printing"
- PRINTER_HOST=voron.srv
- CAM_PORT_MAIN=8081
- CAM_PORT_ALT=8080
- MOONRAKER_API_PORT=7125
- WEB_URL='https://fluidd.drak3.io'
secrets:
- HU3BOT_DISCORD_TOKEN
# the secret is a discord bot token
secrets:
HU3BOT_DISCORD_TOKEN:
external: true
Locally, I can run the script making use of a .env
file w/o issue. I can do the same as a local container. However, when I attempt to use the secret I've defined, I cannot get it to be properly evaluated. I've added some print statements to my code, and depending on how i format the DISCORD_TOKEN=/run/secrets/HU3BOT_DISCORD_TOKEN
line, the token will either be evaluated as a Null (None
of type <class 'NoneType'>
) or as a string with the content /run/secrets/HU3BOT_DISCORD_TOKEN
.
I have tried all the following combinations of formatting, but they'll all either be the name of the secret, or Null:
DISCORD_TOKEN=/run/secrets/HU3BOT_DISCORD_TOKEN
DISCORD_TOKEN= /run/secrets/HU3BOT_DISCORD_TOKEN
DISCORD_TOKEN:/run/secrets/HU3BOT_DISCORD_TOKEN
DISCORD_TOKEN: /run/secrets/HU3BOT_DISCORD_TOKEN
"DISCORD_TOKEN=/run/secrets/HU3BOT_DISCORD_TOKEN"
"DISCORD_TOKEN= /run/secrets/HU3BOT_DISCORD_TOKEN"
"DISCORD_TOKEN:/run/secrets/HU3BOT_DISCORD_TOKEN"
"DISCORD_TOKEN: /run/secrets/HU3BOT_DISCORD_TOKEN"
To add insult to injury, I also have a different stack that pulls a webhook from a secret (like this: WATCHTOWER_NOTIFICATION_SLACK_HOOK_URL=/run/secrets/DISCORD_WEBHOOK_WATCHTOWER
) which works fine.
Could the content of the secret have any bearing on this? I'm honestly at a loss to explain this, and would greatly appreciate any help or suggestions.
UPDATE:
For those coming along after me, having a similar issue, thanks to Chris Becke, I've realized I must have been misunderstanding how docker secrets actually work. I previously thought the string /run/secrets/secret_name
could be used as a literal stand in for the secret value itself, and that by passing them in to environment variables, it would be equivalent of just having the raw secret there. This misunderstanding is most likely due to my having only used secrets in compose files using other people's images. I'm guessing they had some kind of code to distinguish between the value being an environment variable and a docker secret path. After adding such code to my bot, the value is evaluated as expected. This was a useful answer for doing this.
CodePudding user response:
Setting an environment variable just sets it to the literal value you provide.
Handling secrets properly entails injecting a script to read the secret into an environment variable. Something like this:
services:
some-service:
image: whatever
entrypoint:
- /bin/sh
- -c
- |
read -r DISCORD_TOKEN < /run/secrets/HU3BOT_DISCORD_TOKEN
exec $$0 "$$@"
command: previous command
You need to look up the containers previous CMD and ENTRYPOINT values and make sure the new flow chains to the old flow. Setting entrypoint
automatically clears any existing CMD
so you need to fully specify that if it existed.