diff --git a/Dockerfile b/Dockerfile index 91db733..f5ea993 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,33 @@ -FROM python:3.12-slim +# Stage 1: Build +FROM python:3.12-slim-bookworm as builder -# Install build dependencies -RUN apt-get update -y && apt-get install -y gcc python3-dev +# Install build dependencies (gcc, Python headers, etc.) +RUN apt-get update && apt-get install -y --no-install-recommends \ + gcc \ + python3-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* -# Set the working directory to /app +# Set the working directory WORKDIR /app -# Copy the current directory contents into the container at /app -COPY . /app +# Copy only the requirements file to take advantage of Docker's caching +COPY requirements.txt . -# Install any needed packages specified in requirements.txt +# Install Python dependencies RUN pip install --no-cache-dir -r requirements.txt -# Run main.py when the container launches +# Stage 2: Runtime +FROM python:3.12-slim-bookworm + +# Set the working directory +WORKDIR /app + +# Copy installed Python packages from the builder stage +COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages + +# Copy the application code +COPY . . + +# Run the application CMD ["python", "-u", "main.py"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 07edf48..841cfde 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,61 +1,102 @@ -version: "3.8" +# ------------------------------------------------------------------------------------------------------------ # +# READ THIS BEFORE INSTALL! + +# This is a docker-compose file for running Vocard with Lavalink and MongoDB(optional). +# You can selfhost MongoDB. Just uncomment lines starting with single "#" below in the compose file. +# In order to run this, you need to have Docker and Docker Compose installed. +# You can install Docker from https://docs.docker.com/get-docker/ +# and Docker Compose from https://docs.docker.com/compose/install/ + +# Step 1: Start the installation by creating the future config directory for Vocard. +# example - `root@docker:~# mkdir -p /opt/vocard/config` + +# Use `cd` to navigate to the config directory. +# example - `root@docker:~# cd /opt/vocard/config` + +# Step 3: Choose installation method: Build the image from the Dockerfile or pull it from GitHub(recommended). +# If you chose to pull from Docker Hub, comment the "build" lines and uncomment the "image" line. +# If you chose to build the image from the Dockerfile, do the following: +# uncomment this +# build: +# dockerfile: ./Dockerfile +# and comment this +# image: ghcr.io/choco/vocard:latest +# example - `root@docker:/opt/vocard/config# wget https://github.com/ChocoMeow/Vocard/archive/refs/heads/main.zip` + +# Step 4: Configure application.yml and settings.json in the config directory. +# In order to avoid silly syntax errors it is recommended to use external code editor such as VS Code or Notepad++. +# Then you can upload files to host using tools such as WinSCP or +# using `nano` to create and edit the files directly using hosts terminal. +# NOTE that some terminals DO NOT let you paste, so you can either use WinSCP or SSH app like Putty. + +# example - `root@docker:/opt/vocard/config# nano application.yml` +# example - `root@docker:/opt/vocard/config# nano settings.json` +# To exit nano, press `Ctrl + S`, then `Ctrl + X` to save changes. + +# Step 5: If the values are set correctly, you can start the installation by running the following command +# example - `root@docker:/opt/vocard/config# docker-compose up -d` (could be `docker compose` on some systems) + +# ------------------------------------------ THANK YOU FOR READING! ------------------------------------------ # +name: vocard services: lavalink: - image: ghcr.io/lavalink-devs/lavalink:latest container_name: lavalink + #image: ghcr.io/lavalink-devs/lavalink:latest + build: + dockerfile: ./lavalink/Dockerfile-lavalink restart: unless-stopped environment: - _JAVA_OPTIONS=-Xmx1G - SERVER_PORT=2333 - - LAVALINK_SERVER_PASSWORD=youshallnotpass + # there is no point in changing the password here, since the container is available only in docker network + - LAVALINK_SERVER_PASSWORD=youshallnotpass # Change password if needed (don't forget to change it in healthcheck below and settings.json) volumes: - ## Use "./" if you want to create a mount from your current directory (where docker-compose.yml is located) - ## Having access to files INSIDE the container is complicated. Mount function is used to have access to certain container files or folders. - ## Read more: https://docs.docker.com/storage/bind-mounts/ - - ./application.yml:/opt/Lavalink/application.yml + - ./lavalink/application.yml:/opt/Lavalink/application.yml networks: - - local + - vocard expose: - "2333" + healthcheck: + test: nc -z -v localhost 2333 + interval: 10s + timeout: 5s + retries: 3 - # # You can selfhost MongoDB. Just uncomment lines starting with single "#" below. - # mongo: - # image: mongo:latest - # container_name: mongo - # restart: unless-stopped - # volumes: - # # Use "./" if you want to create a mount from your current directory (where docker-compose.yml is located) - # # Having access to files INSIDE the container is complicated. Mount function is used to have access to certain container files or folders. - # # Read more: https://docs.docker.com/storage/bind-mounts/ - # - ./data/mongo/db:/data/db - # - ./data/mongo/conf:/data/configdb - # environment: - # - MONGO_INITDB_ROOT_USERNAME=admin - # - MONGO_INITDB_ROOT_PASSWORD=admin - # expose: - # - "27017" - # networks: - # - local - # command: ["mongod", "--oplogSize=1024", "--wiredTigerCacheSizeGB=1", "--auth", "--noscripting"] + #mongo: + # container_name: mongo + # image: mongo:latest + # + # restart: unless-stopped + # volumes: + # - ./data/mongo/db:/data/db + # - ./data/mongo/conf:/data/configdb + # environment: + # - MONGO_INITDB_ROOT_USERNAME=admin + # - MONGO_INITDB_ROOT_PASSWORD=admin + # expose: + # - "27017" + # networks: + # - vocard + # command: ["mongod", "--oplogSize=1024", "--wiredTigerCacheSizeGB=1", "--auth", "--noscripting"] vocard: container_name: vocard - volumes: - ## Use "./" if you want to create a mount from your current directory (where docker-compose.yml is located) - ## Having access to files INSIDE the container is complicated. Mount function is used to have access to certain container files or folders. - ## Read more: https://docs.docker.com/storage/bind-mounts/ - - ./settings.json:/app/settings.json + restart: unless-stopped + # If you want to build the image from the Dockerfile, uncomment the "build" lines and comment the "image" line. + # image: ghcr.io/choco/vocard:latest build: dockerfile: ./Dockerfile + volumes: + - ./settings.json:/app/settings.json + networks: + - vocard depends_on: lavalink: - condition: service_started + condition: service_healthy # mongo: # condition: service_started - networks: - - local networks: - local: - name: local + vocard: + name: vocard diff --git a/lavalink/Dockerfile-lavalink b/lavalink/Dockerfile-lavalink new file mode 100644 index 0000000..265ab4d --- /dev/null +++ b/lavalink/Dockerfile-lavalink @@ -0,0 +1,18 @@ +FROM eclipse-temurin:23-jre-noble + +RUN apt-get update && \ + apt-get install -y netcat-openbsd && \ + rm -rf /var/lib/apt/lists/* + +RUN groupadd -g 322 lavalink && \ + useradd -u 322 -g lavalink -m -d /opt/Lavalink lavalink + +WORKDIR /opt/Lavalink + +RUN wget -O Lavalink.jar https://github.com/lavalink-devs/Lavalink/releases/download/4.0.8/Lavalink.jar + +RUN chown -R lavalink:lavalink /opt/Lavalink + +USER lavalink + +ENTRYPOINT ["java", "-Djdk.tls.client.protocols=TLSv1.1,TLSv1.2", "-jar", "Lavalink.jar"] diff --git a/lavalink/application.yml b/lavalink/application.yml new file mode 100644 index 0000000..704256d --- /dev/null +++ b/lavalink/application.yml @@ -0,0 +1,126 @@ +server: # REST and WS server + port: 2333 + address: 0.0.0.0 + http2: + enabled: true # Whether to enable HTTP/2 support +plugins: + youtube: + enabled: true # Whether this source can be used. + allowSearch: true # Whether "ytsearch:" and "ytmsearch:" can be used. + allowDirectVideoIds: true # Whether just video IDs can match. If false, only complete URLs will be loaded. + allowDirectPlaylistIds: true # Whether just playlist IDs can match. If false, only complete URLs will be loaded. + # The clients to use for track loading. See below for a list of valid clients. + # Clients are queried in the order they are given (so the first client is queried first and so on...) + clients: + - MUSIC + - ANDROID_VR + - WEB + - WEBEMBEDDED + # The below section of the config allows setting specific options for each client, such as the requests they will handle. + # If an option, or client, is unspecified, then the default option value/client values will be used instead. + # If a client is configured, but is not registered above, the options for that client will be ignored. + # WARNING!: THE BELOW CONFIG IS FOR ILLUSTRATION PURPOSES. DO NOT COPY OR USE THIS WITHOUT + # WARNING!: UNDERSTANDING WHAT IT DOES. MISCONFIGURATION WILL HINDER YOUTUBE-SOURCE'S ABILITY TO WORK PROPERLY. + + # Write the names of clients as they are specified under the heading "Available Clients". + clientOptions: + WEB: + # Example: Disabling a client's playback capabilities. + playback: false + videoLoading: false # Disables loading of videos for this client. A client may still be used for playback even if this is set to 'false'. + WEBEMBEDDED: + # Example: Configuring a client to exclusively be used for video loading and playback. + playlistLoading: false # Disables loading of playlists and mixes. + searching: false # Disables the ability to search for videos. +lavalink: + plugins: + - dependency: "dev.lavalink.youtube:youtube-plugin:1.11.4" +# - dependency: "com.github.example:example-plugin:1.0.0" # required, the coordinates of your plugin +# repository: "https://maven.example.com/releases" # optional, defaults to the Lavalink releases repository by default +# snapshot: false # optional, defaults to false, used to tell Lavalink to use the snapshot repository instead of the release repository +# pluginsDir: "./plugins" # optional, defaults to "./plugins" +# defaultPluginRepository: "https://maven.lavalink.dev/releases" # optional, defaults to the Lavalink release repository +# defaultPluginSnapshotRepository: "https://maven.lavalink.dev/snapshots" # optional, defaults to the Lavalink snapshot repository + server: + password: "youshallnotpass" + sources: + # The default Youtube source is now deprecated and won't receive further updates. Please use https://github.com/lavalink-devs/youtube-source#plugin instead. + youtube: false + bandcamp: true + soundcloud: true + twitch: true + vimeo: true + nico: true + http: true # warning: keeping HTTP enabled without a proxy configured could expose your server's IP address. + local: false + filters: # All filters are enabled by default + volume: true + equalizer: true + karaoke: true + timescale: true + tremolo: true + vibrato: true + distortion: true + rotation: true + channelMix: true + lowPass: true + nonAllocatingFrameBuffer: false # Setting to true reduces the number of allocations made by each player at the expense of frame rebuilding (e.g. non-instantaneous volume changes) + bufferDurationMs: 400 # The duration of the NAS buffer. Higher values fare better against longer GC pauses. Duration <= 0 to disable JDA-NAS. Minimum of 40ms, lower values may introduce pauses. + frameBufferDurationMs: 5000 # How many milliseconds of audio to keep buffered + opusEncodingQuality: 10 # Opus encoder quality. Valid values range from 0 to 10, where 10 is best quality but is the most expensive on the CPU. + resamplingQuality: LOW # Quality of resampling operations. Valid values are LOW, MEDIUM and HIGH, where HIGH uses the most CPU. + trackStuckThresholdMs: 10000 # The threshold for how long a track can be stuck. A track is stuck if does not return any audio data. + useSeekGhosting: true # Seek ghosting is the effect where whilst a seek is in progress, the audio buffer is read from until empty, or until seek is ready. + youtubePlaylistLoadLimit: 6 # Number of pages at 100 each + playerUpdateInterval: 5 # How frequently to send player updates to clients, in seconds + youtubeSearchEnabled: true + soundcloudSearchEnabled: true + gc-warnings: true + #ratelimit: + #ipBlocks: ["1.0.0.0/8", "..."] # list of ip blocks + #excludedIps: ["...", "..."] # ips which should be explicit excluded from usage by lavalink + #strategy: "RotateOnBan" # RotateOnBan | LoadBalance | NanoSwitch | RotatingNanoSwitch + #searchTriggersFail: true # Whether a search 429 should trigger marking the ip as failing + #retryLimit: -1 # -1 = use default lavaplayer value | 0 = infinity | >0 = retry will happen this numbers times + #youtubeConfig: # Required for avoiding all age restrictions by YouTube, some restricted videos still can be played without. + #email: "" # Email of Google account + #password: "" # Password of Google account + #httpConfig: # Useful for blocking bad-actors from ip-grabbing your music node and attacking it, this way only the http proxy will be attacked + #proxyHost: "localhost" # Hostname of the proxy, (ip or domain) + #proxyPort: 3128 # Proxy port, 3128 is the default for squidProxy + #proxyUser: "" # Optional user for basic authentication fields, leave blank if you don't use basic auth + #proxyPassword: "" # Password for basic authentication + +metrics: + prometheus: + enabled: false + endpoint: /metrics + +sentry: + dsn: "" + environment: "" +# tags: +# some_key: some_value +# another_key: another_value + +logging: + file: + path: ./logs/ + + level: + root: INFO + lavalink: INFO + + request: + enabled: true + includeClientInfo: true + includeHeaders: false + includeQueryString: true + includePayload: true + maxPayloadLength: 10000 + + + logback: + rollingpolicy: + max-file-size: 1GB + max-history: 30 \ No newline at end of file