Skip to content

Commit

Permalink
Changes for Docker support (nh-server#832)
Browse files Browse the repository at this point in the history
* Changes for Docker support

This makes a few additions and changes for Kusisu to run inside a Docker
container.

* config.ini and channels.ini are now in data/ instead of the project
  root
* New GitHub Workflow that builds the image and pushes it to Docker Hub
  at https://hub.docker.com/repository/docker/nhserver/kurisu
  There's also commands to pull the image on the server but it's
  disabled for now.
* Uses environment variables to get the commit sha and branch instead of
  calling git, since Kurisu won't be running from a git repository
  inside the container.
* Disables pull when inside a container for the same reason.
* requirements.txt specifies exact versions now. This is useful for
  build caching when built locally, but also prevents unexpected changes
  in these libraries.

* cogs.events: remove unused import

* Push image to ghcr.io instead of Docker Hub

Signed-off-by: Ian Burgwin <[email protected]>
  • Loading branch information
ihaveamac authored Sep 29, 2020
1 parent 778379b commit faf9424
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 33 deletions.
7 changes: 7 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
data
.git
.dockerignore
Dockerfile
config.ini
config.ini.example
dockerbuild.sh
58 changes: 58 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: 'ci'

on:
push:
branches: port

jobs:
main:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-qemu-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
# github username and personal access token
registry: ghcr.io
username: ${{ secrets.CR_USERNAME }}
password: ${{ secrets.CR_PAT }}
- name: Build Docker image
id: docker_build
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
platforms: linux/amd64
push: false
# Can't auto-push with v2 right now...
tags: ghcr.io/nh-server/kurisu:latest
build-args: COMMIT=${{ github.sha }},BRANCH=${{ github.ref }}
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
- name: Push Docker image
run: docker push ghcr.io/nh-server/kurisu:latest
# https://stackoverflow.com/questions/60477061/github-actions-how-to-deploy-to-remote-server-using-ssh/60479844#60479844
# - name: Create SSH key
# run: |
# mkdir -p ~/.ssh/
# chmod 700 ~/.ssh/
# echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
# chmod 600 ~/.ssh/id_rsa
# echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
# shell: bash
# env:
# SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
# SSH_KNOWN_HOSTS: ${{ secrets.SSH_KNOWN_HOSTS }}
# - name: Pull on server
# run: docker-compose pull
# env:
# DOCKER_HOST: ${{ secrets.SSH_HOST }}
# - name: Run on server
# run: docker-compose up -d
# env:
# DOCKER_HOST: ${{ secrets.SSH_HOST }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
*.ini
*.sh
!dockerbuild.sh
*.log
*.json
*.png
Expand Down
15 changes: 15 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM python:3.8.5-slim-buster
LABEL org.opencontainers.image.source https://github.com/nh-server/Kurisu
ENV HOME /home/kurisu
RUN useradd -m -d $HOME -s /bin/sh -u 2849 kurisu
WORKDIR $HOME
COPY ./requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
ENV IS_DOCKER=1
ARG COMMIT="unknown"
ARG BRANCH="unknown"
ENV COMMIT_SHA=${COMMIT}
ENV COMMIT_BRANCH=${BRANCH}
USER kurisu
COPY --chown=2849:2849 . .
CMD ["python3", "kurisu.py"]
15 changes: 8 additions & 7 deletions cogs/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,14 @@ async def channel_spam_check(self, message):
async def on_message(self, message):
if isinstance(message.channel, discord.abc.PrivateChannel):
return
if message.author.name == "GitHub" and message.author.discriminator == "0000":
if message.embeds[0].title.startswith('[Kurisu:port]'):
await self.bot.channels['helpers'].send("Automatically pulling changes!")
call(['git', 'pull'])
await self.bot.channels['helpers'].send("Restarting bot...")
await self.bot.close()
return
if not self.bot.IS_DOCKER:
if message.author.name == "GitHub" and message.author.discriminator == "0000":
if message.embeds[0].title.startswith('[Kurisu:port]'):
await self.bot.channels['helpers'].send("Automatically pulling changes!")
call(['git', 'pull'])
await self.bot.channels['helpers'].send("Restarting bot...")
await self.bot.close()
return
await self.bot.wait_until_all_ready()
if message.author == message.guild.me or await check_staff_id(self, 'Helper', message.author.id) or await self.check_nofilter(message.channel): # don't process messages by the bot or staff or in the helpers channel
return
Expand Down
14 changes: 9 additions & 5 deletions cogs/mod.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,14 @@ async def quit(self, ctx):
@commands.command()
async def pull(self, ctx):
"""Pull new changes from GitHub and restart."""
await ctx.send("Pulling changes...")
call(['git', 'pull'])
await ctx.send("👋 Restarting bot!")
await self.bot.close()
if self.bot.IS_DOCKER:
await ctx.send("Pull isn't used when running from a Docker container!")
return
else:
await ctx.send("Pulling changes...")
call(['git', 'pull'])
await ctx.send("👋 Restarting bot!")
await self.bot.close()

@is_staff("Helper")
@commands.guild_only()
Expand Down Expand Up @@ -580,7 +584,7 @@ async def updatechannel(self, ctx, name, channel: discord.TextChannel):
await ctx.send("Invalid channel name!")
return
self.bot.channel_config['Channels'][name] = str(channel.id)
with open('channels.ini', 'w', encoding='utf-8') as f:
with open('data/channels.ini', 'w', encoding='utf-8') as f:
ctx.bot.channel_config.write(f)
self.bot.channels[name] = channel
await ctx.send(f"Changed {name} channel to {channel.mention} | {channel.id}")
Expand Down
File renamed without changes.
7 changes: 7 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: "3.8"
services:
kurisu:
image: "ghcr.io/nh-server/kurisu"
volumes:
- /opt/kurisudata:/home/kurisu/data
restart: always
2 changes: 2 additions & 0 deletions dockerbuild.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
docker build --build-arg COMMIT=$(git rev-parse HEAD) --build-arg BRANCH=$(git rev-parse --abbrev-ref HEAD) -t ghcr.io/nh-server/kurisu .
40 changes: 24 additions & 16 deletions kurisu.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
from utils.database import ConnectionHolder
from utils.manager import WordFilterManager, InviteFilterManager

IS_DOCKER = os.environ.get('IS_DOCKER', 0)

# sets working directory to bot's folder
dir_path = os.path.dirname(os.path.realpath(__file__))
os.chdir(dir_path)

# Load config
config = ConfigParser()
config.read("config.ini")
config.read("data/config.ini")

database_name = 'data/kurisu.sqlite'

Expand Down Expand Up @@ -68,11 +70,14 @@ async def get_user(self, userid: int):

class Kurisu(commands.Bot):
"""Its him!!."""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.startup = datetime.now()
self.channel_config = ConfigParser()
self.channel_config.read("channels.ini", encoding='utf-8')
self.channel_config.read("data/channels.ini", encoding='utf-8')

self.IS_DOCKER = IS_DOCKER

self.roles = {
'Helpers': None,
Expand Down Expand Up @@ -139,7 +144,6 @@ def __init__(self, *args, **kwargs):
self._is_all_ready = Event(loop=self.loop)

os.makedirs("data", exist_ok=True)
os.makedirs("data/ninupdates", exist_ok=True)

async def get_context(self, message, *, cls=CustomContext):
return await super().get_context(message, cls=cls)
Expand All @@ -165,7 +169,7 @@ def load_channels(self):
print(f"Failed to find channel {n}")
continue
self.channel_config['Channels'][n] = str(self.channels[n].id)
with open('channels.ini', 'w', encoding='utf-8') as f:
with open('data/channels.ini', 'w', encoding='utf-8') as f:
self.channel_config.write(f)

def load_roles(self):
Expand Down Expand Up @@ -330,18 +334,22 @@ def main():
print('Kurisu requires 3.8 or later.')
return 2

# attempt to get current git information
try:
commit = check_output(['git', 'rev-parse', 'HEAD']).decode('ascii')[:-1]
except CalledProcessError as e:
print(f'Checking for git commit failed: {type(e).__name__}: {e}')
commit = "<unknown>"

try:
branch = check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD']).decode()[:-1]
except CalledProcessError as e:
print(f'Checking for git branch failed: {type(e).__name__}: {e}')
branch = "<unknown>"
if not IS_DOCKER:
# attempt to get current git information
try:
commit = check_output(['git', 'rev-parse', 'HEAD']).decode('ascii')[:-1]
except CalledProcessError as e:
print(f'Checking for git commit failed: {type(e).__name__}: {e}')
commit = "<unknown>"

try:
branch = check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD']).decode()[:-1]
except CalledProcessError as e:
print(f'Checking for git branch failed: {type(e).__name__}: {e}')
branch = "<unknown>"
else:
commit = os.environ.get('COMMIT_SHA')
branch = os.environ.get('COMMIT_BRANCH')

bot = Kurisu(('.', '!'), description="Kurisu, the bot for Nintendo Homebrew!", allowed_mentions=discord.AllowedMentions(everyone=False, roles=False))
bot.help_command = commands.DefaultHelpCommand(dm_help=None)
Expand Down
10 changes: 5 additions & 5 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
discord.py
aiosqlite3
Pillow
xkcd
pytz
discord.py==1.4.1
aiosqlite3==0.3.0
Pillow==7.2.0
xkcd==2.4.2
pytz==2020.1

0 comments on commit faf9424

Please sign in to comment.