Skip to content

Commit

Permalink
Workflow build Docker image with arm64,amd64 (#124)
Browse files Browse the repository at this point in the history
* Workflow build Docker image with arm64,amd64

Add entrypoint.sh, start with custom UserID/GroupID
Rework docker-compose
Rework dockerfile

* Volumes provided for data

Backward compatibility for old key.txt path
Additional documentation provided on README.md

* Dokcerfile install with pip requirements.txt

* Fix key.txt permissions
  • Loading branch information
Generator authored Jan 4, 2024
1 parent 570260c commit 7cac445
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 95 deletions.
31 changes: 6 additions & 25 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,25 +1,6 @@
**/__pycache__
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
README.md
*
!*.py
!lib
!plugins
!requirements.txt
!entrypoint.sh
71 changes: 40 additions & 31 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
name: Build & Push Cabernet

on:
on:
push:
# Publish `master` as Docker `latest` image.
branches:
- master
- dev

# Publish `v1.2.3` tags as releases.
tags:
Expand All @@ -13,41 +14,49 @@ on:
# Run tests for any PRs.
pull_request:

env:
IMAGE_NAME: cabernet

jobs:
# Push image to GitHub Packages.
# See also https://docs.docker.com/docker-hub/builds/
push:
docker-image:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
contents: read

steps:
- uses: actions/checkout@v2

- name: Build image
run: docker build . --file Dockerfile_tvh_crypt.alpine --tag $IMAGE_NAME

- name: Log in to registry
# This is where you will update the PAT to GITHUB_TOKEN
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin

- name: Push image
run: |
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME
# Change all uppercase to lowercase
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
# Strip git ref prefix from version
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
# Strip "v" prefix from tag name
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
# Use Docker `latest` tag convention
[ "$VERSION" == "master" ] && VERSION=latest
echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION
docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
docker push $IMAGE_ID:$VERSION
- name: Checkout
uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
type=ref,event=branch
type=semver,pattern={{version}}
type=ref,event=pr
- name: Login to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
25 changes: 12 additions & 13 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
FROM python:3.8-alpine
LABEL maintainer="Thomas Gorgolione <[email protected]>"
WORKDIR /app
COPY . .
RUN apk add --no-cache --update bash tzdata ffmpeg curl su-exec && \
apk add --no-cache --virtual builddeps gcc musl-dev python3-dev libffi-dev openssl-dev cargo && \
pip3 install -r requirements.txt --no-cache-dir && \
apk del builddeps && \
touch /app/is_container && \
mv entrypoint.sh /usr/local/bin && \
rm -rf /tmp/* $HOME/.cache $HOME/.cargo

RUN apk add --no-cache --update ffmpeg
COPY *.ini /app/
COPY *.py /app/
COPY cache/ /app/cache/
COPY data/ /app/data/
COPY lib/ /app/lib/
COPY plugins /app/plugins
COPY plugins_ext /app/plugins_ext
COPY known_stations.json /app/
RUN touch /app/is_container

ENTRYPOINT ["python3", "/app/tvh_main.py"]
VOLUME /app/data /app/plugins_ext /app/.cabernet
EXPOSE 6077 5004
ENTRYPOINT ["entrypoint.sh"]
112 changes: 98 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,104 @@ label = PlutoTV Instance
- https://github.com/cabernetwork/cabernet/tree/master/lib/tvheadend/service

### 4. Docker
See http://ghcr.io/cabernetwork/cabernet:latest
- Use or Review ports and remote mount points at docker-compose.yml
- Note: it requires unzipping the cabernet source into ./docker/cabernet/config/app to run
- Recommended Docker file: Dockerfile_tvh_crypt.alpine
- Bring up browser and go to http://ip address:6077/
- From Plugins, install PlutoTV plugin
- Stop the app
- Edit the data/config.ini and add the following lines
<pre>
[plutotv_default]
label = PlutoTV Instance
</pre>
- Restart the app (from the Scheduler/Applications) to have the plugin fully activate
- From XML/JSON Links try some of the links
You can either use docker-compose or the docker cli.

| Architecture | Available |
|:----:|:----:|
| X86-64 ||
| arm64 ||
| armhf ||

**NOTES:**
- Volume for ```/app/.cabernet``` must be provided before enabling encryption.
- armhf not available due to python cryptography only supports 64bit systems.
[Cryptography supported platforms](https://cryptography.io/en/latest/installation/#supported-platforms)

#### docker-compose
```
version: '2.4'
services:
cabernet:
container_name: cabernet
image: ghcr.io/cabernetwork/cabernet:latest
environment:
- TZ="Etc/UTC" # optional
- PUID=1000 # optional
- PGID=1000 # optional
ports:
- "6077:6077"
- "5004:5004"
restart: unless-stopped
volumes:
- /path/to/cabernet/data:/app/data # optional
- /path/to/cabernet/plugins_ext:/app/plugins_ext # optional
- /path/to/cabernet/secrets:/app/.cabernet # optional
```

#### docker cli
```
docker run -d \
--name=cabernet \
-e PUID=1000 `#optional` \
-e PGID=1000 `#optional` \
-e TZ=Etc/UTC `#optional` \
-p 6077:6077 \
-p 5004:5004 \
-v /path/to/cabernet/data:/app/data `#optional` \
-v /path/to/plugins_ext:/app/plugins_ext `#optional` \
-v /path/to/cabernet/secrets:/app/.cabernet `#optional` \
--restart unless-stopped \
ghcr.io/cabernetwork/cabernet:latest
```

#### Parameters

| Parameter | Function |
| :----: | :----: |
| -p 6077 | Cabernet WebUI |
| -p 5004 | Cabernet stream port |
| -e PUID=1000 | for UserID |
| -e PGID=1000 | for GroupID |
| -e TZ=Etc/UTC | specify a timezone to use, see this [list](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List).|
| -v /app/data | Where Cabernet should store its database and config. |
| -v /app/plugins_ext | External Plugins |
| -v /app/.cabernet | Where encryption key is stored |

#### Updating Info
**Via Docker Compose:**

- Update the image:
```
docker-compose rm --stop -f cabernet
docker-compose pull cabernet
docker-compose up -d cabernet
```

**Via Docker Run:**

- Update the image:
```docker pull ghcr.io/cabernetwork/cabernet:latest```

- Stop the running container:
```docker stop cabernet```

- Delete the container:
```docker rm cabernet```

- You can also remove the old dangling images:
```docker image prune```

#### Via Watchtower auto-updater
```
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower \
--run-once cabernet
```

- For regulary updates follow Watchtower instructions
https://containrrr.dev/watchtower/


### 5. Default Ports
- 6007 Web UI
Expand Down
19 changes: 7 additions & 12 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
# NOTE: Cabernet tends to maintain versions on its own and will conflict with docker's
# versioning system.
# The recommendation is to have the entire cabernet source folder be in its own volume.
# whether you mount /app or /app/cabernet, the whole cabernet folder should be a volume.
# then run the python script tvh_main.py at the top level Caberent folder to start Cabernet.

version: '2.4'
services:
cabernet:
container_name: cabernet
image: ghcr.io/cabernetwork/cabernet:latest
environment:
- TZ="America/New_York"
- PUID=1000
- PGID=1000
- TZ="Etc/UTC" # Timezone (Optional)
- PUID=1000 # UserID (Optional)
- PGID=1000 # GroupID (Optional)
ports:
- "5004:5004" # Port used to stream
- "6077:6077" # Web Interface Port
- "5004:5004" # Port used to stream
restart: unless-stopped
volumes:
- ./docker/cabernet/config/app:/app
- ./.cabernet/key.txt:/root/.cabernet/key.txt
- /path/to/cabernet/data:/app/data # App data (Optional)
- /path/to/cabernet/plugins_ext:/app/plugins_ext # Plugins Data (Optional)
- /path/to/cabernet/secrets:/app/.cabernet # Ecryption key data (Optional)
38 changes: 38 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/sh

# Add local user
# Either use the USER_ID if passed in at runtime or
# fallback

USER_ID=${PUID:-1000}
GROUP_ID=${PGID:-1000}
USERNAME=cabernet
echo "Starting with UID : $USER_ID"
addgroup -S -g $GROUP_ID $USERNAME
adduser -S -D -H -h /app -u $USER_ID -G $USERNAME $USERNAME

blockUpdate="/app/do_not_updagrade_from_WEBUI_on_Docker"

oldKeyFile="/root/.cabernet/key.txt"
newKeyFile="/app/.cabernet/key.txt"

if [ -f "$oldKeyFile" ]; then

cat <<EOF
----------
!!!WARNING!!!
==> DECREPTED Volume Option
Please update your volume for 'key.txt' to new location.
$newKeyFile
----------
EOF

cp "$oldKeyFile" "$newKeyFile"
fi

# Set permissions
chown -R $USER_ID:$GROUP_ID /app

[ ! -f "$blockUpdate" ] && touch "$blockUpdate"

su-exec $USERNAME python3 /app/tvh_main.py "$@"

0 comments on commit 7cac445

Please sign in to comment.