Strip down docker container size
All checks were successful
Build and Publish / build_and_publish (push) Successful in 4m1s

This commit is contained in:
Nexus 2024-07-01 18:50:22 +01:00
parent 01e3e85f19
commit d46ef03ba1
Signed by: nex
GPG key ID: 0FA334385D0B689F
7 changed files with 101 additions and 56 deletions

View file

@ -1,4 +1,4 @@
FROM python:3.11-slim
FROM python:3.12
LABEL org.opencontainers.image.source https://git.i-am.nexus/nex/college-bot-v2
LABEL org.opencontainers.image.url https://git.i-am.nexus/nex/college-bot-v2
@ -11,50 +11,50 @@ WORKDIR /app
RUN DEBIAN_FRONTEND=noninteractive apt-get update
# Install chrome dependencies
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
webext-ublock-origin-chromium \
gconf-service \
libasound2 \
libatk1.0-0 \
libc6 \
libcairo2 \
libcups2 \
libdbus-1-3 \
libexpat1 \
libfontconfig1 \
libgcc1 \
libgconf-2-4 \
libgdk-pixbuf2.0-0 \
libglib2.0-0 \
libgtk-3-0 \
libnspr4 \
libpango-1.0-0 \
libpangocairo-1.0-0 \
libstdc++6 \
libx11-6 \
libx11-xcb1 \
libxcb1 \
libxcomposite1 \
libxcursor1 \
libxdamage1 \
libxext6 \
libxfixes3 \
libxi6 \
libxrandr2 \
libxrender1 \
libxss1 \
libxtst6 \
ca-certificates \
fonts-liberation \
libappindicator1 \
libnss3 \
lsb-release \
xdg-utils
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
chromium-common \
chromium-driver \
chromium-sandbox
#RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
#webext-ublock-origin-chromium \
#gconf-service \
#libasound2 \
#libatk1.0-0 \
#libc6 \
#libcairo2 \
#libcups2 \
#libdbus-1-3 \
#libexpat1 \
#libfontconfig1 \
#libgcc1 \
#libgconf-2-4 \
#libgdk-pixbuf2.0-0 \
#libglib2.0-0 \
#libgtk-3-0 \
#libnspr4 \
#libpango-1.0-0 \
#libpangocairo-1.0-0 \
#libstdc++6 \
#libx11-6 \
#libx11-xcb1 \
#libxcb1 \
#libxcomposite1 \
#libxcursor1 \
#libxdamage1 \
#libxext6 \
#libxfixes3 \
#libxi6 \
#libxrandr2 \
#libxrender1 \
#libxss1 \
#libxtst6 \
#ca-certificates \
#fonts-liberation \
#libappindicator1 \
#libnss3 \
#lsb-release \
#xdg-utils
#
#RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
# chromium-common \
# chromium-driver \
# chromium-sandbox
# Install general utilities
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
@ -67,11 +67,6 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
curl \
libmagic-dev
# Install image dependencies
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
ffmpeg \
imagemagick
RUN python3 -m venv /app/venv
RUN /app/venv/bin/pip install --upgrade --no-input pip wheel setuptools

View file

@ -9,6 +9,11 @@ services:
- ./jimmy.log:/app/jimmy.log
- /dev/dri:/dev/dri
- jimmy-data:/app/data
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
- /usr/bin/nmap:/usr/bin/nmap:ro
- /usr/bin/ffmpeg:/usr/bin/ffmpeg:ro
- /usr/bin/ffprobe:/usr/bin/ffprobe:ro
extra_hosts:
- host.docker.internal:host-gateway
depends_on:

View file

@ -1,5 +1,11 @@
# In order to use commands in this system, the following things must be installed (ideally in /usr/local/bin):
# - `ffmpeg`, usually `ffmpeg`, sometimes `ffmpeg-full`.
# - /dev/dri should be passed through to the container for hardware acceleration.
# - `ffprobe`, usually `ffmpeg`, sometimes `ffmpeg-full`.
# In docker, you can just bind these as volumes, and read-only too.
import asyncio
import io
import shutil
import typing
from collections.abc import Iterable
import logging
@ -105,6 +111,12 @@ class AutoResponder(commands.Cog):
:param uri: The URI to transcode
:return: A transcoded file
"""
if not shutil.which("ffmpeg"):
self.log.error("ffmpeg not installed")
return
if not shutil.which("ffprobe"):
self.log.error("ffprobe not installed")
return
last_reaction: str | None = None
def update_reaction(new: str | None = None) -> None:
@ -118,9 +130,7 @@ class AutoResponder(commands.Cog):
last_reaction = new
self.log.info("Waiting for transcode lock to release")
async with self.transcode_lock:
cog: FFMeta = self.bot.get_cog("FFMeta")
if not cog:
raise RuntimeError("FFMeta cog not loaded")
cog = FFMeta(self.bot)
if not isinstance(uri, str):
uri = str(uri)
@ -240,6 +250,12 @@ class AutoResponder(commands.Cog):
*domains: str,
additional: Iterable[str] = None
) -> None:
if not shutil.which("ffmpeg"):
self.log.error("ffmpeg not installed")
return
if not shutil.which("ffprobe"):
self.log.error("ffprobe not installed")
return
if self.allow_hevc_to_h264 is False:
self.log.debug("hevc_to_h264 is disabled, not engaging.")
return

View file

@ -2,7 +2,6 @@
This module is only meant to be loaded during election times.
"""
import asyncio
import datetime
import logging
import re

View file

@ -1,8 +1,14 @@
# In order to use commands in this system, the following things must be installed (ideally in /usr/local/bin):
# - `ffmpeg`, usually `ffmpeg`, sometimes `ffmpeg-full`.
# - /dev/dri should be passed through to the container for hardware acceleration.
# - `ffprobe`, usually `ffmpeg`, sometimes `ffmpeg-full`.
# In docker, you can just bind these as volumes, and read-only too.
import asyncio
import io
import json
import logging
import pathlib
import shutil
import sys
import tempfile
import typing
@ -56,6 +62,8 @@ class FFMeta(commands.Cog):
@commands.slash_command()
async def ffprobe(self, ctx: discord.ApplicationContext, url: str = None, attachment: discord.Attachment = None):
"""Runs ffprobe on a given URL or attachment"""
if not shutil.which("ffprobe"):
return await ctx.respond("ffprobe is not installed on this system.")
if url is None:
if attachment is None:
return await ctx.respond("No URL or attachment provided")
@ -142,6 +150,10 @@ class FFMeta(commands.Cog):
] = False,
):
"""Converts a given URL or attachment to an Opus file"""
if not shutil.which("ffmpeg"):
return await ctx.respond("ffmpeg is not installed on this system.")
if not shutil.which("ffprobe"):
return await ctx.respond("ffprobe is not installed on this system.")
if bitrate == 0:
bitrate = 0.5
if mono:
@ -244,6 +256,8 @@ class FFMeta(commands.Cog):
rbh = Path("assets/right-behind-you.ogg").resolve()
if not rbh.exists():
return await ctx.respond("The file `right-behind-you.ogg` is missing.")
if not shutil.which("ffmpeg"):
return await ctx.respond("ffmpeg is not installed on this system.")
if not image.content_type.startswith("image"):
return await ctx.respond("That's not an image!")
with tempfile.NamedTemporaryFile(suffix=Path(image.filename).suffix) as temp:

View file

@ -1,3 +1,9 @@
# In order to use commands in this system, the following things must be installed (ideally in /usr/local/bin):
# - `ping`, usually iputils-ping
# - `whois`, usually whois
# - `traceroute`, usually traceroute
# - `nmap`, usually nmap
# In docker, you can just bind these as volumes, and read-only too.
import asyncio
import io
import json
@ -49,6 +55,8 @@ class NetworkCog(commands.Cog):
@commands.slash_command()
async def ping(self, ctx: discord.ApplicationContext, target: str = None):
"""Get the bot's latency, or the network latency to a target."""
if not shutil.which("ping"):
return await ctx.respond("Ping is not installed on this system.")
if target is None:
return await ctx.respond(f"Pong! {round(self.bot.latency * 1000)}ms")
else:
@ -75,6 +83,8 @@ class NetworkCog(commands.Cog):
@commands.slash_command()
async def whois(self, ctx: discord.ApplicationContext, target: str):
"""Get information about a user."""
if not shutil.which("whois"):
return await ctx.respond("Whois is not installed on this system.")
async def run_command(with_disclaimer: bool = False):
args = [] if with_disclaimer else ["-H"]
@ -221,6 +231,8 @@ class NetworkCog(commands.Cog):
await ctx.defer()
if re.search(r"\s+", url):
return await ctx.respond("URL cannot contain spaces.")
if not shutil.which("traceroute"):
return await ctx.respond("Traceroute is not installed on this system.")
args = ["sudo", "-E", "-n", "traceroute"]
flags = {

View file

@ -3,6 +3,7 @@ import functools
import hashlib
import logging
import math
import shutil
import time
import datetime
@ -190,6 +191,8 @@ class YTDLCog(commands.Cog):
:param file: The file to convert
:return: The converted file
"""
if not shutil.which("ffmpeg"):
raise RuntimeError("ffmpeg is not installed.")
new_file = file.with_suffix(".m4a")
args = [
"-vn",
@ -319,8 +322,9 @@ class YTDLCog(commands.Cog):
else:
chosen_format = user_format
ffmpeg_installed = bool(shutil.which("ffmpeg"))
options.setdefault("postprocessors", [])
if audio_only:
if audio_only and ffmpeg_installed:
# Overwrite format here to be best audio under 25 megabytes.
chosen_format = "ba[filesize<20M]"
# Also force sorting by the best audio bitrate first.
@ -332,7 +336,7 @@ class YTDLCog(commands.Cog):
options["format"] = chosen_format
options["paths"] = paths
if subtitles:
if subtitles and ffmpeg_installed:
subtitles, burn = subtitles.split("+", 1) if "+" in subtitles else (subtitles, "0")
burn = burn[0].lower() in ("y", "1", "t")
if subtitles.lower() == "auto":