Skip to content
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

Adds Docker support (cross-platform) #93

Open
wants to merge 33 commits into
base: rewrite
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
24e8db7
Initial work on Docker support
Dids Mar 23, 2020
47106ca
Settings dict values for lavalink
Dids Mar 23, 2020
685a583
Check for file size when checking if file exists
Dids Mar 23, 2020
80bb43d
More containerization work
Dids Mar 23, 2020
7804905
Attempting to use a separate data directory
Dids Mar 23, 2020
63e7178
Settings.py now supports override paths
Dids Mar 24, 2020
8d941e0
Updated Docker stuff with new settings changes
Dids Mar 24, 2020
7c29d4c
Docker cleanup
Dids Mar 24, 2020
7ec7bb9
Initial work on Dockerfile for Windows
Dids Mar 27, 2020
5e84c0e
Dockerfile for Windows now compiles and runs (kinda)
Dids Mar 27, 2020
f39cd08
Merge remote-tracking branch 'upstream/rewrite' into feature/docker
Dids Apr 19, 2020
e672dfd
Fixed docker-compose.yaml
Dids Apr 20, 2020
a46f3b5
First pass on Docker CI workflow
Dids Apr 20, 2020
90fcfc9
Fixing Docker CI workflow
Dids Apr 20, 2020
93b92cf
Fixing Docker CI workflow
Dids Apr 20, 2020
6bbd3ce
Fixing Docker CI workflow
Dids Apr 20, 2020
69ec832
Fixing Docker CI workflow
Dids Apr 20, 2020
56f87f6
Fixing Docker CI workflow
Dids Apr 20, 2020
14370ce
Fixing Docker CI workflow
Dids Apr 20, 2020
494afa5
Fixing Docker CI workflow
Dids Apr 20, 2020
31503d3
Fixing Docker CI workflow for Windows
Dids Apr 20, 2020
be53a3a
Finishing touches on Docker support
Dids Apr 20, 2020
3feb10a
Cleanup and optional Docker Hub support for CI
Dids Apr 23, 2020
0ab7306
Added feature/docker branch back to CI build rules
Dids Apr 23, 2020
4a6aad4
Fixed typo in CI workflow
Dids Apr 23, 2020
378fbdd
Minor documentation update
Dids Apr 23, 2020
50e4a13
Updated the CI workflow to be more dynamic
Dids Apr 23, 2020
e39b5e8
Fixing Docker CI workflow
Dids Apr 23, 2020
0d00c39
Fixing Docker CI workflow
Dids Apr 23, 2020
815ce96
Merge branch 'rewrite' of github.com:corpnewt/CorpBot.py into feature…
Dids Apr 20, 2021
69bdd15
Update Settings.py
Dids Apr 20, 2021
dbe956e
Update Docker
Dids Apr 20, 2021
85ab3e8
Better data persisting, handling TempRole errors
Dids Apr 21, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 147 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
name: Deploy Docker

# Trigger the workflow on both pushes and pull requests
on: [ push, pull_request ]

# Use bash as the default shell for run commands
defaults:
run:
shell: bash

env:
DOCKER_CLI_EXPERIMENTAL: enabled # Enable Docker experimental features (eg. `docker manifest ...`)

jobs:

deploy-linux:
name: Deploy (linux)
runs-on: ubuntu-latest
steps:

- name: Checkout Repository
uses: actions/checkout@v2

- name: Login to Docker Registry
if: github.event_name != 'pull_request'
run: |-
# Login to GitHub Package Registry
docker login docker.pkg.github.com -u $GITHUB_ACTOR -p ${{ secrets.GITHUB_TOKEN }}

# Login to Docker Hub
if [ ! -z "${{ secrets.DOCKER_HUB_USERNAME }}" ] && [ ! -z "${{ secrets.DOCKER_HUB_TOKEN }}" ]; then
docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} -p ${{ secrets.DOCKER_HUB_TOKEN }}
fi

- name: Build Docker image
run: |-
# Parse the tag
TAG=${GITHUB_REF##*/}
TAG=${TAG:-$GITHUB_SHA}

# Build the image
docker build --rm -f docker/Dockerfile -t corpbot.py:${TAG}-linux-amd64 .

- name: Publish to Docker Registry
if: github.event_name != 'pull_request'
run: |-
# Parse the tag
TAG=${GITHUB_REF##*/}
TAG=${TAG:-$GITHUB_SHA}

# Publish to GitHub Package Registry
docker tag corpbot.py:${TAG}-linux-amd64 docker.pkg.github.com/${GITHUB_ACTOR,,}/corpbot.py/corpbot.py:${TAG}-linux-amd64
docker push docker.pkg.github.com/${GITHUB_ACTOR,,}/corpbot.py/corpbot.py:${TAG}-linux-amd64

# Publish to Docker Hub
if [ ! -z "${{ secrets.DOCKER_HUB_USERNAME }}" ]; then
docker tag corpbot.py:${TAG}-linux-amd64 ${{ secrets.DOCKER_HUB_USERNAME }}/corpbot.py:${TAG}-linux-amd64
docker push ${{ secrets.DOCKER_HUB_USERNAME }}/corpbot.py:${TAG}-linux-amd64
fi

deploy-windows:
name: Deploy (windows)
runs-on: windows-latest
steps:

- name: Checkout Repository
uses: actions/checkout@v2

- name: Login to Docker Registry
if: github.event_name != 'pull_request'
run: |-
# Login to GitHub Package Registry
docker login docker.pkg.github.com -u $GITHUB_ACTOR -p ${{ secrets.GITHUB_TOKEN }}

# Login to Docker Hub
if [ ! -z "${{ secrets.DOCKER_HUB_USERNAME }}" ] && [ ! -z "${{ secrets.DOCKER_HUB_TOKEN }}" ]; then
docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} -p ${{ secrets.DOCKER_HUB_TOKEN }}
fi

- name: Build Docker image
run: |-
# Parse the tag
TAG=${GITHUB_REF##*/}
TAG=${TAG:-$GITHUB_SHA}

# Build the image
docker build --rm -f docker/Dockerfile.win -t corpbot.py:${TAG}-windows-amd64 .

- name: Publish to Docker Registry
if: github.event_name != 'pull_request'
run: |-
# Parse the tag
TAG=${GITHUB_REF##*/}
TAG=${TAG:-$GITHUB_SHA}

## FIXME: GitHub Package Registry doesn't support Windows images (yet)
# Publish to GitHub Package Registry
# docker tag corpbot.py:${TAG}-windows-amd64 docker.pkg.github.com/${GITHUB_ACTOR,,}/corpbot.py/corpbot.py:${TAG}-windows-amd64
# docker push docker.pkg.github.com/${GITHUB_ACTOR,,}/corpbot.py/corpbot.py:${TAG}-windows-amd64

# Publish to Docker Hub
if [ ! -z "${{ secrets.DOCKER_HUB_USERNAME }}" ]; then
docker tag corpbot.py:${TAG}-windows-amd64 ${{ secrets.DOCKER_HUB_USERNAME }}/corpbot.py:${TAG}-windows-amd64
docker push ${{ secrets.DOCKER_HUB_USERNAME }}/corpbot.py:${TAG}-windows-amd64
fi

deploy-manifest:
name: Deploy (manifest)
runs-on: ubuntu-latest
needs: [ deploy-linux, deploy-windows ]
steps:

- name: Checkout Repository
uses: actions/checkout@v1

- name: Login to Docker Registry
if: github.event_name != 'pull_request'
run: |-
# Login to GitHub Package Registry
docker login docker.pkg.github.com -u $GITHUB_ACTOR -p ${{ secrets.GITHUB_TOKEN }}

# Login to Docker Hub
if [ ! -z "${{ secrets.DOCKER_HUB_USERNAME }}" ] && [ ! -z "${{ secrets.DOCKER_HUB_TOKEN }}" ]; then
docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} -p ${{ secrets.DOCKER_HUB_TOKEN }}
fi

- name: Publish to Docker Registry
if: github.event_name != 'pull_request'
run: |-
# Parse the tag
TAG=${GITHUB_REF##*/}
TAG=${TAG:-$GITHUB_SHA}

## FIXME: GitHub Package Registry doesn't support Windows images (yet)
# Create and push a combined image manifest to GitHub Package Registry
# docker manifest create docker.pkg.github.com/${GITHUB_ACTOR,,}/corpbot.py:${TAG} docker.pkg.github.com/${GITHUB_ACTOR,,}/corpbot.py:${TAG}-linux-amd64 docker.pkg.github.com/${GITHUB_ACTOR,,}/corpbot.py:${TAG}-windows-amd64
# docker manifest annotate docker.pkg.github.com/${GITHUB_ACTOR,,}/corpbot.py:${TAG} docker.pkg.github.com/${GITHUB_ACTOR,,}/corpbot.py:${TAG}-linux-amd64 --os linux --arch amd64
# docker manifest annotate docker.pkg.github.com/${GITHUB_ACTOR,,}/corpbot.py:${TAG} docker.pkg.github.com/${GITHUB_ACTOR,,}/corpbot.py:${TAG}-windows-amd64 --os windows --arch amd64
# docker manifest push docker.pkg.github.com/${GITHUB_ACTOR,,}/corpbot.py:${TAG} --purge

# Create and push a combined image manifest to Docker Hub
if [ ! -z "${{ secrets.DOCKER_HUB_USERNAME }}" ]; then
docker manifest create ${{ secrets.DOCKER_HUB_USERNAME }}/corpbot.py:${TAG} ${{ secrets.DOCKER_HUB_USERNAME }}/corpbot.py:${TAG}-linux-amd64 ${{ secrets.DOCKER_HUB_USERNAME }}/corpbot.py:${TAG}-windows-amd64
docker manifest annotate ${{ secrets.DOCKER_HUB_USERNAME }}/corpbot.py:${TAG} ${{ secrets.DOCKER_HUB_USERNAME }}/corpbot.py:${TAG}-linux-amd64 --os linux --arch amd64
docker manifest annotate ${{ secrets.DOCKER_HUB_USERNAME }}/corpbot.py:${TAG} ${{ secrets.DOCKER_HUB_USERNAME }}/corpbot.py:${TAG}-windows-amd64 --os windows --arch amd64
docker manifest push ${{ secrets.DOCKER_HUB_USERNAME }}/corpbot.py:${TAG} --purge
fi
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Anythings starting with .
.*

# Don't ignore .github
!.github

# Ignore redis stuff
Redis*

Expand Down
10 changes: 5 additions & 5 deletions Cogs/Settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@ class Settings(commands.Cog):
def __init__(self, bot, prefix = "$", file : str = None):
if file == None:
# We weren't given a file, default to ./Settings.json
file = "Settings.json"
file = bot.settings_dict.get("settings_path","Settings.json")

self.file = file
self.backupDir = "Settings-Backup"
self.backupDir = bot.settings_dict.get("settings_backup_path","Settings-Backup")
self.backupMax = 100
self.backupTime = 7200 # runs every 2 hours
self.backupWait = 10 # initial wait time before first backup
Expand Down Expand Up @@ -309,14 +309,14 @@ def __init__(self, bot, prefix = "$", file : str = None):


def load_json(self, file):
if os.path.exists(file):
if os.path.exists(file) and os.path.getsize(file):
print("Since no mongoDB instance was running, I'm reverting back to the Settings.json")
self.serverDict = json.load(open(file))
else:
self.serverDict = {}

def migrate(self, _file):
if os.path.exists(_file):
if os.path.exists(_file) and os.path.getsize(_file):
try:
settings_json = json.load(open(_file))
if "mongodb_migrated" not in settings_json:
Expand Down Expand Up @@ -478,7 +478,7 @@ async def backup(self):
os.makedirs(self.backupDir)
# Flush backup
timeStamp = datetime.today().strftime("%Y-%m-%d %H.%M")
self.flushSettings("./{}/Backup-{}.json".format(self.backupDir, timeStamp), True)
self.flushSettings("{}/Backup-{}.json".format(self.backupDir, timeStamp), True)

# Get curr dir and change curr dir
retval = os.getcwd()
Expand Down
2 changes: 1 addition & 1 deletion Cogs/TempRole.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def check_temp(self):
# Bail if we're not the current instance
return
temp_roles = self.settings.getUserStat(member, server, "TempRoles")
if len(temp_roles):
if temp_roles is not None and len(temp_roles):
# We have a list
remove_temps = []
for temp_role in temp_roles:
Expand Down
66 changes: 66 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Base the image on Python 3 running on Alpine
# FROM python:3.9.4-alpine3.13
FROM python:3.8.9-alpine3.13

# Install base dependencies
RUN apk add --update --no-cache \
bash \
git \
openssh \
ca-certificates \
libffi \
libxml2 \
zlib \
libxslt \
libjpeg

# Install build dependencies
RUN apk add --update --no-cache --virtual build-dependencies \
alpine-sdk \
linux-headers \
python3-dev \
libffi-dev \
libxml2-dev \
zlib-dev \
libxslt-dev \
jpeg-dev

# Disable host key checking for git
RUN mkdir -p ~/.ssh && \
echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config

# Switch to the image provided work directory
WORKDIR /usr/src/app

# Set default git merge strategy
RUN git config --global pull.rebase false

# Copy the installation script and install dependencies
COPY Install.py ./Install.py
RUN yes '' | python ./Install.py

# Remove build dependencies
RUN apk del build-dependencies

# Copy the rest of the application over
COPY . .

# Create the data directory
RUN mkdir -p /data

# Define default environment variables
ENV SETTINGS_DICT_PREFIX ""
ENV SETTINGS_DICT_TOKEN ""
ENV SETTINGS_DICT_WEATHER ""
ENV SETTINGS_DICT_CURRENCY ""
ENV SETTINGS_DICT_SETTINGS_PATH "/data/Settings.json"
ENV SETTINGS_DICT_SETTINGS_BACKUP_PATH "/data"
ENV SETTINGS_DICT_LAVALINK_HOST "lavalink"
ENV SETTINGS_DICT_LAVALINK_REGION "us_central"
ENV SETTINGS_DICT_LAVALINK_PASSWORD "youshallnotpass"

# Expose volumes
VOLUME [ "/data", "/usr/local/lib/python3.8/site-packages" ]

# Set the startup Python script
CMD [ "docker/start.sh" ]
3 changes: 3 additions & 0 deletions docker/Dockerfile.lavalink
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM 1conan/lavalink:latest

COPY lavalink.yaml /config/application.yml
48 changes: 48 additions & 0 deletions docker/Dockerfile.win
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Base the image on Python 3 running on Windows Server Core
FROM python:3.8.2-windowsservercore

# Install git
ENV GIT_VERSION 2.26.0
ENV GIT_PATCH_VERSION 1
RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ;\
Invoke-WebRequest $('https://github.com/git-for-windows/git/releases/download/v{0}.windows.{1}/MinGit-{0}-busybox-64-bit.zip' -f $env:GIT_VERSION, $env:GIT_PATCH_VERSION) -OutFile 'mingit.zip' -UseBasicParsing ;\
Expand-Archive mingit.zip -DestinationPath c:\mingit ;\
Remove-Item mingit.zip -Force ;\
setx /M PATH $('c:\mingit\cmd;{0}' -f $env:PATH)

# Update certificates
RUN certutil -generateSSTFromWU roots.sst ;\
certutil -addstore -f root roots.sst ;\
del roots.sst

# Create the app directory
RUN mkdir C:/app

# Set the working directory
WORKDIR C:/app

# Copy the application
ADD ./ C:/app

# Install dependencies
RUN cmd /c "break|C:/app/Install.bat"

## TODO: Install Lavalink and use "StartBot.bat"
## https://github.com/Frederikam/Lavalink/releases/tag/3.3.1

# Define default environment variables
ENV SETTINGS_DICT_PREFIX ""
ENV SETTINGS_DICT_TOKEN ""
ENV SETTINGS_DICT_WEATHER ""
ENV SETTINGS_DICT_CURRENCY ""
ENV SETTINGS_DICT_SETTINGS_PATH "C:/app/docker/data/Settings.json"
ENV SETTINGS_DICT_SETTINGS_BACKUP_PATH "C:/app/docker/data/Settings-Backup"
ENV SETTINGS_DICT_LAVALINK_HOST "lavalink"
ENV SETTINGS_DICT_LAVALINK_REGION "us_central"
ENV SETTINGS_DICT_LAVALINK_PASSWORD "youshallnotpass"

# Expose volumes
VOLUME [ "C:/app/docker/data" ]

# Set the startup command
CMD [ "Start.bat" ]
43 changes: 43 additions & 0 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Docker support for CorpBot.py

This is a short document detailing the current status of the Docker images, including how to set them up.

## Features

#### Implemented

- [x] Bot running smoothly inside Docker (tested and works well)
- [x] Full data persistence (data is stored under `/data`, see `docker-compose.yml`)
- [x] Lavalink support both as a Docker container and an external service (playback tested and works well)
- [x] Docker image for Linux (tested and working)
- [x] Docker image for Windows (largely untested)

#### Planned

- [ ] Fix/update CI workflow to use new GH registry URL
- [ ] Fix/update CI workflow to support Windows (if/when available)
- [ ] ARM image support (CorpBot itself runs fine on ARM)
- [ ] Redis support (redis branch)
- [ ] MongoDB support (same deal)
- [ ] Optimized, minimal image sizes (Alpine, multi-staged builds, Windows image needs special attention)

## Running

Create a `.env` file at the root of this project with the following environment variables):
```
SETTINGS_DICT_PREFIX="<bot_prefix>"
SETTINGS_DICT_TOKEN="<discord_bot_token>"
SETTINGS_DICT_WEATHER="<openweathermap_api_token>"
SETTINGS_DICT_CURRENCY="<currencyconverter_api_token>"
SETTINGS_DICT_SETTINGS_PATH="<path_to_settings.json> (optional)
SETTINGS_DICT_SETTINGS_BACKUP_PATH="<path_to_settings_backups>" (optional)
SETTINGS_DICT_LAVALINK_HOST="<lavalink_hostname_or_ip>" (optional)
SETTINGS_DICT_LAVALINK_REGION="<lavalink_discord_region>" (optional)
SETTINGS_DICT_LAVALINK_PASSWORD="<lavalink_password>" (optional)
```

Build and run with Docker Compose while inside the `./docker/` directory:
> docker-compose up --build

To bring it down with Docker Compose:
> docker-compose down
Loading