diff --git a/docker-compose.yml b/docker-compose.yml index 91bfba5a..a3cf079a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,90 +1,51 @@ version: '3.7' + services: bc-mysql: image: mysql:8.0 container_name: bc-mysql - command: --default-authentication-plugin=mysql_native_password restart: always - networks: + networks: - bluecherry_net volumes: - ./database:/var/lib/mysql - "/etc/timezone:/etc/timezone:ro" - "/etc/localtime:/etc/localtime:ro" environment: - MYSQL_ROOT_PASSWORD: $MYSQL_ADMIN_PASSWORD - TZ: $TZ + MYSQL_ROOT_PASSWORD: "${MYSQL_ADMIN_PASSWORD}" + TZ: "${TZ}" + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 10s + timeout: 5s + retries: 5 bluecherry: - image: bluecherrydvr/bluecherry:latest - container_name: bc-server - cap_add: - - NET_BIND_SERVICE build: context: ./server/ - network: bluecherry_net - args: - MYSQL_ADMIN_PASSWORD: $MYSQL_ADMIN_PASSWORD - # MYSQL_ADMIN_LOGIN: $MYSQL_ADMIN_LOGIN - # BLUECHERRY_DB_USER: $BLUECHERRY_DB_USER - BLUECHERRY_DB_PASSWORD: $BLUECHERRY_DB_PASSWORD - # BLUECHERRY_DB_NAME: $BLUECHERRY_DB_NAME - # BLUECHERRY_DB_HOST: $BLUECHERRY_DB_HOST - # BLUECHERRY_DB_ACCESS_HOST: $BLUECHERRY_DB_ACCESS_HOST - # BLUECHERRY_LINUX_GROUP_ID: $BLUECHERRY_LINUX_GROUP_ID - # BLUECHERRY_LINUX_USER_ID: $BLUECHERRY_LINUX_USER_ID - restart: unless-stopped - networks: + image: bluecherrydvr/bluecherry:latest + container_name: bc-server + depends_on: + bc-mysql: + condition: service_healthy + networks: - bluecherry_net volumes: - ./recordings:/var/lib/bluecherry/recordings - ./data/bconf:/var/lib/bluecherry/.local/share/data/bconf - ./data/letsencrypt:/usr/share/bluecherry/nginx-includes/letsencrypt - ./data/backups:/usr/share/bluecherry/backups - # - ./server/bluecherry.conf:/etc/bluecherry.conf - # Enable this only if you have a supported VAAPI device and /dev/dri exists on the host system. - # devices: - # - /dev/dri:/dev/dri - ports: - - "7001:7001/tcp" - - "7002:7002/tcp" - env_file: - - ./.env - depends_on: - - bc-mysql - - mta_mailer: - container_name: bc-mail - cap_add: - - NET_BIND_SERVICE - image: juanluisbaptiste/postfix:latest -# We assume bc-mail is only used by Bluecherry apps and not something else on the network -# expose: -# - "25" - dns: - - 8.8.8.8 -# ports: -# - "25:25/tcp" - env_file: - - .mailenv - restart: always - networks: - - bluecherry_net - volumes: - - "/etc/localtime:/etc/localtime:ro" + environment: + # MySQL admin credentials (used by entrypoint to create/upgrade DB) + MYSQL_ADMIN_LOGIN: root + MYSQL_ADMIN_PASSWORD: "${MYSQL_ADMIN_PASSWORD}" - uptime-kuma: - image: louislam/uptime-kuma:latest - container_name: uptime-kuma - volumes: - - ./uptime-kuma-data:/app/data - - /var/run/docker.sock:/var/run/docker.sock - ports: - - "1337:3001" - networks: - - bluecherry_net - restart: always + # Bluecherry DB user (will be created if missing) + BLUECHERRY_DB_HOST: bc-mysql + BLUECHERRY_DB_NAME: bluecherry + BLUECHERRY_DB_USER: bluecherry + BLUECHERRY_DB_PASSWORD: "${BLUECHERRY_DB_PASSWORD}" + BLUECHERRY_DB_ACCESS_HOST: '%' -networks: - bluecherry_net: - name: bluecherry_net + # Timezone + TZ: America/Chicago diff --git a/server/entrypoint.sh b/server/entrypoint.sh index f4d61b88..701d9b2d 100644 --- a/server/entrypoint.sh +++ b/server/entrypoint.sh @@ -2,77 +2,77 @@ set -e +# Wait for MySQL to be ready +echo "> Waiting for MySQL at $BLUECHERRY_DB_HOST:3306..." +until mysql -h"$BLUECHERRY_DB_HOST" -u"$MYSQL_ADMIN_LOGIN" -p"$MYSQL_ADMIN_PASSWORD" -e "SELECT 1" &>/dev/null; do + echo "MySQL not reachable - sleeping 5s" + sleep 5 +done +echo "> MySQL is up" + +# Create or upgrade the Bluecherry database +echo "> Creating or upgrading Bluecherry database" +if ! echo "exit" | mysql -h"$BLUECHERRY_DB_HOST" -u"$BLUECHERRY_DB_USER" -p"$BLUECHERRY_DB_PASSWORD" "$BLUECHERRY_DB_NAME" &>/dev/null; then + echo "> Database does not exist or credentials invalid, creating..." + /bin/bc-database-create || { echo "Database creation failed"; exit 1; } +else + echo "> Database exists, upgrading if needed..." + /bin/bc-database-upgrade || { echo "Database upgrade failed"; exit 1; } +fi + +# -- Original entrypoint logic -- + echo "> Update MySQL's my.cnf from environment variables passed in from docker" echo "> Writing /root/.my.cnf" { - echo "[client]"; \ - echo "user=$MYSQL_ADMIN_LOGIN"; \ - echo "password=$MYSQL_ADMIN_PASSWORD"; \ - echo "[mysql]"; \ - echo "user=$MYSQL_ADMIN_LOGIN"; \ - echo "password=$MYSQL_ADMIN_PASSWORD"; \ - echo "[mysqldump]"; \ - echo "user=$MYSQL_ADMIN_LOGIN"; \ - echo "password=$MYSQL_ADMIN_PASSWORD"; \ - echo "[mysqldiff]"; \ - echo "user=$MYSQL_ADMIN_LOGIN"; \ - echo "password=$MYSQL_ADMIN_PASSWORD"; \ + echo "[client]" + echo "user=$MYSQL_ADMIN_LOGIN" + echo "password=$MYSQL_ADMIN_PASSWORD" + echo "[mysql]" + echo "user=$MYSQL_ADMIN_LOGIN" + echo "password=$MYSQL_ADMIN_PASSWORD" + echo "[mysqldump]" + echo "user=$MYSQL_ADMIN_LOGIN" + echo "password=$MYSQL_ADMIN_PASSWORD" + echo "[mysqldiff]" + echo "user=$MYSQL_ADMIN_LOGIN" + echo "password=$MYSQL_ADMIN_PASSWORD" } > /root/.my.cnf echo "> Update bluecherry server's bluecherry.conf from environment variables passed in from docker" echo "> Writing /etc/bluecherry.conf" { - echo "# Bluecherry configuration file"; \ - echo "# Used to be sure we don't use configurations not suitable for us";\ - echo "version = \"1.0\";"; \ - echo "bluecherry:"; \ - echo "{"; \ - echo " db:"; \ - echo " {"; \ - echo " # 0 = sqlite, 1 = pgsql, 2 = mysql"; \ - echo " type = 2;"; \ - echo " dbname = \"$BLUECHERRY_DB_NAME\";"; \ - echo " user = \"$BLUECHERRY_DB_USER\";"; \ - echo " password = \"$BLUECHERRY_DB_PASSWORD\";"; \ - echo " host = \"$BLUECHERRY_DB_HOST\";"; \ - echo " userhost = \"$BLUECHERRY_DB_ACCESS_HOST\";"; \ - echo " };"; \ - echo "};"; \ + echo "# Bluecherry configuration file" + echo "# Used to be sure we don't use configurations not suitable for us" + echo "version = \"1.0\";" + echo "bluecherry:" + echo "{" + echo " db:" + echo " {" + echo " # 0 = sqlite, 1 = pgsql, 2 = mysql" + echo " type = 2;" + echo " dbname = \"$BLUECHERRY_DB_NAME\";" + echo " user = \"$BLUECHERRY_DB_USER\";" + echo " password = \"$BLUECHERRY_DB_PASSWORD\";" + echo " host = \"$BLUECHERRY_DB_HOST\";" + echo " userhost = \"$BLUECHERRY_DB_ACCESS_HOST\";" + echo " };" + echo "};" } > /etc/bluecherry.conf echo "> chown bluecherry:bluecherry /var/lib/bluecherry/recordings" chown bluecherry:bluecherry /var/lib/bluecherry/recordings chmod ug+rwx /var/lib/bluecherry/recordings - -# The bluecherry container's Dockerfile sets rsyslog to route the bluecherry -# server's main log file to STDOUT for process #1, which then gets picked up -# by docker (so its messages get routed out through docker logs, etc.), but -# the location permissions have to be reset on every start of the container: +echo "> Starting rsyslogd" chmod 777 /proc/self/fd/1 - - -echo "> /usr/sbin/rsyslogd" /usr/sbin/rsyslogd -status=$? -if [ $status -ne 0 ]; then - echo "Failed to start apache2 web server: $status" - exit $status -fi - -echo "> /usr/sbin/apache2" +echo "> Starting Apache2" source /etc/apache2/envvars -/usr/sbin/apache2 -status=$? -if [ $status -ne 0 ]; then - echo "Failed to start apache2 web server: $status" - exit $status -fi +/usr/sbin/apache2 -DFOREGROUND & - -echo "> /usr/sbin/bc-server -u bluecherry -g bluecherry" -export LD_LIBRARY_PATH=/usr/lib/bluecherry +echo "> Starting Bluecherry server" /usr/sbin/bc-server -u bluecherry -g bluecherry status=$? if [ $status -ne 0 ]; then @@ -80,24 +80,16 @@ if [ $status -ne 0 ]; then exit $status fi - -# Naive check runs checks once a minute to see if either of the processes exited. -# This illustrates part of the heavy lifting you need to do if you want to run -# more than one service in a container. The container exits with an error -# if it detects that any of the processes has exited. -# Otherwise it loops forever, waking up every 15 seconds +# Monitor essential services while sleep 15; do - ps aux |grep rsyslog |grep -q -v grep - PROCESS_1_STATUS=$? - ps aux |grep nginx |grep -q -v grep - PROCESS_2_STATUS=$? - ps aux |grep bc-server |grep -q -v grep - PROCESS_3_STATUS=$? - - # If the greps above find anything, they exit with 0 status - # If they are not both 0, then something is wrong - if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 -o $PROCESS_3_STATUS -ne 0 ]; then - echo "One of the processes has already exited." + ps aux | grep -q "[r]syslogd" + STATUS1=$? + ps aux | grep -q "[a]pache2" + STATUS2=$? + ps aux | grep -q "[b]c-server" + STATUS3=$? + if [ $STATUS1 -ne 0 ] || [ $STATUS2 -ne 0 ] || [ $STATUS3 -ne 0 ]; then + echo "One of the processes has exited unexpectedly. Stopping container." exit 1 fi done