Power & Source of Big Ideas

Going nuts with Docker

Moderators: chensy, FATechsupport

After finally getting my R5S running from NVMe, I've been having much better success with Docker. I thought I'd share some of my config. My R5S is running off an internal 500GB NVMe, a 128GB would be adequate. I've setup a 14GB swap partition, but I've never seen its use go over 20%, so I imagine a 4GB swap might be adequate, but there doesn't seem to be any harm having a bigger one. The swap really helps when resources are stretched like when you index photos with Photoprism.

I'm running the following containers:

    nginx
    certbot
    watchtower
    qbittorrent
    homeassistant
    jellyfin
    photoprism
    mariadb
    adminer
    bookstack

Nginx acts as a reverse proxy, so I can have subdomains:

    mywebsite.com
    homeassistant.mywebsite.com
    jellyfin.mywebsite.com
    photoprism.mywebsite.com
    bookstack.mywebsite.com

I keep all my Docker volumes and media on an external USB3 NVMe. This means if you have to upgrade firmware wiping the internal NVMe, it's easy to pick up where you left off when redeploying the containers.

overview.png
system overview
overview.png (51.63 KiB) Viewed 4996 times

That's with all the containers running but not much load/traffic.
docker_stats.png
docker stats
docker_stats.png (77.08 KiB) Viewed 4996 times

Note: docker stats shows CPU usage per core, so it's 4x100% = 400%. Like when you index photos with Photoprism, the CPU usage might say something like 271%. And in the image above qBittorrent is using of 36.53 of 400%.

########################################################################
First thing I do is change the ports Luci runs on:
########################################################################
vi /etc/config/uhttpd
    8000
    8443
/etc/init.d/uhttpd restart
########################################################################
opkg update
opkg install docker-compose
########################################################################
docker-compose.yml
########################################################################

Code: Select all

services:
  nginx:
    image: nginx:latest
    restart: unless-stopped
    user: "65536"
    environment:
      TZ: 'Australia/Melbourne'
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /mnt/sda1/nginx/config:/etc/nginx/conf.d
      - /mnt/sda1/nginx/logs:/var/log/nginx
      - /mnt/sda1/nginx/nginx.conf:/etc/nginx/nginx.conf
      - /mnt/sda1/nginx/cache:/var/cache/nginx
      - /mnt/sda1/nginx/run:/var/run
      - /mnt/sda1/nginx/html:/usr/share/nginx/html
      - /etc/letsencrypt:/etc/letsencrypt:ro
    depends_on:
      - bookstack
      - homeassistant
      - jellyfin
      - photoprism
    networks:
      my-network:
        ipv4_address: 172.19.0.11

  certbot:
    image: certbot/certbot:latest
    restart: unless-stopped
    user: "65536"
    environment:
      TZ: 'Australia/Melbourne'
    volumes:
      - /etc/letsencrypt:/etc/letsencrypt
      - /var/lib/letsencrypt:/var/lib/letsencrypt
      - /mnt/sda1/nginx/html:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
    command: certonly --webroot --webroot-path=/var/www/certbot --email bob@mail.com -d mywebsite.com --agree-tos --no-eff-email
    networks:
      - my-network

  mariadb:
    image: mariadb:latest
    restart: unless-stopped
    user: "65536"
    environment:
      TZ: 'Australia/Melbourne'
      MARIADB_ROOT_PASSWORD: "top_secret"
    volumes:
      - /mnt/sda1/mariadb/data:/var/lib/mysql
    networks:
      - my-network

  adminer:
    image: adminer:latest
    restart: unless-stopped
    ports:
      - 8082:8080
    networks:
      - my-network

  qbittorrent:
    image: linuxserver/qbittorrent:latest
    restart: unless-stopped
    user: "root"
    environment:
      TZ: 'Australia/Melbourne'
    ports:
      - "8080:8080"
      - "6881:6881"
      - "6881:6881/udp"
    volumes:
      - /mnt/sda1/qbittorrent/config:/config
      - /mnt/sda1/qbittorrent/downloads:/downloads
    networks:
      - my-network

  homeassistant:
    image: homeassistant/home-assistant:latest
    restart: unless-stopped
    environment:
      - TZ=Australia/Melbourne
      - PUID=1000
      - PGID=1000
      - UMASK=007
      - PACKAGES=iputils
    volumes:
      - /mnt/sda1/homeassistant/config:/config
    networks:
      - my-network

  jellyfin:
    image: jellyfin/jellyfin:latest
    restart: unless-stopped
    user: "65536"
    environment:
      TZ: 'Australia/Melbourne'
    volumes:
      - /mnt/sda1/jellyfin/config:/config
      - /mnt/sda1/jellyfin/cache:/cache
      - /mnt/sda1/media:/media
    networks:
      - my-network

  photoprism:
    image: photoprism/photoprism:latest
    restart: unless-stopped
    ports:
      - 2342:2342
    environment:
      TZ: 'Australia/Melbourne'
      PHOTOPRISM_ADMIN_USER: "admin"
      PHOTOPRISM_ADMIN_PASSWORD: "top_secret"
      PHOTOPRISM_DATABASE_DRIVER: "mysql"
      PHOTOPRISM_DATABASE_SERVER: "mariadb:3306"
      PHOTOPRISM_DATABASE_NAME: "photoprism"
      PHOTOPRISM_DATABASE_USER: "photoprism"
      PHOTOPRISM_DATABASE_PASSWORD: "top_secret"
      PHOTOPRISM_SITE_URL: "https://photoprism.mywebsite.com/"
      PHOTOPRISM_ORIGINALS_LIMIT: 1000
      PHOTOPRISM_DEBUG: "false"
      PHOTOPRISM_INDEX_WORKERS: 1
      PHOTOPRISM_WORKERS: 1
    volumes:
      - "/mnt/sda1/photos:/photoprism/originals"
      - "/mnt/sda1/photoprism/import:/photoprism/import"
      - "/mnt/sda1/photoprism/storage:/photoprism/storage"
    depends_on:
      - mariadb
    networks:
      - my-network

  bookstack:
    image: linuxserver/bookstack:latest
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Australia/Melbourne
      - APP_URL=https://bookstack.mywebsite.com
      - DB_HOST=mariadb:3306
      - DB_DATABASE=bookstack
      - DB_USERNAME=bookstack
      - DB_PASSWORD='top_secret'
    volumes:
      - /mnt/sda1/bookstack/config:/config
      - /mnt/sda1/bookstack/uploads:/var/www/html/public/uploads
    depends_on:
      - mariadb
    ports:
      - "6875:80"
    networks:
      - my-network

  watchtower:
    image: containrrr/watchtower:latest
    restart: unless-stopped
    environment:
      TZ: 'Australia/Melbourne'
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    networks:
      - my-network

networks:
  my-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.19.0.0/16

########################################################################
nginx.conf
########################################################################

Code: Select all

user  nginx;
worker_processes  1;

events {
    worker_connections 1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    # Upstream servers
    upstream bookstack {
        server bookstack:80;
    }
    upstream homeassistant {
        server homeassistant:8123;
    }
    upstream jellyfin {
        server jellyfin:8096;
    }
    upstream photoprism {
        server photoprism:2342;
    }


    server {
        listen 80;
        server_name *.mywebsite.com;

        # Redirect all HTTP traffic to HTTPS
        return 301 https://$host$request_uri;
    }


    # HTTPS server block for Home Page
    server {
        listen 443 ssl;
        server_name mywebsite.com;

        # SSL/TLS configurations
        ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem;

        location / {
            root /usr/share/nginx/html;
            index index.html;
        }
    }


    # HTTPS server block for BookStack
    server {
        listen 443 ssl;
        server_name bookstack.mywebsite.com;

        # SSL/TLS configurations
        ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem;

        location / {
            proxy_pass http://bookstack;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }


    # HTTPS server block for Home Assistant
    server {
        listen 443 ssl;
        server_name homeassistant.mywebsite.com;

        # SSL/TLS configurations
        ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem;

        location / {
            proxy_pass http://homeassistant;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }
    }


    # HTTPS server block for Jellyfin
    server {
        listen 443 ssl;
        server_name jellyfin.mywebsite.com;

        # SSL/TLS configurations
        ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem;

        location / {
            proxy_pass http://jellyfin;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }


    # HTTPS server block for Photoprism
    server {
        listen 443 ssl;
        server_name photoprism.mywebsite.com;

        # SSL/TLS configurations
        ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem;

        location / {
            proxy_pass http://photoprism;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }


}

########################################################################
MariaDB
########################################################################

Code: Select all

-- Create BookStack database and user
CREATE DATABASE IF NOT EXISTS bookstack;
CREATE USER IF NOT EXISTS 'bookstack'@'%' IDENTIFIED BY 'top_secret';
GRANT ALL PRIVILEGES ON bookstack.* TO 'bookstack'@'%';

-- Create Photoprism database and user
CREATE DATABASE IF NOT EXISTS photoprism;
CREATE USER IF NOT EXISTS 'photoprism'@'%' IDENTIFIED BY 'top_secret';
GRANT ALL PRIVILEGES ON photoprism.* TO 'photoprism'@'%';

FLUSH PRIVILEGES;

ALTER DATABASE bookstack
    CHARACTER SET = 'utf8mb4'
    COLLATE = 'utf8mb4_unicode_ci';

ALTER DATABASE photoprism
    CHARACTER SET = 'utf8mb4'
    COLLATE = 'utf8mb4_unicode_ci';

########################################################################
Docker forwards various ports that don't show up in Luci:
forwarding.png
Port forwarding
forwarding.png (44.27 KiB) Viewed 4987 times

You can restrict access to the LAN by specifying the NanoPi IP address in the docker-compose.yml

Code: Select all

  adminer:
    image: adminer:latest
    restart: unless-stopped
    ports:
      - 10.0.0.1:8082:8080
    networks:
      - my-network

This can be useful if you don't want the login accessible over the internet. For example, if you don't need access over the internet or for services that don't support MFA.

Who is online

In total there is 1 user online :: 0 registered, 0 hidden and 1 guest (based on users active over the past 5 minutes)
Most users ever online was 5185 on Wed Jan 22, 2020 1:44 pm

Users browsing this forum: No registered users and 1 guest