Project One-Click: All-in-One Installations of Docker Extensions and CDVR Custom Channels

I forgot about that little gotcha on Synology. Unfortunately I can't create directories on the host from inside the OliveTin container (except on paths already bound to OliveTin). But, I could add another "confirmation" check box reminding Synology users of the need to do this before clicking "Start".

Your input, and testing, are much appreciated!

You also might want to add notes that users running Synology Container Manager, Windows and Mac Docker Desktop need to use host NETWORK_MODE, but Windows and Mac Docker Desktop don't support that, so they're SOL.

Good news it looks like windows users might not be locked out from 4.34 Docker release notes:

Host networking is supported on Docker Desktop version 4.34 and later. To enable this feature:

Sign in to your Docker account in Docker Desktop.
Navigate to Settings.
Under the Resources tab, select Network.
Check the Enable host networking option.
Select Apply and restart.
This feature works in both directions. This means you can access a server that is running in a container from your host and you can access servers running on your host from any container that is started with host networking enabled. TCP as well as UDP are supported as communication protocols.

Examples
The following command starts netcat in a container that listens on port 8000:



 docker run --rm -it --net=host nicolaka/netshoot nc -lkv 0.0.0.0 8000
Port 8000 will then be available on the host and you can connect to it with the following command from another terminal:


 nc localhost 8000
3 Likes

Well the good news is it created a Channels DVR container!
The bad news is the compose sent didn't enable host mode networking or hardware transcoding.
Also, when it creates the Channels DVR container and you go into the Channels DVR web admin UI, you need to know where your recording directory is mapped to in the container. (I figured it out, but other users will be stumped). The way you set it up, it's /shares/DVR and capitalization matters.



OliveTin Standard Output
JSON response from http://192.168.1.4:9000/api/stacks?type=2&method=string&endpointId=2:
{"Id":3,"Name":"channels-dvr","Type":2,"EndpointId":2,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"TAG","value":"tve"},{"name":"HOST_PORT","value":"8589"},{"name":"CHANNELS_PORT","value":"8589"},{"name":"TZ","value":"America/Los_Angeles"},{"name":"HOST_DIR","value":"/volume1/docker"},{"name":"DVR_SHARE","value":"/volume1/ChDVRpoc"},{"name":"NETWORK_MODE","value":"host"},{"name":"DEVICES","value":"true"}],"ResourceControl":{"Id":3,"ResourceId":"2_channels-dvr","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/3","CreationDate":1726344287,"CreatedBy":"my_portainer_username","UpdateDate":0,"UpdatedBy":"","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":"","IsComposeFormat":false}
true
OliveTin Standard Error
++ basename /config/channels-dvr.sh
+ extension=channels-dvr.sh
+ extension=channels-dvr
+ cp /config/channels-dvr.env /tmp
+ envFile=/tmp/channels-dvr.env
+ envVars=("TAG=$1" "HOST_PORT=$2" "CHANNELS_PORT=$3" "TZ=$4" "HOST_DIR=$5" "DVR_SHARE=$6" "VOL_EXTERNAL=$7" "VOL_NAME=$8" "NETWORK_MODE=$9" "DEVICES=${10}")
+ printf '%s\n' TAG=tve HOST_PORT=8589 CHANNELS_PORT=8589 TZ=America/Los_Angeles HOST_DIR=/volume1/docker DVR_SHARE=/volume1/ChDVRpoc VOL_EXTERNAL=# VOL_NAME=# NETWORK_MODE=host DEVICES=true
+ sed -i /=#/d /tmp/channels-dvr.env
+ /config/portainerstack.sh channels-dvr
+ stackName=channels-dvr
+ portainerHost=192.168.1.4
+ curl -s -o /dev/null http://192.168.1.4:9000
+ portainerURL='http://192.168.1.4:9000/api/stacks?type=2&method=string&endpointId=2'
+ portainerToken=REDACTED
+ cp /config/channels-dvr.yaml /tmp
+ stackFile=/tmp/channels-dvr.yaml
+ envFile=/tmp/channels-dvr.env
++ grep DVR_SHARE= /tmp/channels-dvr.env
++ grep -v /
++ awk -F= '{print $2}'
+ dockerVolume=
++ grep VOL_EXTERNAL= /tmp/channels-dvr.env
++ grep -v '#'
++ awk -F= '{print $2}'
+ volumeExternal=
++ grep VOL_NAME= /tmp/channels-dvr.env
++ grep -v '#'
++ awk -F= '{print $2}'
+ volumeName=
+ [[ -n '' ]]
++ sed 's/\\/\\\\/g' /tmp/channels-dvr.yaml
++ sed 's/"/\\"/g'
++ awk '{printf "%s\\n", $0}'
+ stackContent='version: '\''3.9'\''\nservices:\n  # 2024.09.13\n  # Docker Hub home for this project: https://hub.docker.com/r/fancybits/channels-dvr\n  channels-dvr:\n    image: fancybits/channels-dvr:${TAG}\n    container_name: channels-dvr\n    #devices:\n      #- /dev/dri:/dev/dri\n    ports:\n      - ${HOST_PORT}:${CHANNELS_PORT}\n    environment:\n      - CHANNELS_PORT=${CHANNELS_PORT}\n      - TZ=${TZ}\n    volumes:\n      - ${HOST_DIR}/channels-dvr:/channels-dvr\n      - ${DVR_SHARE}:/shares/DVR\n    #network_mode: host\n    restart: unless-stopped\n#volumes: # use this section if you'\''ve setup a docker volume named channels-dvr, with CIFS or NFS, to bind to /channels-dvr inside the container\n  #channels-dvr:\n    #external: ${VOL_EXTERNAL}\n    #name: ${VOL_NAME}\n'
+ stackEnvVars='['
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "tve"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "tve"},{"name": "HOST_PORT", "value": "8589"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "tve"},{"name": "HOST_PORT", "value": "8589"},{"name": "CHANNELS_PORT", "value": "8589"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "tve"},{"name": "HOST_PORT", "value": "8589"},{"name": "CHANNELS_PORT", "value": "8589"},{"name": "TZ", "value": "America/Los_Angeles"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "tve"},{"name": "HOST_PORT", "value": "8589"},{"name": "CHANNELS_PORT", "value": "8589"},{"name": "TZ", "value": "America/Los_Angeles"},{"name": "HOST_DIR", "value": "/volume1/docker"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "tve"},{"name": "HOST_PORT", "value": "8589"},{"name": "CHANNELS_PORT", "value": "8589"},{"name": "TZ", "value": "America/Los_Angeles"},{"name": "HOST_DIR", "value": "/volume1/docker"},{"name": "DVR_SHARE", "value": "/volume1/ChDVRpoc"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "tve"},{"name": "HOST_PORT", "value": "8589"},{"name": "CHANNELS_PORT", "value": "8589"},{"name": "TZ", "value": "America/Los_Angeles"},{"name": "HOST_DIR", "value": "/volume1/docker"},{"name": "DVR_SHARE", "value": "/volume1/ChDVRpoc"},{"name": "NETWORK_MODE", "value": "host"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "tve"},{"name": "HOST_PORT", "value": "8589"},{"name": "CHANNELS_PORT", "value": "8589"},{"name": "TZ", "value": "America/Los_Angeles"},{"name": "HOST_DIR", "value": "/volume1/docker"},{"name": "DVR_SHARE", "value": "/volume1/ChDVRpoc"},{"name": "NETWORK_MODE", "value": "host"},{"name": "DEVICES", "value": "true"},'
+ IFS==
+ read -r key value
+ stackEnvVars='[{"name": "TAG", "value": "tve"},{"name": "HOST_PORT", "value": "8589"},{"name": "CHANNELS_PORT", "value": "8589"},{"name": "TZ", "value": "America/Los_Angeles"},{"name": "HOST_DIR", "value": "/volume1/docker"},{"name": "DVR_SHARE", "value": "/volume1/ChDVRpoc"},{"name": "NETWORK_MODE", "value": "host"},{"name": "DEVICES", "value": "true"}]'
++ cat
+ stackJSON='{
  "Name": "channels-dvr",
  "SwarmID": "",
  "StackFileContent": "version: '\''3.9'\''\nservices:\n  # 2024.09.13\n  # Docker Hub home for this project: https://hub.docker.com/r/fancybits/channels-dvr\n  channels-dvr:\n    image: fancybits/channels-dvr:${TAG}\n    container_name: channels-dvr\n    #devices:\n      #- /dev/dri:/dev/dri\n    ports:\n      - ${HOST_PORT}:${CHANNELS_PORT}\n    environment:\n      - CHANNELS_PORT=${CHANNELS_PORT}\n      - TZ=${TZ}\n    volumes:\n      - ${HOST_DIR}/channels-dvr:/channels-dvr\n      - ${DVR_SHARE}:/shares/DVR\n    #network_mode: host\n    restart: unless-stopped\n#volumes: # use this section if you'\''ve setup a docker volume named channels-dvr, with CIFS or NFS, to bind to /channels-dvr inside the container\n  #channels-dvr:\n    #external: ${VOL_EXTERNAL}\n    #name: ${VOL_NAME}\n",
  "Env": [{"name": "TAG", "value": "tve"},{"name": "HOST_PORT", "value": "8589"},{"name": "CHANNELS_PORT", "value": "8589"},{"name": "TZ", "value": "America/Los_Angeles"},{"name": "HOST_DIR", "value": "/volume1/docker"},{"name": "DVR_SHARE", "value": "/volume1/ChDVRpoc"},{"name": "NETWORK_MODE", "value": "host"},{"name": "DEVICES", "value": "true"}]
}'
+ echo 'JSON response from http://192.168.1.4:9000/api/stacks?type=2&method=string&endpointId=2:'
++ curl -k -X POST -H 'Content-Type: application/json' -H 'X-API-Key: REDACTED' -d '{
  "Name": "channels-dvr",
  "SwarmID": "",
  "StackFileContent": "version: '\''3.9'\''\nservices:\n  # 2024.09.13\n  # Docker Hub home for this project: https://hub.docker.com/r/fancybits/channels-dvr\n  channels-dvr:\n    image: fancybits/channels-dvr:${TAG}\n    container_name: channels-dvr\n    #devices:\n      #- /dev/dri:/dev/dri\n    ports:\n      - ${HOST_PORT}:${CHANNELS_PORT}\n    environment:\n      - CHANNELS_PORT=${CHANNELS_PORT}\n      - TZ=${TZ}\n    volumes:\n      - ${HOST_DIR}/channels-dvr:/channels-dvr\n      - ${DVR_SHARE}:/shares/DVR\n    #network_mode: host\n    restart: unless-stopped\n#volumes: # use this section if you'\''ve setup a docker volume named channels-dvr, with CIFS or NFS, to bind to /channels-dvr inside the container\n  #channels-dvr:\n    #external: ${VOL_EXTERNAL}\n    #name: ${VOL_NAME}\n",
  "Env": [{"name": "TAG", "value": "tve"},{"name": "HOST_PORT", "value": "8589"},{"name": "CHANNELS_PORT", "value": "8589"},{"name": "TZ", "value": "America/Los_Angeles"},{"name": "HOST_DIR", "value": "/volume1/docker"},{"name": "DVR_SHARE", "value": "/volume1/ChDVRpoc"},{"name": "NETWORK_MODE", "value": "host"},{"name": "DEVICES", "value": "true"}]
}' 'http://192.168.1.4:9000/api/stacks?type=2&method=string&endpointId=2'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100  1187    0     0  100  1187      0    985  0:00:01  0:00:01 --:--:--   985
100  2049  100   862  100  1187    410    565  0:00:02  0:00:02 --:--:--   977
100  2049  100   862  100  1187    410    565  0:00:02  0:00:02 --:--:--   977
+ portainerResponse='{"Id":3,"Name":"channels-dvr","Type":2,"EndpointId":2,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"TAG","value":"tve"},{"name":"HOST_PORT","value":"8589"},{"name":"CHANNELS_PORT","value":"8589"},{"name":"TZ","value":"America/Los_Angeles"},{"name":"HOST_DIR","value":"/volume1/docker"},{"name":"DVR_SHARE","value":"/volume1/ChDVRpoc"},{"name":"NETWORK_MODE","value":"host"},{"name":"DEVICES","value":"true"}],"ResourceControl":{"Id":3,"ResourceId":"2_channels-dvr","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/3","CreationDate":1726344287,"CreatedBy":"my_portainer_username","UpdateDate":0,"UpdatedBy":"","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":"","IsComposeFormat":false}'
+ [[ -z {"Id":3,"Name":"channels-dvr","Type":2,"EndpointId":2,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"TAG","value":"tve"},{"name":"HOST_PORT","value":"8589"},{"name":"CHANNELS_PORT","value":"8589"},{"name":"TZ","value":"America/Los_Angeles"},{"name":"HOST_DIR","value":"/volume1/docker"},{"name":"DVR_SHARE","value":"/volume1/ChDVRpoc"},{"name":"NETWORK_MODE","value":"host"},{"name":"DEVICES","value":"true"}],"ResourceControl":{"Id":3,"ResourceId":"2_channels-dvr","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/3","CreationDate":1726344287,"CreatedBy":"my_portainer_username","UpdateDate":0,"UpdatedBy":"","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":"","IsComposeFormat":false} ]]
+ echo '{"Id":3,"Name":"channels-dvr","Type":2,"EndpointId":2,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"TAG","value":"tve"},{"name":"HOST_PORT","value":"8589"},{"name":"CHANNELS_PORT","value":"8589"},{"name":"TZ","value":"America/Los_Angeles"},{"name":"HOST_DIR","value":"/volume1/docker"},{"name":"DVR_SHARE","value":"/volume1/ChDVRpoc"},{"name":"NETWORK_MODE","value":"host"},{"name":"DEVICES","value":"true"}],"ResourceControl":{"Id":3,"ResourceId":"2_channels-dvr","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/3","CreationDate":1726344287,"CreatedBy":"my_portainer_username","UpdateDate":0,"UpdatedBy":"","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":"","IsComposeFormat":false}'
+ echo '{"Id":3,"Name":"channels-dvr","Type":2,"EndpointId":2,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"TAG","value":"tve"},{"name":"HOST_PORT","value":"8589"},{"name":"CHANNELS_PORT","value":"8589"},{"name":"TZ","value":"America/Los_Angeles"},{"name":"HOST_DIR","value":"/volume1/docker"},{"name":"DVR_SHARE","value":"/volume1/ChDVRpoc"},{"name":"NETWORK_MODE","value":"host"},{"name":"DEVICES","value":"true"}],"ResourceControl":{"Id":3,"ResourceId":"2_channels-dvr","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/3","CreationDate":1726344287,"CreatedBy":"my_portainer_username","UpdateDate":0,"UpdatedBy":"","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":"","IsComposeFormat":false}'
+ jq -e '.Id != null'
+ exit 0
+ [[ 0 == 1 ]]
+ exit 0
Portainer stack with env vars it created
version: '3.9'
services:
  # 2024.09.13
  # Docker Hub home for this project: https://hub.docker.com/r/fancybits/channels-dvr
  channels-dvr:
    image: fancybits/channels-dvr:${TAG}
    container_name: channels-dvr
    #devices:
      #- /dev/dri:/dev/dri
    ports:
      - ${HOST_PORT}:${CHANNELS_PORT}
    environment:
      - CHANNELS_PORT=${CHANNELS_PORT}
      - TZ=${TZ}
    volumes:
      - ${HOST_DIR}/channels-dvr:/channels-dvr
      - ${DVR_SHARE}:/shares/DVR
    #network_mode: host
    restart: unless-stopped
#volumes: # use this section if you've setup a docker volume named channels-dvr, with CIFS or NFS, to bind to /channels-dvr inside the container
  #channels-dvr:
    #external: ${VOL_EXTERNAL}
    #name: ${VOL_NAME}

TAG=tve
HOST_PORT=8589
CHANNELS_PORT=8589
TZ=America/Los_Angeles
HOST_DIR=/volume1/docker
DVR_SHARE=/volume1/ChDVRpoc
NETWORK_MODE=host
DEVICES=true
1 Like

Would be nice if you could display something like this when the action completes.

A new stack, named channels-dvr has been created in Portainer at http://{PORTAINER_HOST}:9000
You can now access your new Channels DVR container at http://{PORTAINER_HOST}:{HOST_PORT}
Setup Channels DVR to use this container directory /shares/DVR (case sensitive) for storing recordings, since that is mapped to the host directory {DVR_SHARE} you specified.

1 Like

Forgot to update the script that does that in the main repo -- so it's fixed (but haven't built a new container just yet) -- thanks.

I'm a bit less sure of how to deal with this, though adding feedback in standard output is a good suggestion. /shares/DVR is a directory inside the container, and it's as designated by the Channels devs. Here's their recommended compose from Docker Hub:

 channels-dvr:
  image: fancybits/channels-dvr:latest
  container_name: channels-dvr
  network_mode: host
  ports:
    - "8089:8089"
  restart: unless-stopped
  devices:
    - /dev/dri:/dev/dri
  volumes:
    - /mnt/disk/dvr/config:/channels-dvr
    - /mnt/disk/dvr/recordings:/shares/DVR

Have you been doing it a different way with the CDVR containers you've been running? It's possible that directory name has no significance, and could be pretty much anything -- but I don't know that for sure.

For the :/shares/DVR directory, it can be any valid linux path in the container. When the container is created, it will create that path in the container. You have to specify what it is anyway in the Channels DVR setup.
I like this (although it might not work on Windows)

And the issue with ports.
If Channels DVR container is using host network mode, it needs CHANNELS_PORT to change the port Channels DVR uses within the container, since that is the port exposed to the host.
If Channels DVR container is using bridge network mode, it needs just HOST_PORT which is port mapped to the Channels DVR container port 8089.

Using network_mode: host negates the need to map ports (not valid in host mode)

  ports:
    - "8089:8089"

And that compose wouldn't work if the user already had something using port 8089 since the compose doesn't include this

    environment:
      - CHANNELS_PORT=8190                               # MODIFY the host port number to use

This works (appears the port mapping is ignored since host mode was specified)

version: '3.9'
services:
  # 2024.09.13
  # Docker Hub home for this project: https://hub.docker.com/r/fancybits/channels-dvr
  channels-dvr:
    image: fancybits/channels-dvr:${TAG}
    container_name: channels-dvr
    devices:
      - /dev/dri:/dev/dri
    ports:
      - ${HOST_PORT}:${CHANNELS_PORT}
    environment:
      - CHANNELS_PORT=${CHANNELS_PORT}
      - TZ=${TZ}
    volumes:
      - ${HOST_DIR}/channels-dvr:/channels-dvr
      - ${DVR_SHARE}:/shares/DVR
    network_mode: host
    restart: unless-stopped
#volumes: # use this section if you've setup a docker volume named channels-dvr, with CIFS or NFS, to bind to /channels-dvr inside the container
  #channels-dvr:
    #external: ${VOL_EXTERNAL}
    #name: ${VOL_NAME}

TAG=tve
HOST_PORT=8589
CHANNELS_PORT=8589
TZ=America/Los_Angeles
HOST_DIR=/volume1/docker
DVR_SHARE=/volume1/ChDVRpoc


Screenshot 2024-09-14 at 15-49-50 Channels Settings

Don't know how helpful this is but here is one I set up sometime back, just stopped using it because could not get hardware transcoding working.

# channels compose

version: '3.9'
services:
  channels-dvr:
    image: fancybits/channels-dvr:tve
    container_name: channels-dvr
#    network_mode: host
    ports:
      - 192.168.50.149:8089:8089
    environment:
#     - CHANNELS_DVR=192.168.50.219:8089 # Add your Channels DVR server in the form hostname:port or ip:port
#     - CHANNELS_CLIENTS=192.168.50.21 # Space separated list of Channels DVR clients you'd like notifications sent to in the form hostname or IP
#     - UPDATE_YAMLS=true # Set this to true to update config.yaml
#     - UPDATE_SCRIPTS=true # Set this to true to update all included scripts
      - TZ=US/Pacific # Add your local timezone in standard linux format. E.G. US/Eastern, US/Central, US/Mountain, US/Pacific, etc  
    devices:
#      - /dev/dri:/dev/dri
    volumes:
#      - dvr-config:/channels-dvr
      - DVR:/shares/DVR
    restart: unless-stopped  
volumes: # use this section if you've setup a docker volume named channels-dvr, with CIFS or NFS, to bind to /mnt/dvr inside the container
#  dvr-config:
#    external: true
  DVR:
    external: true


channels.env

NVIDIA_VISIBLE_DEVICES=all
NVIDIA_DRIVER_CAPABILITIES=compute,video,utility

then again I'm still fighting to get OliveTin fully functional, using Docker Desktop and I have trouble getting Windows and Linux playing nicely. Then again it's probably me :wink:

And finally, here is what I would want to use, making the path inside the container the same as on the host for the DVR directory. Added DVR_CONTAINER_DIRECTORY

version: '3.9'
services:
  # 2024.09.13
  # Docker Hub home for this project: https://hub.docker.com/r/fancybits/channels-dvr
  channels-dvr:
    image: fancybits/channels-dvr:${TAG}
    container_name: channels-dvr
    devices:
      - /dev/dri:/dev/dri
    ports:
      - ${HOST_PORT}:${CHANNELS_PORT}
    environment:
      - CHANNELS_PORT=${CHANNELS_PORT}
      - TZ=${TZ}
    volumes:
      - ${HOST_DIR}/channels-dvr:/channels-dvr
      - ${DVR_SHARE}:${DVR_CONTAINER_DIRECTORY}
    network_mode: host
    restart: unless-stopped
#volumes: # use this section if you've setup a docker volume named channels-dvr, with CIFS or NFS, to bind to /channels-dvr inside the container
  #channels-dvr:
    #external: ${VOL_EXTERNAL}
    #name: ${VOL_NAME}

TAG=tve
HOST_PORT=8589
CHANNELS_PORT=8589
TZ=America/Los_Angeles
HOST_DIR=/volume1/docker
DVR_SHARE=/volume1/ChDVRpoc
DVR_CONTAINER_DIRECTORY=/volume1/ChDVRpoc



But then I'm not your typical Project One-Click user

I believe we're in sync on the points you've made in your last few posts. I'll make some changes in the morning, and push a new version at some point tomorrow.

I'm planning to do the following:

  • Include the fix for uncommenting devices:, - /dev/dri:/dev/dri, and network_mode: host as required.

  • Comment out ports: and - ${HOST_PORT}:${CHANNELS_PORT} when network_mode: host is being used to avoid confusion.

  • Make the container-side folder an environment variable in - ${DVR_SHARE}:/shares/DVR.

  • Add some additional comments in the descriptions of several fields in the WebUI, and to standard output.

Hopefully that will cover what's been identified as areas for improvement. :slight_smile:

1 Like

@chDVRuser I've implemented the above, along with the ability to spin-up multiple CDVR containers on a single Docker host. Any number used as a CDVR_CONTAINER value will be appended to the stack name, container name and to ${HOST_DIR}/channels-dvr[2, 3, 4 or whatever integer].

Pushed just now, so if you could give it a try when you have a moment I'd appreciate it!

Let me know if there's anything I can do to help. Docker Desktop for Windows definitely has its challenges when it comes to more deploying more "advanced" containers like OliveTin, that need both inbound and outbound network connections -- along with fully functioning WSL integration.

I've had, and fixed, some of these issues in the past, especially related to some of the more subtle types of problems with Docker Desktop's internal data. Ping me in the OliveTin thread if you want to pursue this.

Was looking good


Until I clicked Start

That's all I see

My guess is the error means "#" isn't an integer

  - title: Create a Channels DVR Stack in Portainer
    arguments:
      - name: CDVR_CONTAINER
        type: int
        description: If you have multiple CDVR containers running on a single Docker host, this number will be appended to stack, container and path names. Leave as "#" for none.
        default: "#"

Because using 2 worked.


Portainer Stacks>channels-dvr2

version: '3.9'
services:
  # 2024.09.15
  # Docker Hub home for this project: https://hub.docker.com/r/fancybits/channels-dvr
  channels-dvr:
    image: fancybits/channels-dvr:${TAG}
    container_name: channels-dvr2
    devices:
      - /dev/dri:/dev/dri
    #ports:
      #- ${HOST_PORT}:${CHANNELS_PORT}
    environment:
      - CHANNELS_PORT=${CHANNELS_PORT}
      - TZ=${TZ}
    volumes:
      - ${HOST_DIR}/channels-dvr2:/channels-dvr
      - ${DVR_SHARE}:${DVR_CONTAINER_DIR}
    network_mode: host
    restart: unless-stopped
#volumes: # use this section if you've setup a docker volume named channels-dvr, with CIFS or NFS, to bind to /channels-dvr inside the container
  #channels-dvr:
    #external: ${VOL_EXTERNAL}
    #name: ${VOL_NAME}

TAG=tve
HOST_PORT=8089
CHANNELS_PORT=8689
TZ=America/Los_Angeles
HOST_DIR=/volume1/docker
DVR_SHARE=/volume1/ChDVRpoc2
DVR_CONTAINER_DIR=/volume1/ChDVRpoc2
NETWORK_MODE=host
DEVICES=true
CDVR_CONTAINER=2

Is it possible to display the values for HOST_DIR and DVR_SHARE?
Using ${HOST_DIR} and ${DVR_SHARE} in your config.yaml doesn't display the values.

If I'm running this on a Synology box, I recognize ${HOST_DIR}/channels-dvr and ${DVR_SHARE} need to exist before clicking "Start" (Click to confirm):

I also noticed the same issue with the Post-Install Healthcheck

Add host healthcheck (requires running sudo -E ./fifopipe_hostside.sh "$PATH" from host directory bound to /config first!).

Right you are. Fixed now. Re-pull when you have a moment.

Thanks for the assist in testing!

You have a winner!
Now, if you can only find someone to test it on Windows (not me).

I don't think so, but I see what you're getting at -- so I'll take another look.

In that case that command, including "$PATH" is correct, as shown.

1 Like

And the finishing touches to make it shine would be Project One-Click: All-in-One Installations of Docker Extensions and CDVR Custom Channels - #187 by chDVRuser

UPDATED:

A new stack, named channels-dvr{CDVR_CONTAINER} has been created in Portainer at http://{PORTAINER_HOST}:9000
You can now access your new Channels DVR container at http://{PORTAINER_HOST}:{HOST_PORT} (if bridge network), or http://{PORTAINER_HOST}:{CHANNELS_PORT} (if host network).
Setup Channels DVR to use this container directory {DVR_CONTAINER_DIR} (case sensitive) for storing recordings, since that is mapped to the host directory {DVR_SHARE} you specified.

Not sure if this is possible to include in the STD OUT after success, but would be a nice touch to an otherwise excellent solution.

1 Like

That should be possible. I'll tackle it shortly.

1 Like

Done. New version pushed this AM with improvements to stdout along these lines:

JSON response from http://htpc6:9000/api/stacks?type=2&method=string&endpointId=2:
{"Id":131,"Name":"channels-dvr","Type":2,"EndpointId":2,"SwarmId":"","EntryPoint":"docker-compose.yml","Env":[{"name":"TAG","value":"tve"},{"name":"HOST_PORT","value":"8089"},{"name":"CHANNELS_PORT","value":"8089"},{"name":"TZ","value":"US/Mountain"},{"name":"HOST_DIR","value":"/data"},{"name":"DVR_SHARE","value":"/mnt/dvr"},{"name":"DVR_CONTAINER_DIR","value":"/shares/DVR"},{"name":"NETWORK_MODE","value":"host"}],"ResourceControl":{"Id":108,"ResourceId":"2_channels-dvr","SubResourceIds":[],"Type":6,"UserAccesses":[],"TeamAccesses":[],"Public":false,"AdministratorsOnly":true,"System":false},"Status":1,"ProjectPath":"/data/compose/131","CreationDate":1726494878,"CreatedBy":"admin","UpdateDate":0,"UpdatedBy":"","AdditionalFiles":null,"AutoUpdate":null,"Option":null,"GitConfig":null,"FromAppTemplate":false,"Namespace":"","IsComposeFormat":false}
true
A new stack, named channels-dvr has been created in Portainer at http://htpc6:9000 or https://htpc6:9443
You can now access your new Channels DVR container at http://htpc6:8089 (if bridge network), or http://htpc6:8089 (if host network).
Setup Channels DVR to use this container directory /shares/DVR (case sensitive) for storing recordings, since that is mapped to the host directory /mnt/dvr you specified.

Also, adding a digit to "channels-dvr" to support deploying multiple CDVR servers on a single Docker host, is now a series of choices rather than a free form field entry.