From 048e93fef01ba840fcd991d9b8471ba5771db158 Mon Sep 17 00:00:00 2001 From: Samuel ORTION Date: Mon, 22 Aug 2022 06:22:30 +0200 Subject: [PATCH] Spliiting to far may not be the solution --- .dockerignore | 3 + .env | 13 ++- .gitignore | 2 + docker-compose.yml | 104 ++++++++++++------ docker/all/Dockerfile | 15 ++- docker/database/init/00-create-init-sql.sh | 12 ++ .../database/init/01-databases.sql.template | 6 + docker/nginx/Dockerfile | 25 +++++ docker/nginx/nginx.conf.template | 56 ++++++++++ docker/recording/Dockerfile | 19 +++- docker/symfony/Dockerfile | 56 ++++++++++ docker/www/Dockerfile | 0 docs/DOCKER.md | 60 ++++++++++ uninstal.sh => uninstall.sh | 5 +- www/.gitignore | 1 - www/nginx.conf.template | 4 +- www/src/Controller/HomeController.php | 2 +- 17 files changed, 333 insertions(+), 50 deletions(-) create mode 100644 docker/database/init/00-create-init-sql.sh create mode 100644 docker/database/init/01-databases.sql.template create mode 100644 docker/nginx/Dockerfile create mode 100644 docker/nginx/nginx.conf.template create mode 100644 docker/symfony/Dockerfile delete mode 100644 docker/www/Dockerfile create mode 100644 docs/DOCKER.md rename uninstal.sh => uninstall.sh (94%) diff --git a/.dockerignore b/.dockerignore index 4585e05..1cac819 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,3 +2,6 @@ var .venv .github .ideas +media +daemon/systemd +analyzer diff --git a/.env b/.env index 75af76d..cc93515 100644 --- a/.env +++ b/.env @@ -1 +1,12 @@ -CUDA_VISIBLE_DEVICES="" \ No newline at end of file +# BirdNET-Analyzer environment +CUDA_VISIBLE_DEVICES="" + +# BirdNET-stream environment +DATABASE_USER="birdnet" +DATABASE_PASSWORD="secret" +DATABASE_PORT="3306" # Change this if you have already a running MySQL server on the host +MYSQL_ROOT_PASSWORD="secret" + +RECORDS_FOLDER="./var/chunks" +CHARTS_FOLDER="./var/charts" +SERVER_NAME="birdnet.lan" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 68306b0..d1c8dd9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ var/ /.venv/ .env +.env.local +!.env.local.example species_list.txt diff --git a/docker-compose.yml b/docker-compose.yml index fb0afef..d1acb62 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,36 +1,76 @@ -version: '3.8' +version: '3.9' + +services: + # recording: + # container_name: birdnet_recording + # build: + # context: . + # dockerfile: ./docker/recording/Dockerfile + # restart: unless-stopped + # environment: + # - CHUNK_FOLDER=${CHUNK_FOLDER:-/media/birdnet/records} + # volumes: + # - ./var/:/media/birdnet/records + # # Allow container to access to the hosts microphone + # devices: + # - /dev/snd + + # analyzer: + # container_name: birdnet_analyzer + # build: + # context: ./analyzer/ + # dockerfile: ./Dockerfile + + + # db: + # container_name: birdnet_database + # image: mariadb:latest + # command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci + # ports: + # - '3307:3306' + # networks: + # - birdnet_network + # environment: + # MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-secret}' + # MYSQL_DATABASE: ${DATABASE:-birdnet} + # MYSQL_USER: ${DATABASE_USER:-birdnet} + # MYSQL_PASSWORD: ${DATABASE_PASSWORD:-secret} + # volumes: + # - ./docker/database/init:/docker-entrypoint-initdb.d + # restart: unless-stopped + + symfony: + container_name: birdnet_symfony + hostname: birdnet.symfony + build: + context: . + dockerfile: ./docker/symfony/Dockerfile + environment: + restart: unless-stopped + volumes: + networks: + - birdnet_network + depends_on: + - db + + nginx: + container_name: birdnet_nginx + hostname: birdnet.nginx + build: + context: . + dockerfile: ./docker/nginx/Dockerfile + ports: + - '81:80' + - '444:443' + environment: + - PHP_FPM_PORT=${PHP_FPM_PORT:-9001} + - PHP_FPM_HOST=${PHP_FPM_HOST:-birdnet.php-fpm} + networks: + - birdnet_network + restart: unless-stopped networks: birdnet_network: -services: - # database: - # container_name: birdnet_database - # image: - - php: - container_name: birdnet_php - image: php:8.1-fpm - ports: - - "${PHP_FPM_PORT:-9001}:9000" - - - nginx: - container_name: birdnet_nginx - build: - context: ./docker/ - environment: - SERVER_NAME: ${SERVER_NAME:-birdnet.local} - PHP_FPM_PORT: ${PHP_FPM_PORT:-9001} - restart: unless-stopped - volumes: - - ./www:/var/www/birdnet/ - - ./www/nginx.conf:/etc/nginx/conf.d/birdnet.conf - ports: - - "81:80" - dependends_on: - - php - - birdnet: - container_name: birdnet_analyzer - image: \ No newline at end of file +volumes: + birdnet: \ No newline at end of file diff --git a/docker/all/Dockerfile b/docker/all/Dockerfile index 8cf0570..5fa4138 100644 --- a/docker/all/Dockerfile +++ b/docker/all/Dockerfile @@ -4,19 +4,24 @@ FROM debian:bullseye ENV REPOSITORY=${REPOSITORY:-https://github.com/UncleSamulus/BirdNET-stream.git} # DEBUG defaults to 1 for descriptive DEBUG logs, 0 for error logs only ENV DEBUG=${DEBUG:-1} -RUN useradd birdnet WORKDIR /home/birdnet +RUN useradd -m -s /bin/bash -G sudo birdnet +USER birdnet # Upgrade system RUN apt-get update && apt-get upgrade -y -# Install sudo +# Install some dependencies RUN apt-get install -y \ sudo \ - git + git \ + curl \ + bash \ + vim \ + systemctl COPY ./install.sh install.sh -RUN bash ./install.sh +RUN ./install.sh -USER birdnet +EXPOSE 443 \ No newline at end of file diff --git a/docker/database/init/00-create-init-sql.sh b/docker/database/init/00-create-init-sql.sh new file mode 100644 index 0000000..c65f518 --- /dev/null +++ b/docker/database/init/00-create-init-sql.sh @@ -0,0 +1,12 @@ +#! /usr/bin/bash + +if [[ -z "${MYSQL_USER}" ]]; then + MYSQL_USER="birdnet" + echo "Defaults MYSQL_USER to $MYSQL_USER" +fi +if [[ -z "${MYSQL_USER_PASSWORD}" ]]; then + echo "MYSQL_ROOT_PASSWORD is not set" + exit 1 +fi +sed -i "s//$MYSQL_USER/g" ./01-databases.sql.template ./01-databases.sql +sed -i "s//$MYSQL_USER_PASSWORD/g" ./01-databases.sql.template ./01-databases.sql \ No newline at end of file diff --git a/docker/database/init/01-databases.sql.template b/docker/database/init/01-databases.sql.template new file mode 100644 index 0000000..a9cfb31 --- /dev/null +++ b/docker/database/init/01-databases.sql.template @@ -0,0 +1,6 @@ +CREATE DATABASE IF NOT EXISTS `birdnet_observations`; +CREATE DATABASE IF NOT EXISTS `birdnet_default`; + +CREATE USER ''@'localhost' IDENTIFIED BY ''; +GRANT ALL PRIVILEGES ON birdnet_observations.* TO ''@'%'; +GRANT ALL PRIVILEGES ON birdnet_default.* TO ''@'%'; \ No newline at end of file diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile new file mode 100644 index 0000000..4cbf3f0 --- /dev/null +++ b/docker/nginx/Dockerfile @@ -0,0 +1,25 @@ +FROM nginx:latest + +ENV PHP_FPM_PORT=${PHP_FPM_PORT:-9000} + +ENV SERVER_NAME=${SERVER_NAME:-birdnet.lan} +ENV PROJECT_ROOT=${PROJECT_ROOT:-/opt/birdnet} +ENV SYMFONY_PUBLIC=${SYMFONY_PUBLIC:-${PROJECT_ROOT}/www/public} + +USER root +COPY docker/nginx/nginx.conf.template /etc/nginx/sites-available/birdnet.conf +RUN ln -s /etc/nginx/sites-available/birdnet.conf /etc/nginx/sites-enabled/birdnet.conf \ + && sed -i "s||${SERVER_NAME}|g" /etc/nginx/sites-available/birdnet.conf \ + && sed -i "s||${SYMFONY_PUBLIC}|g" /etc/nginx/sites-available/birdnet.conf \ + && sed -i "s||${RECORDS_DIR}|g" /etc/nginx/sites-available/birdnet.conf \ + && sed -i "s||${CHARTS_DIR}|g" /etc/nginx/sites-available/birdnet.conf +RUN mkdir -p /etc/nginx/certs/birdnet +WORKDIR /etc/nginx/certs/birdnet +RUN openssl req -x509 -newkey rsa:4096 -keyout privkey.pem -out fullchain.pem -sha256 -days 365 -nodes --subj "/CN=${SERVER_NAME}" +RUN sed -i "s||/etc/nginx/certs/birdnet/fullchain.pem|g" /etc/nginx/sites-available/birdnet.conf \ + && sed -i "s||/etc/nginx/certs/birdnet/privkey.pem|g" /etc/nginx/sites-available/birdnet.conf +RUN nginx -t + +EXPOSE 443 +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/docker/nginx/nginx.conf.template b/docker/nginx/nginx.conf.template new file mode 100644 index 0000000..03cc61f --- /dev/null +++ b/docker/nginx/nginx.conf.template @@ -0,0 +1,56 @@ +server { + listen 80; + server_name ; + + location / { + return 302 https://$host$request_uri; + } + + location /.well-known/acme-challenge { + alias /var/www/html/.well-known/acme-challenge; + allow all; + } +} + +server { + listen 443 ssl; + server_name ; + + fastcgi_buffers 16 16k; + fastcgi_buffer_size 32k; + + root ; + + ssl_certificate ; + ssl_certificate_key ; + + index index.php; + + location / { + try_files $uri $uri/ /index.php$is_args$args; + } + + location ^~ /media/records { + autoindex on; + alias ; + } + + location ^~ /media/charts { + autoindex on; + alias ; + } + + location ~ \.php$ { + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass unix:/run/php/php8.1-fpm.sock; + fastcgi_index index.php; + include fastcgi.conf; + } + + location /stream { + proxy_pass http://localhost:8000/stream; + } + + access_log /var/log/nginx/birdnet-access.log; + error_log /var/log/nginx/birdnet-error.log error; +} diff --git a/docker/recording/Dockerfile b/docker/recording/Dockerfile index 5f1d603..83ebbf0 100644 --- a/docker/recording/Dockerfile +++ b/docker/recording/Dockerfile @@ -1,16 +1,25 @@ # Recording container for BirdNET-stream -# Reference: https://leimao.github.io/blog/Docker-Container-Audio/ +# References: +# - https://leimao.github.io/blog/Docker-Container-Audio/ +# - https://askubuntu.com/questions/972510/how-to-set-alsa-default-device-to-pulseaudio-sound-server-on-docker FROM debian:bullseye ENV DEBIAN_FRONTEND noninteractive # Install packages dependencies - -RUN apt-get update && \ - apt-get install apt-utils \ - && apt-get install -y --no-install-recommends \ +RUN apt-get update && apt-get upgrade -y \ + && apt-get install -y \ + --no-install-recommends \ libasound2 \ alsa-utils \ libsndfile1-dev \ + && apt-get install -y ffmpeg \ && apt-get clean + +RUN mkdir -p /opt/birdnet/ +WORKDIR /opt/birdnet/ +COPY config ./config +COPY daemon/birdnet_recording.sh /usr/local/bin/birdnet_recording.sh + +ENTRYPOINT ["/usr/local/bin/birdnet_recording.sh"] \ No newline at end of file diff --git a/docker/symfony/Dockerfile b/docker/symfony/Dockerfile new file mode 100644 index 0000000..b14f3f9 --- /dev/null +++ b/docker/symfony/Dockerfile @@ -0,0 +1,56 @@ +ARG PHP_VERSION=${PHP_VERSION:-8.1} +FROM php:${PHP_VERSION} +ENV PROJECT_ROOT=${PROJECT_ROOT:-/opt/birdnet} +ENV SYMFONY_PUBLIC=${SYMFONY_PUBLIC:-${PROJECT_ROOT}/www/public} + +RUN apt-get update && apt-get upgrade -y \ + && apt-get install -y \ + nginx \ + curl \ + gzip \ + git \ + vim \ + && apt-get clean + +# Install composer +RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \ + && php composer-setup.php --install-dir=/usr/local/bin --filename=composer + + +ENV NODE_VERSION="16.17.0" +ENV NVM_DIR="/usr/local/nvm" +RUN mkdir ${NVM_DIR} +RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash +RUN . "$NVM_DIR/nvm.sh" \ + && nvm install ${NODE_VERSION} \ + && nvm use ${NODE_VERSION} \ + && nvm alias default ${NODE_VERSION} \ + && npm install -g yarn +ENV PATH="$PATH:/usr/local/nvm/versions/node/v${NODE_VERSION}/bin" + +WORKDIR ${PROJECT_ROOT} +RUN chown -R www-data:www-data "${PROJECT_ROOT}" +# Install composer dependencies +USER www-data +WORKDIR ${PROJECT_ROOT}/www +RUN composer install +# Install yarn dependencies +RUN . "$NVM_DIR/nvm.sh" && yarn install && yarn build +USER root +COPY docker/www/nginx.conf.template /etc/nginx/sites-available/birdnet.conf +RUN ln -s /etc/nginx/sites-available/birdnet.conf /etc/nginx/sites-enabled/birdnet.conf \ + && sed -i "s||${SERVER_NAME}|g" /etc/nginx/sites-available/birdnet.conf \ + && sed -i "s||${SYMFONY_PUBLIC}|g" /etc/nginx/sites-available/birdnet.conf \ + && sed -i "s||${RECORDS_DIR}|g" /etc/nginx/sites-available/birdnet.conf \ + && sed -i "s||${CHARTS_DIR}|g" /etc/nginx/sites-available/birdnet.conf +RUN mkdir -p /etc/nginx/certs/birdnet +WORKDIR /etc/nginx/certs/birdnet +RUN openssl req -x509 -newkey rsa:4096 -keyout privkey.pem -out fullchain.pem -sha256 -days 365 -nodes --subj "/CN=${SERVER_NAME}" +RUN sed -i "s||/etc/nginx/certs/birdnet/fullchain.pem|g" /etc/nginx/sites-available/birdnet.conf \ + && sed -i "s||/etc/nginx/certs/birdnet/privkey.pem|g" /etc/nginx/sites-available/birdnet.conf +RUN nginx -t + +EXPOSE 443 +EXPOSE 80 +CMD [""] +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/docker/www/Dockerfile b/docker/www/Dockerfile deleted file mode 100644 index e69de29..0000000 diff --git a/docs/DOCKER.md b/docs/DOCKER.md new file mode 100644 index 0000000..79555c5 --- /dev/null +++ b/docs/DOCKER.md @@ -0,0 +1,60 @@ +# Use docker to run BirdNET-stream + +There are two ways to run BirdNET-stream using docker: a "all in one" container, running all services on the same container, or using a splitted approach, running each service on a separate container. + +## Prerequisites + +- docker +- docker-compose (for splitted approach) +- git + +## Using the all in one container (not working yet) + +The all in one container is a container that runs all services on the same container. + +You can follow the instructions in [./docker/all/README.md](./docker/all/README.md) to create this container. + +## Using the splitted approach (recommended) + +The splitted approach uses docker-compose and a docker container for each service. + +This is the recommended approach to run BirdNET-stream while using docker. + +Thirst of of all, you need to clone the repository. + +```bash +mkdir ~/Documents/BirdNET-stream +cd ~/Documents/BirdNET-stream +git clone -b main https://github.com/UncleSamulus/BirdNET-stream.git . +``` + +Then, run docker-compose: + +```bash +docker-compose up +``` + +## Building and running each of the containers + +### birdnet_recording container + +Building: +```bash +docker build -f ./docker/recording/Dockerfile -t birdnet_recording:latest . +``` +Running +```bash +docker run --rm --device /dev/snd birdnet_recording:latest +``` + +### birdnet_www container + +Building: +```bash +docker build -f ./docker/www/Dockerfile -t birdnet_www:latest . +``` + +Running +```bash +docker run --rm birdnet_www:latest +``` \ No newline at end of file diff --git a/uninstal.sh b/uninstall.sh similarity index 94% rename from uninstal.sh rename to uninstall.sh index 36e4627..31df398 100644 --- a/uninstal.sh +++ b/uninstall.sh @@ -27,6 +27,7 @@ uninstall_birdnet_services() { sudo systemctl stop "$service" sudo systemctl disable "$service" sudo rm -f "/etc/systemd/system/$service" + sudo systemctl daemon-reload done debug "Done removing systemd services" } @@ -36,6 +37,4 @@ uninstall_webapp() { debug "Removing nginx server configuration" sudo unlink /etc/nginx/sites-enabled/birdnet-stream.conf sudo systemctl restart nginx - debug "Removing webapp directory" - sudo rm -rf $WORKDIR -} \ No newline at end of file +} diff --git a/www/.gitignore b/www/.gitignore index e3d09c7..f6bc5ec 100644 --- a/www/.gitignore +++ b/www/.gitignore @@ -8,7 +8,6 @@ /public/bundles/ /var/ /vendor/ -yarn.lock ###< symfony/framework-bundle ### ###> symfony/webpack-encore-bundle ### diff --git a/www/nginx.conf.template b/www/nginx.conf.template index cb34e56..5ff5628 100644 --- a/www/nginx.conf.template +++ b/www/nginx.conf.template @@ -1,6 +1,6 @@ server { listen 80; - server_name birdnet.lab.home; + server_name ; location / { return 302 https://$host$request_uri; @@ -14,7 +14,7 @@ server { server { listen 443 ssl; - server_name birdnet.lab.home; + server_name ; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; diff --git a/www/src/Controller/HomeController.php b/www/src/Controller/HomeController.php index 787f43f..ce4c2cb 100644 --- a/www/src/Controller/HomeController.php +++ b/www/src/Controller/HomeController.php @@ -77,7 +77,7 @@ class HomeController extends AbstractController $files = glob($this->getParameter('kernel.project_dir') . '/../var/charts/*.png'); usort($files, function($a, $b) { - return filemtime($b) - filemtime($a); + return filemtime($a) - filemtime($b); }); $last_chart = basename(array_pop($files)); return $last_chart;