diff --git a/.github/workflows/docker-deploy.yml b/.github/workflows/docker-deploy.yml
index 1ad022a..6d4be62 100644
--- a/.github/workflows/docker-deploy.yml
+++ b/.github/workflows/docker-deploy.yml
@@ -44,7 +44,7 @@ jobs:
uses: docker/setup-buildx-action@v2
- name: Log in to Docker Hub
- if: env.SHOULD_BUILD == 'true'
+ if: ${{ env.SHOULD_BUILD == 'true' }}
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
diff --git a/.gitignore b/.gitignore
index 59e1534..d479b72 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,5 @@ data/db.sqlite3
data/django_key.txt
.env
.pytest_cache
-filetree.txt
\ No newline at end of file
+filetree.txt
+.vscode/
diff --git a/README.md b/README.md
index e0a9527..3d1d837 100644
--- a/README.md
+++ b/README.md
@@ -25,30 +25,67 @@ As this application is intended to interface with [Sonarr](https://sonarr.tv) an
### Linux (Fully Automated)
-```bash
-curl https://raw.githubusercontent.com/nickheyer/DiscoFlix/main/auto_install_update.sh -o auto_install_update.sh && sudo bash auto_install_update.sh
+```bash
+wget https://raw.githubusercontent.com/nickheyer/DiscoFlix/main/auto_install_update.sh
+sudo ./auto_install_update.sh
```
-### Other Operating Systems (Windows, Mac, etc.)
+### Installation Using Docker CLI (All Operating Systems)
+
+#### Download Docker Image
-##### Download Docker Image (Recommended - x86_64 Architecture)
+To get the latest version of Discoflix, run:
```bash
docker image pull nickheyer/discoflix:latest
```
-##### OR Download Docker Image (ARM64, aarch64 Architecture, ie: Raspberry-Pi, Mac M1, etc.)
+#### Run Docker Container
+
+To run Discoflix in a container, use the following command. Make sure to mount a volume to `/app/data` in the container so that your data persists across container restarts. Here's how to do it:
+
+**Example**:
```bash
-docker image pull nickheyer/discoflix_rpi:latest
+docker run -d -p 5454:5454 --name discoflix -v /opt/discoflix/data:/app/data nickheyer/discoflix
```
-##### Run Docker Container
+
+**On Other Platforms**:
+You can replace `/opt/discoflix/data` with an appropriate path on your local system. For Windows and macOS, specify the full path you want to use for data storage.
+This allows DiscoFlix's database to remain on your pc even if you delete or update your container!
+
+##### The server within the docker container can be accessed locally at [http://127.0.0.1:5454](http://127.0.0.1:5454)
+
+
+### Installation Using Docker-Compose
+
+#### Prep
+
+First, get the compose file:
```bash
-docker run -d -p 5454:5454 --name discoflix nickheyer/discoflix
+mkdir -p /opt/discoflix/data && cd /opt/discoflix
+wget https://raw.githubusercontent.com/nickheyer/DiscoFlix/main/docker-compose.yml
```
+
+#### Start the Container Using Docker Compose
+
+With Docker Compose installed on your system, you can start Discoflix by running:
+
+```bash
+docker-compose -f /opt/discoflix/docker-compose.yml up -d
+```
+
+This will pull the latest Discoflix image and run it, mounting the volume specified in the `docker-compose.yml` file. This will use the default /opt/discoflix/data, so modify this path if needed.
+
##### The server within the docker container can be accessed locally at [http://127.0.0.1:5454](http://127.0.0.1:5454)
+**To stop the service**, use:
+
+```bash
+docker-compose -f /opt/discoflix/docker-compose.yml down
+```
+
diff --git a/auto_install_update.sh b/auto_install_update.sh
old mode 100644
new mode 100755
index fe9bfe8..50182a0
--- a/auto_install_update.sh
+++ b/auto_install_update.sh
@@ -1,327 +1,126 @@
#!/bin/bash
+set -e
-#App-Agnostic-Auto-Install-&-Update-Script created by Nicholas Heyer
-
-# .... SCRIPT CONFIGURATION ....
-
-app_name="DiscoFlix" # <-- Required!
-#database_file="/data/disco.db" # <-- Optional
-docker_user="nickheyer" # <-- Required!
-docker_app="discoflix" # <-- Required!
-ports="5454:5454" # <-- Optional
-
-
-#Checking if script was run as root (with sudo)
-if [ "$EUID" -ne 0 ]
- then echo "This script requires root access. Please try again using \"sudo bash $0\""
- exit
-fi
-
-# .... Creating TMP dir for backup and install files ....
-tmp_dir=$(mktemp -d -t ci-XXXXXXXXXX)
-
-#Determine system architecture
-system_arch=$(uname -i)
-
-#Appending repo based on system arch
-[[ $system_arch =~ ^arm ]] && docker_app="${docker_app}_rpi"
+# Universal Install & Update Script for DiscoFlix by Nicholas Heyer
+# USE ENV VARIABLE IF PROVIDED, OTHERWISE USE SCRIPT DEFAULTS
+app_name="${APP_NAME:-DiscoFlix}"
+docker_user="${DOCKER_USER:-nickheyer}"
+docker_app="${DOCKER_APP:-discoflix}"
docker_repo="${docker_user}/${docker_app}"
-
-#Greet user
-
-echo "Initializing ${app_name} Install & Update Script..."
-
-#Detect if Docker is installed
-
-echo "Checking for Docker installation on current machine..."
-
-docker_loc="$(command -v docker)"
-
-if [ ! -z "${docker_loc}" ]
-then
-
- echo "Docker is installed, install location saved for future reference..."
-
-else
-
- while true; do
- read -p "Docker installation not detected on this machine. Would you like to install Docker (required for ${app_name})? " yn
- case $yn in
-
- [Yy]* )
- echo "Installing Docker via get-docker.com --- Please wait..."
- iscript_loc="${tmp_dir}/get-docker.sh"
- curl -fsSL https://get.docker.com -o $iscript_loc
- sh $iscript_loc
- break
- ;;
-
- [Nn]* )
- echo "Docker is required for installation of ${app_name}. Please install before retrying this installation. Thank you!"
- exit
- ;;
-
- * ) echo "Please answer yes or no";;
- esac
- done
+outer_port="${DOCKER_PORT_HOST:-5454}"
+inner_port="${DOCKER_PORT_CONTAINER:-5454}"
+ports="${outer_port}:${inner_port}"
+host_volume_dir="${HOST_VOLUME_DIR:-/opt/discoflix/data}"
+container_data_path="${CONTAINER_DATA_PATH:-/app/data}"
+volume_path="${host_volume_dir}:${container_data_path}"
+service_file="/etc/systemd/system/docker-${docker_app}.service"
+create_service="${CREATE_SERVICE:-false}"
+
+# CHECK ROOT
+if [ "$EUID" -ne 0 ]; then
+ echo "This script requires root access. Please run with sudo: sudo bash $0"
+ exit 1
fi
-#Checking for docker-.service. If service is running, stop service (which stops container).
-
-echo "Handling service file creation and control. Please wait..."
-
-app_service_file="/etc/systemd/system/docker-${docker_app}.service"
-
-echo "Checking if .service file exists at ${app_service_file}. Please wait..."
-if [ -f "${app_service_file}" ]
-then
-
- echo "Service exists! Stopping any running services associated with ${app_name}. Please wait..."
- systemctl stop "docker-${docker_app}.service"
-
-else
-
- docker_loc="$(command -v docker)"
-
- echo "No services exist for this application. Creating service file. Please wait..."
- echo "[Unit]
- Description=${app_name} Service
- Requires=docker.service
- After=docker.service
-
- [Service]
- Restart=always
- ExecStart=${docker_loc} start -a ${docker_app}
- ExecStop=${docker_loc} stop -t 2 ${docker_app}
-
- [Install]
- WantedBy=default.target" > "${app_service_file}"
+# CHECK FOR DOCKER, INSTALL IF NEEDED
+which docker > /dev/null || {
+ read -p "Docker is not installed. Would you like to install Docker? (y/N): " ans
+ if [[ $ans != "y" ]]; then
+ echo "Installation aborted. Exiting."
+ exit 1
+ fi
+ echo "Installing Docker..."
+ curl -fsSL https://get.docker.com -o get-docker.sh
+ sh get-docker.sh
+ rm get-docker.sh
+}
+
+# CREATE SYSTEMD SERVICE IF SYSTEMD IS PRESENT AND CREATE_SERVICE IS TRUE
+if command -v systemctl &> /dev/null && [ "$create_service" = "true" ]; then
+ if [ -f "$service_file" ]; then
+ echo "Stopping existing ${app_name} service..."
+ systemctl stop "docker-${docker_app}.service"
+ else
+ echo "Creating systemd service file for ${app_name}..."
+ cat << EOF > "$service_file"
+[Unit]
+Description=${app_name} Service
+Requires=docker.service
+After=docker.service
+
+[Service]
+Restart=always
+ExecStart=$(which docker) run -d -p "${ports}" -v "${volume_path}" --name "${docker_app}" "${docker_repo}"
+ExecStop=$(which docker) stop ${docker_app}
+
+[Install]
+WantedBy=multi-user.target
+EOF
+ systemctl daemon-reload
+ fi
fi
-#Checking for running app containers. Stopping them.
-
-echo "Checking for pre-existing ${app_name} containers..."
-container_state=$(docker container ls -a --filter name="${docker_app}" --format "{{.State}}")
-container_id=$(docker container ls -a --filter name="${docker_app}" --format "{{.ID}}")
-
-[ -z "${container_id}" ] || echo "Container discovered: $container_id is $container_state."
-
-[ "${container_state}" = "running" ] && echo "Shutting down container. Please wait..." && docker container stop $docker_app #If container is running, stop container
-
-
-#If app image exists, search for app in running containers.
-
-echo "Checking for ${app_name} images on current machine..."
-app_installation=$(docker images "${docker_repo}:latest" --format "{{.Repository}}")
-
-if [ -z "${app_installation}" ] #If app image does not exist
-then
-
- echo "No installations of ${app_name} detected. Pulling new image from ${docker_repo}. Please wait..."
- docker pull "${docker_repo}"
-
-else
-
- while true; do
- read -p "Installation of ${app_name} detected. Would you like to force an update to the most recent version? " yn
- case $yn in
-
- [Yy]* )
- echo "Pulling most recent image for ${docker_repo}. Please wait..."
- docker pull "${docker_repo}"
- break
- ;;
-
- [Nn]* )
- echo "Skipping update..."
- break
- ;;
-
- * ) echo "Please answer yes or no";;
- esac
- done
+# MAKE SURE VOL MOUNT DIR EXISTS
+if [ ! -d "$host_volume_dir" ]; then
+ echo "Creating volume directory at $host_volume_dir..."
+ mkdir -p "$host_volume_dir"
+ chmod 777 "$host_volume_dir"
fi
-updated_installation=$(docker images "${docker_repo}:latest")
-
-
-
-#If app container already exists, backup all configs, data, etc.
-
-if [ -z "${container_id}" ]
-then
-
- echo "No containers detected. Skipping file backup..."
-
-else
-
- tmp_img="${docker_app}_tmp"
-
- echo "Creating temporary image from stopped container..."
- docker commit $container_id $tmp_img
-
- echo "Running temporary container from temp image..."
- docker run -d --name $tmp_img $tmp_img
- tmp_id=$(docker container ls -a --filter name="${tmp_img}" --format "{{.ID}}")
-
- db_backup_successful=false
- if [ -v database_file ]; then
- read -p "Would you like to backup the database? (y/N): " answer
- if [[ $answer =~ ^[Yy] ]]; then
- echo "Preparing to backup the database..."
-
- # Check if SQLite is installed
- if ! command -v sqlite3 &> /dev/null; then
- echo "SQLite is not installed. Attempting to install SQLite..."
-
- # Detect the platform and install SQLite
- case "$(uname -s)" in
- Linux)
- if [ -f "/etc/os-release" ]; then
- . /etc/os-release
- case "$ID" in
- debian|ubuntu)
- sudo apt-get update
- sudo apt-get install sqlite3 libsqlite3-dev
- ;;
- fedora)
- sudo dnf install sqlite sqlite-devel
- ;;
- centos|rhel)
- sudo yum install sqlite sqlite-devel
- ;;
- *)
- echo "Unsupported Linux distribution. Please install SQLite manually."
- exit 1
- ;;
- esac
- else
- echo "Unsupported Linux distribution. Please install SQLite manually."
- exit 1
- fi
- ;;
- Darwin)
- if command -v brew &> /dev/null; then
- brew install sqlite
- else
- echo "Homebrew is not installed. Please install Homebrew and then install SQLite."
- exit 1
- fi
- ;;
- *)
- echo "Unsupported platform. Please install SQLite manually."
- exit 1
- ;;
- esac
- fi
-
- # Continue with the backup process
- echo "SQLite is installed. Proceeding with the backup..."
- database_base_file=$(basename ${database_file})
- docker cp "${tmp_id}:/app${database_file}" "${tmp_dir}/${database_base_file}"
- db_file_1="${tmp_dir}/${database_base_file}"
- db_backup_successful=true
- else
- echo "Backup process canceled."
- fi
+# CHECK FOR EXISTING CONTAINER
+if docker container inspect "$docker_app" &> /dev/null; then
+ echo "Existing ${app_name} container detected."
+ # CHECK FOR VOL MOUNT
+ mounts=$(docker inspect -f '{{ range .Mounts }}{{ .Destination }} {{ end }}' "$docker_app")
+ if [[ ! $mounts =~ $container_data_path ]]; then
+ echo "No volume mount detected for data. Backing up data from the running container..."
+ # COPY DATA FROM CONTAINER TO HOST MOUNT
+ docker cp "${docker_app}:${container_data_path}/." "$host_volume_dir"
+ echo "Data backup completed to ${host_volume_dir}."
else
- echo "No DB File Provided"
+ echo "Volume mount detected. No data backup needed."
fi
- echo "Cleaning up temporary image and containers..."
- docker container rm -f $tmp_img
- docker image rm -f $tmp_img
-
- #Removing old containers
- echo "Removing old container #${container_id}"
- docker container rm -f $container_id
-
+ # STOP + RM CONTAINER
+ echo "Stopping and removing the existing ${app_name} container..."
+ docker container stop "$docker_app"
+ docker container rm "$docker_app"
fi
+# PULL IMAGE
+echo "Pulling the latest image for ${app_name}..."
+docker pull "$docker_repo"
-#Create container using new image
+# RUN CONTAINER
+echo "Starting ${app_name} container..."
+docker run -d -p "${ports}" -v "${volume_path}" --name "${docker_app}" "${docker_repo}"
-echo "Creating/running container from updated image. Please wait..."
-[ -z $ports ] && docker run -d --name $docker_app $docker_repo || docker run -d -p $ports --name $docker_app $docker_repo
-new_id=$(docker container ls -a --filter name="${docker_app}" --format "{{.ID}}")
-
-#Injecting backed-up files into new container
+# START SYSTEMD SERVICE IF SYSTEMD IS PRESENT AND CREATE_SERVICE IS TRUE
+if command -v systemctl &> /dev/null && [ "$create_service" = "true" ]; then
+ echo "Enabling and starting ${app_name} service..."
+ systemctl enable "docker-${docker_app}.service"
+ systemctl start "docker-${docker_app}.service"
+fi
+# VERIFY RUNNING CONTAINER
+if [ "$(docker container inspect -f '{{.State.Running}}' "$docker_app")" == "true" ]; then
+ echo "${app_name} is successfully installed and running!"
+ ip=$(hostname -i | cut -f1 -d' ') || '127.0.1.1'
+ port=$(echo $outer_port)
-if [ -z "${container_id}" ]
-then
+ echo " "
+ echo "-----------------------------------------------------------------------------------------------"
+ echo " "
- echo "No backed up files to inject, skipping container injection. Please wait..."
+ echo "${app_name} should be remotely accessible via http://${ip}:${port}"
+ echo " "
+ echo "-----------------------------------------------------------------------------------------------"
+ echo " "
else
- if $db_backup_successful; then
- echo "Injecting DB"
- docker exec ${docker_app} ls
- database_base_file=$(basename ${database_file})
- docker cp "${new_id}:/app${database_file}" "${tmp_dir}/${base_file}_new"
- db_file_2="${tmp_dir}/${base_file}_new"
- cat $db_file_2
-
- # Get schema from DB files
- sqlite3 "$db_file_1" ".schema" | sort > "${tmp_dir}/schema_1.txt"
- sqlite3 "$db_file_2" ".schema" | sort > "${tmp_dir}/schema_2.txt"
-
- if diff -q "${tmp_dir}/schema_1.txt" "${tmp_dir}/schema_2.txt" > /dev/null; then
- echo "The schemas are compatible for backup."
- docker cp "${tmp_dir}/${database_base_file}" "${new_id}:/app${database_file}"
- else
- echo "The schemas are not compatible for backup."
- fi
- fi
+ echo "Failed to start ${app_name} container. Please check Docker logs for details."
+ exit 1
fi
-
-
-#Preparing for service start by shutting down new container
-
-echo "Temporarily shutting down ${docker_repo} (will restart with service)..."
-docker container stop $docker_app
-
-#Reloading systemctl daemon to populate changes to services
-
-echo "Reloading systemctl daemon to poulate changes to services. Please wait..."
-systemctl daemon-reload
-
-#Starting services
-
-echo "Starting docker-${docker_app}.service. Please wait..."
-systemctl start "docker-${docker_app}.service"
-wait
-
-#Cleaning tmp files
-echo "Cleaning up temporary files and removing tmp_dir. Please wait..."
-rm -rf $tmp_dir
-
-#Confirming container is running now as it should
-
-echo "Verifying that container is running properly. Please wait..."
-new_state=$(docker container ls -a --filter name="${docker_app}" --format "{{.State}}")
-while [ ! "${new_state}" = "running" ]
-do
- sleep 1
- echo "Service Status: ${new_state}"
- new_state=$(docker container ls -a --filter name="${docker_app}" --format "{{.State}}")
- [ "${new_state}" = "dead" ] && echo "Container is unable to start. Try running this install script again or try installing manually." && exit
-done
-
-echo "${app_name} install/update successful. Container is running!"
-
-ip=$(hostname -I | cut -f1 -d' ')
-port=$(echo $ports | cut -f1 -d':')
-
-echo " "
-echo "-----------------------------------------------------------------------------------------------"
-echo " "
-
-echo "${app_name} should be remotely accessible via http://${ip}:${port}"
-
-echo " "
-echo "-----------------------------------------------------------------------------------------------"
-echo " "
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..83a6912
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,11 @@
+version: '3.8'
+
+services:
+ discoflix:
+ image: nickheyer/discoflix:latest
+ container_name: discoflix
+ ports:
+ - "5454:5454"
+ volumes:
+ - /opt/discoflix/data:/app/data
+ restart: unless-stopped