I’m having trouble getting my Python Discord bot to work on Google Cloud Run. The bot runs fine in a Docker container locally, and I’ve successfully pushed the image to Google Container Registry. However, when launching a Cloud Run instance, the container fails to start.
Here’s my Dockerfile:
FROM python:3.9
WORKDIR /app
COPY requirements.txt .
RUN pip3 install -r requirements.txt
COPY . .
ENV PORT 8080
ENV HOST 0.0.0.0
CMD [ "python3", "bot.py"]
The error message is as follows:
Container failed to start. Failed to start and then listen on the port defined by the PORT environment variable.
Oddly, while the logs show that the bot logs in successfully, it crashes almost immediately after. Below is the simplified version of my bot code:
import os
import discord
TOKEN = os.environ['BOT_TOKEN']
client = discord.Client()
@client.event
async def on_ready():
print(f'Logged in as {client.user}')
@client.event
async def on_message(msg):
if msg.author == client.user:
return
if msg.content.lower() == 'hi':
await msg.channel.send(f'Hey {msg.author.name}!')
elif msg.content.lower() == 'bye':
await msg.channel.send(f'Farewell {msg.author.name}!')
client.run(TOKEN)
I’ve ensured the environment variable is properly set in Cloud Run. Can anyone suggest what might be causing this container start-up failure?
The issue you’re encountering is likely due to Cloud Run’s specific requirements for container applications. Your bot isn’t explicitly listening on the port specified by the PORT environment variable, which Cloud Run expects.
To resolve this, you’ll need to modify your bot.py to include an HTTP server that listens on the specified port. Here’s a basic implementation using aiohttp:
import os
from aiohttp import web
import discord
# Your existing bot code here
async def health_check(request):
return web.Response(text='OK')
app = web.Application()
app.router.add_get('/', health_check)
if __name__ == '__main__':
web.run_app(app, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))
client.run(TOKEN)
This modification should allow your container to start successfully on Cloud Run while still running your Discord bot. Remember to add aiohttp to your requirements.txt file.
hey mike, sounds like ur bot’s not listening on the right port. cloud run expects ur app to listen on $PORT. try adding this before client.run(TOKEN):
import asyncio
loop = asyncio.get_event_loop()
loop.create_task(client.start(TOKEN))
loop.run_forever()
that shud fix it. lmk if u need more help!
I have dealt with similar issues when deploying Discord bots on cloud platforms. In my experience, the error arises because Cloud Run expects an application to actively listen on the designated port, and a Discord bot that only connects to Discord without establishing a web server will trigger a startup failure. One solution that worked for me was to start a simple HTTP server alongside the bot. You can import the threading module and define a function that uses Python’s http.server to create a basic web server listening on the port provided by the PORT environment variable. Then, before calling client.run(TOKEN), you initiate this web server on a separate daemon thread. This method satisfied Cloud Run’s requirement for an active listening port while allowing your bot to function normally. It is a straightforward workaround that integrates well into your existing application without major modifications.