python docker containers

How To Run a Discord Bot With Python Inside a Docker Container

In this post, we’re going to make a simple Discord bot using Python and run it inside a Docker container. Benefit of running Python projects with Docker is that you don’t need to install pip packages on your system. This is because Docker installs all required packages inside the container.

Before we begin with this project, you’ll need to install Docker of course. In my case, I’ll be using WSL2, and I recommend you do so as well. I’m not trying to push my personal preferences on you here, it’s just faster.

Setting up Docker image

Before we get to the coding part, we’ll need to create a couple of files for Docker.

Here is the basic Python project file architecture, we’ll go for here:

  • src folder
    • auth.json
    • main.py
  • docker-compose.yml
  • Dockerfile
  • requirements.txt

To explain, main.py will contain all the Discord bot code and auth.json will contain Discord API access token. This src folder contains all the files for a Discord bot to function. Therefore, by adding them into a Docker container, we basically wrap them into a their own environment.

Next, let’s talk about the Dockerfile file. In here, we’ll add the image configuration, which includes information such as Python version, name of the work directory, which file to copy inside the Docker container, and which commands to run.

Following are the contents of the Dockerfile for our Python project.

FROM python:3.9
WORKDIR /docker-python-dir

COPY ./requirements.txt .
COPY ./src ./src

RUN pip install -r requirements.txt

CMD ["python", "./src/main.py"]

We’ll copy the requirements.txt file and the Python project folder into the container here. To clarify, requirements.txt file contains all names of the third-party Python packages, in our case discord and asyncio. Furthermore, we’ll use this file to install all required packages in the container. Last thing we add in the Dockerfile is the command to run the Python script.

After we’re done with the Dockerfile, we need to build the image. We can do this part in a couple of different ways. One way to do it is with docker build command by stringing together all the necessary arguments.

Another, more optimal, way to go about it, is to create a YAML configuration file (docker-compose.yml), which contains everything we would input into those arguments with the docker build command.

Following code contains the contents of this configuration file for our project.

services:
  app:
    build: .
    container_name: docker-python-container
    command: python ./src/main.py
    ports:
      - 80:80
    volumes:
      - .:/docker-python-dir

We can then use docker compose up to build the Docker Python container and run it.

Coding a simple Discord bot

For demonstration purposes, I made a simple Discord bot, which responds only to one command with a message.

import os
import json
import asyncio
import discord
from discord.ext import commands

ROOT = os.path.dirname(__file__)

def get_token(token_name):
    with open(os.path.join(ROOT, 'auth.json'), 'r') as auth_file:
        auth_data = json.load(auth_file)
        token = auth_data[token_name]
        return token

class TestCog(commands.Cog):

    def __init__(self, bot):
        self.bot = bot
    
    @commands.hybrid_command(name='ping')
    async def ping(self, ctx):
        await ctx.send('This bot runs inside a docker container! PONG')

intents = discord.Intents.default()
intents.message_content = True

bot = commands.Bot(
    command_prefix=commands.when_mentioned_or('!'),
    description='This bot runs inside a docker container.',
    intents=intents
)

@bot.event
async def on_ready():
    print(f'Logged in as {bot.user} (ID: {bot.user.id})')
    print('------')
    await bot.tree.sync()

async def main():
    async with bot:
        await bot.add_cog(TestCog(bot))
        await bot.start(get_token('discord-token'))

asyncio.run(main())
Discord bot respond to command

Editing Python code inside a Docker container

You’ll probably want to edit your Python code at some point, which means you’ll also need to access it inside the container.

If you’re using VS Code, like I do, you’ll need to install the following extensions:

  • Docker
  • Dev Containers

When you finish this step, you’ll need to click at the very bottom left corner and select attach to running container option and select the container you created for this project.

editing python code inside an existing docker container

Make sure you’re using the Python version you specified in the Dockerfile as well. Once you have all this set up, you’ll need to download the Python extension for this container. This will allow you to use intellisense, and enable your code editor to see the libraries it installed inside the container.

Conclusion

To conclude, we made a simple Discord bot and configured a Python environment inside a Docker container to run it. I learned a lot while working on this project and I hope it proves itself helpful to you as well.

Share this article:

Related posts

Discussion(0)