feat(host): start docker addon
This commit is contained in:
parent
7423b40337
commit
c7ddba1bae
22 changed files with 394 additions and 12 deletions
7
.envs/.local/.postgres
Normal file
7
.envs/.local/.postgres
Normal file
|
@ -0,0 +1,7 @@
|
|||
# PostgreSQL
|
||||
# ------------------------------------------------------------------------------
|
||||
POSTGRES_HOST=postgres
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_DB=tuxbot_bot
|
||||
POSTGRES_USER=debug
|
||||
POSTGRES_PASSWORD=debug
|
4
.envs/.local/.tuxbot
Normal file
4
.envs/.local/.tuxbot
Normal file
|
@ -0,0 +1,4 @@
|
|||
# General
|
||||
# ------------------------------------------------------------------------------
|
||||
USE_DOCKER=yes
|
||||
IPYTHONDIR=/app/.ipython
|
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -36,4 +36,10 @@ venv
|
|||
dist
|
||||
build
|
||||
*.egg
|
||||
*.egg-info
|
||||
*.egg-info
|
||||
|
||||
|
||||
.ipython/
|
||||
.env
|
||||
.envs/*
|
||||
!.envs/.local/
|
|
@ -2,7 +2,7 @@
|
|||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/tuxbot-bot.iml" filepath="$PROJECT_DIR$/.idea/tuxbot-bot.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/tuxbot_bot.iml" filepath="$PROJECT_DIR$/.idea/tuxbot_bot.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -6,7 +6,7 @@
|
|||
<excludeFolder url="file://$MODULE_DIR$/dist" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.9 (tuxbot-bot)" jdkType="Python SDK" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.9 (venv)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="PyDocumentationSettings">
|
37
compose/local/tuxbot/Dockerfile
Normal file
37
compose/local/tuxbot/Dockerfile
Normal file
|
@ -0,0 +1,37 @@
|
|||
FROM python:3.8-slim-buster
|
||||
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
ENV PYTHONDONTWRITEBYTECODE 1
|
||||
|
||||
RUN apt-get update \
|
||||
# dependencies for building Python packages
|
||||
&& apt-get install -y build-essential \
|
||||
# psycopg2 dependencies
|
||||
&& apt-get install -y libpq-dev \
|
||||
# Translations dependencies
|
||||
&& apt-get install -y gettext \
|
||||
# Git
|
||||
&& apt-get install -y git \
|
||||
# cleaning up unused files
|
||||
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Requirements are installed here to ensure they will be cached.
|
||||
COPY ./dev.requirements.txt /app/dev.requirements.txt
|
||||
COPY ./tuxbot /app/tuxbot
|
||||
COPY ./setup.cfg /app/setup.cfg
|
||||
COPY ./setup.py /app/setup.py
|
||||
RUN pip install -r /app/dev.requirements.txt
|
||||
RUN pip install ./app
|
||||
|
||||
COPY ./compose/production/tuxbot/entrypoint /entrypoint
|
||||
RUN sed -i 's/\r$//g' /entrypoint
|
||||
RUN chmod +x /entrypoint
|
||||
|
||||
COPY ./compose/local/tuxbot/start /start
|
||||
RUN sed -i 's/\r$//g' /start
|
||||
RUN chmod +x /start
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENTRYPOINT ["/entrypoint"]
|
6
compose/local/tuxbot/start
Normal file
6
compose/local/tuxbot/start
Normal file
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
6
compose/production/postgres/Dockerfile
Normal file
6
compose/production/postgres/Dockerfile
Normal file
|
@ -0,0 +1,6 @@
|
|||
FROM postgres:12.3
|
||||
|
||||
COPY ./compose/production/postgres/maintenance /usr/local/bin/maintenance
|
||||
RUN chmod +x /usr/local/bin/maintenance/*
|
||||
RUN mv /usr/local/bin/maintenance/* /usr/local/bin \
|
||||
&& rmdir /usr/local/bin/maintenance
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
BACKUP_DIR_PATH='/backups'
|
||||
BACKUP_FILE_PREFIX='backup'
|
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
countdown() {
|
||||
declare desc="A simple countdown. Source: https://superuser.com/a/611582"
|
||||
local seconds="${1}"
|
||||
local d=$(($(date +%s) + "${seconds}"))
|
||||
while [ "$d" -ge `date +%s` ]; do
|
||||
echo -ne "$(date -u --date @$(($d - `date +%s`)) +%H:%M:%S)\r";
|
||||
sleep 0.1
|
||||
done
|
||||
}
|
41
compose/production/postgres/maintenance/_sourced/messages.sh
Normal file
41
compose/production/postgres/maintenance/_sourced/messages.sh
Normal file
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
message_newline() {
|
||||
echo
|
||||
}
|
||||
|
||||
message_debug()
|
||||
{
|
||||
echo -e "DEBUG: ${@}"
|
||||
}
|
||||
|
||||
message_welcome()
|
||||
{
|
||||
echo -e "\e[1m${@}\e[0m"
|
||||
}
|
||||
|
||||
message_warning()
|
||||
{
|
||||
echo -e "\e[33mWARNING\e[0m: ${@}"
|
||||
}
|
||||
|
||||
message_error()
|
||||
{
|
||||
echo -e "\e[31mERROR\e[0m: ${@}"
|
||||
}
|
||||
|
||||
message_info()
|
||||
{
|
||||
echo -e "\e[37mINFO\e[0m: ${@}"
|
||||
}
|
||||
|
||||
message_suggestion()
|
||||
{
|
||||
echo -e "\e[33mSUGGESTION\e[0m: ${@}"
|
||||
}
|
||||
|
||||
message_success()
|
||||
{
|
||||
echo -e "\e[32mSUCCESS\e[0m: ${@}"
|
||||
}
|
16
compose/production/postgres/maintenance/_sourced/yes_no.sh
Normal file
16
compose/production/postgres/maintenance/_sourced/yes_no.sh
Normal file
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
yes_no() {
|
||||
declare desc="Prompt for confirmation. \$\"\{1\}\": confirmation message."
|
||||
local arg1="${1}"
|
||||
|
||||
local response=
|
||||
read -r -p "${arg1} (y/[n])? " response
|
||||
if [[ "${response}" =~ ^[Yy]$ ]]
|
||||
then
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
38
compose/production/postgres/maintenance/backup
Normal file
38
compose/production/postgres/maintenance/backup
Normal file
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
### Create a database backup.
|
||||
###
|
||||
### Usage:
|
||||
### $ docker-compose -f <environment>.yml (exec |run --rm) postgres backup
|
||||
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
|
||||
working_dir="$(dirname ${0})"
|
||||
source "${working_dir}/_sourced/constants.sh"
|
||||
source "${working_dir}/_sourced/messages.sh"
|
||||
|
||||
|
||||
message_welcome "Backing up the '${POSTGRES_DB}' database..."
|
||||
|
||||
|
||||
if [[ "${POSTGRES_USER}" == "postgres" ]]; then
|
||||
message_error "Backing up as 'postgres' user is not supported. Assign 'POSTGRES_USER' env with another one and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export PGHOST="${POSTGRES_HOST}"
|
||||
export PGPORT="${POSTGRES_PORT}"
|
||||
export PGUSER="${POSTGRES_USER}"
|
||||
export PGPASSWORD="${POSTGRES_PASSWORD}"
|
||||
export PGDATABASE="${POSTGRES_DB}"
|
||||
|
||||
backup_filename="${BACKUP_FILE_PREFIX}_$(date +'%Y_%m_%dT%H_%M_%S').sql.gz"
|
||||
pg_dump | gzip > "${BACKUP_DIR_PATH}/${backup_filename}"
|
||||
|
||||
|
||||
message_success "'${POSTGRES_DB}' database backup '${backup_filename}' has been created and placed in '${BACKUP_DIR_PATH}'."
|
22
compose/production/postgres/maintenance/backups
Normal file
22
compose/production/postgres/maintenance/backups
Normal file
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
### View backups.
|
||||
###
|
||||
### Usage:
|
||||
### $ docker-compose -f <environment>.yml (exec |run --rm) postgres backups
|
||||
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
|
||||
working_dir="$(dirname ${0})"
|
||||
source "${working_dir}/_sourced/constants.sh"
|
||||
source "${working_dir}/_sourced/messages.sh"
|
||||
|
||||
|
||||
message_welcome "These are the backups you have got:"
|
||||
|
||||
ls -lht "${BACKUP_DIR_PATH}"
|
55
compose/production/postgres/maintenance/restore
Normal file
55
compose/production/postgres/maintenance/restore
Normal file
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
### Restore database from a backup.
|
||||
###
|
||||
### Parameters:
|
||||
### <1> filename of an existing backup.
|
||||
###
|
||||
### Usage:
|
||||
### $ docker-compose -f <environment>.yml (exec |run --rm) postgres restore <1>
|
||||
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
|
||||
working_dir="$(dirname ${0})"
|
||||
source "${working_dir}/_sourced/constants.sh"
|
||||
source "${working_dir}/_sourced/messages.sh"
|
||||
|
||||
|
||||
if [[ -z ${1+x} ]]; then
|
||||
message_error "Backup filename is not specified yet it is a required parameter. Make sure you provide one and try again."
|
||||
exit 1
|
||||
fi
|
||||
backup_filename="${BACKUP_DIR_PATH}/${1}"
|
||||
if [[ ! -f "${backup_filename}" ]]; then
|
||||
message_error "No backup with the specified filename found. Check out the 'backups' maintenance script output to see if there is one and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
message_welcome "Restoring the '${POSTGRES_DB}' database from the '${backup_filename}' backup..."
|
||||
|
||||
if [[ "${POSTGRES_USER}" == "postgres" ]]; then
|
||||
message_error "Restoring as 'postgres' user is not supported. Assign 'POSTGRES_USER' env with another one and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export PGHOST="${POSTGRES_HOST}"
|
||||
export PGPORT="${POSTGRES_PORT}"
|
||||
export PGUSER="${POSTGRES_USER}"
|
||||
export PGPASSWORD="${POSTGRES_PASSWORD}"
|
||||
export PGDATABASE="${POSTGRES_DB}"
|
||||
|
||||
message_info "Dropping the database..."
|
||||
dropdb "${PGDATABASE}"
|
||||
|
||||
message_info "Creating a new database..."
|
||||
createdb --owner="${POSTGRES_USER}"
|
||||
|
||||
message_info "Applying the backup to the new database..."
|
||||
gunzip -c "${backup_filename}" | psql "${POSTGRES_DB}"
|
||||
|
||||
message_success "The '${POSTGRES_DB}' database has been restored from the '${backup_filename}' backup."
|
46
compose/production/tuxbot/Dockerfile
Normal file
46
compose/production/tuxbot/Dockerfile
Normal file
|
@ -0,0 +1,46 @@
|
|||
FROM node:10-stretch-slim as client-builder
|
||||
|
||||
WORKDIR /app
|
||||
COPY ./package.json /app
|
||||
RUN npm install && npm cache clean --force
|
||||
COPY . /app
|
||||
RUN npm run build
|
||||
|
||||
# Python build stage
|
||||
FROM python:3.8-slim-buster
|
||||
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
|
||||
RUN apt-get update \
|
||||
# dependencies for building Python packages
|
||||
&& apt-get install -y build-essential \
|
||||
# psycopg2 dependencies
|
||||
&& apt-get install -y libpq-dev \
|
||||
# Translations dependencies
|
||||
&& apt-get install -y gettext \
|
||||
# cleaning up unused files
|
||||
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN addgroup --system tuxbot \
|
||||
&& adduser --system --ingroup tuxbot tuxbot
|
||||
|
||||
# Requirements are installed here to ensure they will be cached.
|
||||
RUN pip install --no-cache-dir psycopg2==2.8.6
|
||||
|
||||
COPY --chown=tuxbot:tuxbot ./compose/production/tuxbot/entrypoint /entrypoint
|
||||
RUN sed -i 's/\r$//g' /entrypoint
|
||||
RUN chmod +x /entrypoint
|
||||
|
||||
|
||||
COPY --chown=tuxbot:tuxbot ./compose/production/tuxbot/start /start
|
||||
RUN sed -i 's/\r$//g' /start
|
||||
RUN chmod +x /start
|
||||
COPY --from=client-builder --chown=tuxbot:tuxbot /app /app
|
||||
|
||||
|
||||
USER tuxbot
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENTRYPOINT ["/entrypoint"]
|
42
compose/production/tuxbot/entrypoint
Normal file
42
compose/production/tuxbot/entrypoint
Normal file
|
@ -0,0 +1,42 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
|
||||
|
||||
|
||||
if [ -z "${POSTGRES_USER}" ]; then
|
||||
base_postgres_image_default_user='postgres'
|
||||
export POSTGRES_USER="${base_postgres_image_default_user}"
|
||||
fi
|
||||
export DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}"
|
||||
|
||||
postgres_ready() {
|
||||
python << END
|
||||
import sys
|
||||
|
||||
import psycopg2
|
||||
|
||||
try:
|
||||
psycopg2.connect(
|
||||
dbname="${POSTGRES_DB}",
|
||||
user="${POSTGRES_USER}",
|
||||
password="${POSTGRES_PASSWORD}",
|
||||
host="${POSTGRES_HOST}",
|
||||
port="${POSTGRES_PORT}",
|
||||
)
|
||||
except psycopg2.OperationalError:
|
||||
sys.exit(-1)
|
||||
sys.exit(0)
|
||||
|
||||
END
|
||||
}
|
||||
until postgres_ready; do
|
||||
>&2 echo 'Waiting for PostgreSQL to become available...'
|
||||
sleep 1
|
||||
done
|
||||
>&2 echo 'PostgreSQL is available'
|
||||
|
||||
exec "$@"
|
8
compose/production/tuxbot/start
Normal file
8
compose/production/tuxbot/start
Normal file
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
|
||||
tuxbot dev
|
33
local.yml
Normal file
33
local.yml
Normal file
|
@ -0,0 +1,33 @@
|
|||
version: '3'
|
||||
|
||||
volumes:
|
||||
local_postgres_data: {}
|
||||
local_postgres_data_backups: {}
|
||||
|
||||
services:
|
||||
tuxbot:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./compose/local/tuxbot/Dockerfile
|
||||
image: tuxbot_bot_local_tuxbot
|
||||
container_name: tuxbot
|
||||
depends_on:
|
||||
- postgres
|
||||
volumes:
|
||||
- .:/app:z
|
||||
env_file:
|
||||
- ./.envs/.local/.tuxbot
|
||||
- ./.envs/.local/.postgres
|
||||
command: /start
|
||||
|
||||
postgres:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./compose/production/postgres/Dockerfile
|
||||
image: tuxbot_bot_production_postgres
|
||||
container_name: postgres
|
||||
volumes:
|
||||
- local_postgres_data:/var/lib/postgresql/data:Z
|
||||
- local_postgres_data_backups:/backups:z
|
||||
env_file:
|
||||
- ./.envs/.local/.postgres
|
|
@ -26,7 +26,7 @@ install_requires =
|
|||
psutil==5.7.2
|
||||
pydig==0.3.0
|
||||
rich==9.10.0
|
||||
sentry_sdk==0.19.5
|
||||
sentry_sdk==0.20.0
|
||||
structured_config==4.12
|
||||
tortoise-orm==0.16.17
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import sys
|
||||
from tuxbot import ExitCodes
|
||||
from tuxbot.core.utils.console import console
|
||||
|
||||
|
@ -9,10 +10,7 @@ def main() -> None:
|
|||
run()
|
||||
except SystemExit as exc:
|
||||
if exc.code == ExitCodes.RESTART:
|
||||
# reimport to load changes
|
||||
from .__run__ import run # pylint: disable=import-outside-toplevel
|
||||
|
||||
run()
|
||||
sys.exit(exc.code)
|
||||
else:
|
||||
raise exc
|
||||
except Exception:
|
||||
|
|
|
@ -366,10 +366,10 @@ class Tux(commands.AutoShardedBot):
|
|||
and reboot.
|
||||
|
||||
"""
|
||||
if not restart:
|
||||
self.shutdown_code = ExitCodes.SHUTDOWN
|
||||
else:
|
||||
self.shutdown_code = ExitCodes.RESTART
|
||||
|
||||
self.shutdown_code = (
|
||||
ExitCodes.RESTART if restart else ExitCodes.SHUTDOWN
|
||||
)
|
||||
|
||||
await self.logout()
|
||||
|
||||
|
|
Loading…
Reference in a new issue