diff --git a/.dockerignore b/.dockerignore index fb85e2ca..2f4b4b61 100644 --- a/.dockerignore +++ b/.dockerignore @@ -10,3 +10,5 @@ docs/ *.sln *.njsproj *.md +examples +tests \ No newline at end of file diff --git a/.github/workflows/docker.yml b/.github/workflows/docker-alpine.yml similarity index 99% rename from .github/workflows/docker.yml rename to .github/workflows/docker-alpine.yml index 2e5b7ad6..75caaef9 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker-alpine.yml @@ -1,9 +1,9 @@ -name: Docker-Builder +name: Docker-Builder-Alpine on: workflow_dispatch: schedule: - - cron: '2 0 * * *' # Daily at 00:02 UTC + - cron: '0 0 * * *' # Daily at 00:00 UTC release: types: [ published ] @@ -95,7 +95,7 @@ jobs: . build-arm64: - runs-on: ubuntu-22.04-arm + runs-on: ubuntu-24.04-arm needs: translate strategy: fail-fast: false diff --git a/.github/workflows/docker-debian.yml b/.github/workflows/docker-debian.yml new file mode 100644 index 00000000..5a862727 --- /dev/null +++ b/.github/workflows/docker-debian.yml @@ -0,0 +1,230 @@ +name: Docker-Builder-Debian + +on: + workflow_dispatch: + schedule: + - cron: '0 1 * * *' # Daily at 01:00 UTC (I think) + release: + types: [ published ] + +jobs: + + translate: + runs-on: ubuntu-24.04 + name: Run Translations + steps: + - name: Checkout repository + uses: actions/checkout@v5 + - name: Set up Node.js + uses: actions/setup-node@v6 + with: + node-version: "lts/*" + - name: Run translate.js (ignore errors) + run: node translate.js || true + working-directory: translate + - name: Run translate extractall + run: node translate extractall + working-directory: translate + - name: Run translate.js minifyall + run: node translate.js minifyall + working-directory: translate + - name: Run translate.js translateall + run: node translate.js translateall + working-directory: translate + - name: Upload repo with translations + uses: actions/upload-artifact@v5 + with: + name: repo-with-translations + path: . + + build-amd64: + runs-on: ubuntu-24.04 + needs: translate + strategy: + fail-fast: false + max-parallel: 3 + matrix: + variant: [mongodb, postgresql, mariadb, all, slim] + name: Build Docker Image (amd64-${{ matrix.variant }}) + steps: + - name: Download repo artifact + uses: actions/download-artifact@v5 + with: + name: repo-with-translations + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + cache-image: false + platforms: amd64 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + cache-binary: false + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.MY_TOKEN || secrets.GITHUB_TOKEN }} + - name: Build and push Docker image (amd64-${{ matrix.variant }}) + run: | + REPO_OWNER_LC="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')" + case "${{ matrix.variant }}" in + mongodb) + MONGODB=YES; POSTGRESQL=NO; MARIADB=NO; TAG="-amd64-mongodb-debian";; + postgresql) + MONGODB=NO; POSTGRESQL=YES; MARIADB=NO; TAG="-amd64-postgresql-debian";; + mariadb) + MONGODB=NO; POSTGRESQL=NO; MARIADB=YES; TAG="-amd64-mariadb-debian";; + all) + MONGODB=YES; POSTGRESQL=YES; MARIADB=YES; TAG="-amd64-debian";; + slim) + MONGODB=NO; POSTGRESQL=NO; MARIADB=NO; TAG="-amd64-slim-debian";; + esac + docker buildx build \ + --platform linux/amd64 \ + --build-arg INCLUDE_MONGODB_TOOLS=$MONGODB \ + --build-arg INCLUDE_POSTGRESQL_TOOLS=$POSTGRESQL \ + --build-arg INCLUDE_MARIADB_TOOLS=$MARIADB \ + --build-arg DISABLE_MINIFY=yes \ + --build-arg DISABLE_TRANSLATE=yes \ + --build-arg DISABLE_EXTRACT=yes \ + --build-arg PREINSTALL_LIBS=true \ + -f docker/Dockerfile-debian \ + -t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}$TAG \ + --push \ + . + + build-arm64: + runs-on: ubuntu-24.04-arm + needs: translate + strategy: + fail-fast: false + max-parallel: 3 + matrix: + variant: [mongodb, postgresql, mariadb, all, slim] + name: Build Docker Image (arm64-${{ matrix.variant }}) + steps: + - name: Download repo artifact + uses: actions/download-artifact@v5 + with: + name: repo-with-translations + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + cache-image: false + platforms: arm64 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + cache-binary: false + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.MY_TOKEN || secrets.GITHUB_TOKEN }} + - name: Build and push Docker image (arm64-${{ matrix.variant }}) + run: | + REPO_OWNER_LC="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')" + case "${{ matrix.variant }}" in + mongodb) + MONGODB=YES; POSTGRESQL=NO; MARIADB=NO; TAG="-arm64-mongodb-debian";; + postgresql) + MONGODB=NO; POSTGRESQL=YES; MARIADB=NO; TAG="-arm64-postgresql-debian";; + mariadb) + MONGODB=NO; POSTGRESQL=NO; MARIADB=YES; TAG="-arm64-mariadb-debian";; + all) + MONGODB=YES; POSTGRESQL=YES; MARIADB=YES; TAG="-arm64-debian";; + slim) + MONGODB=NO; POSTGRESQL=NO; MARIADB=NO; TAG="-arm64-slim-debian";; + esac + docker buildx build \ + --platform linux/arm64 \ + --build-arg INCLUDE_MONGODB_TOOLS=$MONGODB \ + --build-arg INCLUDE_POSTGRESQL_TOOLS=$POSTGRESQL \ + --build-arg INCLUDE_MARIADB_TOOLS=$MARIADB \ + --build-arg DISABLE_MINIFY=yes \ + --build-arg DISABLE_TRANSLATE=yes \ + --build-arg DISABLE_EXTRACT=yes \ + --build-arg PREINSTALL_LIBS=true \ + -f docker/Dockerfile-debian \ + -t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}$TAG \ + --push \ + . + + merge-manifest: + runs-on: ubuntu-24.04 + needs: + - translate + - build-amd64 + - build-arm64 + name: Create and Push Multi-Arch Manifest + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + cache-binary: false + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.MY_TOKEN || secrets.GITHUB_TOKEN }} + - name: Create and push multi-arch manifests for all variants + run: | + REPO_OWNER_LC="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')" + # mongodb + docker buildx imagetools create \ + -t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-mongodb-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-mongodb-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-mongodb-debian \ + # postgresql + docker buildx imagetools create \ + -t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-postgresql-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-postgresql-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-postgresql-debian \ + # mariadb + docker buildx imagetools create \ + -t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-mariadb-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-mariadb-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-mariadb-debian \ + # all (no suffix) + docker buildx imagetools create \ + -t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-debian \ + # slim + docker buildx imagetools create \ + -t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-slim-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-slim-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-slim-debian \ + - name: Create and push 'latest' tags (releases only) + if: github.event_name == 'release' + run: | + REPO_OWNER_LC="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')" + # latest-mongodb + docker buildx imagetools create \ + -t ghcr.io/$REPO_OWNER_LC/meshcentral:latest-mongodb-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-mongodb-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-mongodb-debian \ + # latest-postgresql + docker buildx imagetools create \ + -t ghcr.io/$REPO_OWNER_LC/meshcentral:latest-postgresql-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-postgresql-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-postgresql-debian \ + # latest-mariadb + docker buildx imagetools create \ + -t ghcr.io/$REPO_OWNER_LC/meshcentral:latest-mariadb-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-mariadb-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-mariadb-debian \ + # latest (all databases) + docker buildx imagetools create \ + -t ghcr.io/$REPO_OWNER_LC/meshcentral:latest-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-debian \ + # latest-slim + docker buildx imagetools create \ + -t ghcr.io/$REPO_OWNER_LC/meshcentral:latest-slim-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-slim-debian \ + ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-slim-debian \ diff --git a/docker/01_nodoc b/docker/01_nodoc new file mode 100644 index 00000000..da3bf156 --- /dev/null +++ b/docker/01_nodoc @@ -0,0 +1,18 @@ +# Exclude unneeded documentation files to save space + +# Don't install package docs +path-exclude=/usr/share/doc/* +path-include=/usr/share/doc/*/copyright + +# Don't install man pages +path-exclude=/usr/share/man/* + +# Don't install localized man pages +path-exclude=/usr/share/locale/* + +# Optional: exclude info pages +path-exclude=/usr/share/info/* + +# Optional: exclude lintian and other package data +path-exclude=/usr/share/lintian/* +path-exclude=/usr/share/linda/* diff --git a/docker/Dockerfile b/docker/Dockerfile index 6c479e0f..547bdae7 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -49,8 +49,7 @@ RUN rm -rf /opt/meshcentral/meshcentral/docker /opt/meshcentral/meshcentral/node FROM node:22-alpine3.22 AS dep-compiler -RUN apk update && \ - echo -e "----------\nINSTALLING ALPINE PACKAGES...\n----------"; \ +RUN echo -e "----------\nINSTALLING ALPINE PACKAGES...\n----------"; \ apk add --no-cache --update \ bash gcc g++ jq make python3 tzdata @@ -59,13 +58,15 @@ WORKDIR /opt/meshcentral/meshcentral RUN jq '.dependencies += {"modern-syslog": "1.2.0", "telegram": "2.26.22"}' package.json > temp.json && mv temp.json package.json \ && npm i --package-lock-only \ - && npm ci + && npm ci --omit=dev \ + && npm cache clean --force -### STAGE 3 RUNTIME +### STAGE 3 BUILDING. -FROM node:22-alpine3.22 AS runtime +FROM node:22-alpine3.22 AS finalizer +#FROM alpine:3.22 AS finalizer -# # Copy prepared app from builder stage +# copy files from previous layer COPY --from=dep-compiler /opt/meshcentral/meshcentral /opt/meshcentral/meshcentral # environment variables @@ -122,12 +123,12 @@ ENV MARIADB_HOST="" \ MARIADB_PASS="" \ MARIADB_DATABASE="" +RUN mkdir -p /opt/meshcentral/meshcentral WORKDIR /opt/meshcentral -RUN apk update && \ - echo -e "----------\nINSTALLING ALPINE PACKAGES...\n----------"; \ +RUN echo -e "----------\nINSTALLING ALPINE PACKAGES...\n----------"; \ apk add --no-cache --update \ - bash curl jq nodejs npm tzdata && \ + bash curl jq tzdata && \ rm -rf /var/cache/* \ /tmp/* \ /usr/share/man/ \ @@ -189,25 +190,22 @@ RUN case "$INCLUDE_MARIADB_TOOLS" in \ exit 1;; \ esac -# install dependencies from package.json -RUN cd meshcentral && \ - npm cache clean --force && \ - rm -rf /root/ /tmp/ +# Remove left over files and cache +RUN cd meshcentral \ + && rm -rf /root /tmp/* /var/tmp/* /usr/lib/node_modules/npm/man /usr/lib/node_modules/npm/doc /usr/lib/node_modules/npm/html \ + && npm cache clean --force # Expose needed ports EXPOSE 80 443 -# These volumes will be created by default even without any declaration, this allows default persistence in Docker/Podman. +# These volumes will be created by default even without any declaration, this allows default persistence in Docker/Podman. Dummy-proofing. VOLUME /opt/meshcentral/meshcentral-data VOLUME /opt/meshcentral/meshcentral-files VOLUME /opt/meshcentral/meshcentral-web VOLUME /opt/meshcentral/meshcentral-backups # Copy images from Git repo, place it before ending so recompilation can make good use of cache. -COPY ./docker/entrypoint.sh /opt/meshcentral/entrypoint.sh +COPY ./docker/entrypoint.sh /opt/meshcentral/entrypoint.sh COPY ./docker/config.json.template /opt/meshcentral/config.json.template -HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \ - CMD curl -k --fail https://localhost:443/health.ashx || exit 1 - -ENTRYPOINT ["bash", "/opt/meshcentral/entrypoint.sh"] +ENTRYPOINT ["bash", "/opt/meshcentral/entrypoint.sh"] \ No newline at end of file diff --git a/docker/Dockerfile-debian b/docker/Dockerfile-debian new file mode 100644 index 00000000..a397da6f --- /dev/null +++ b/docker/Dockerfile-debian @@ -0,0 +1,238 @@ +### STAGE 1 BUILDING. +FROM node:22-trixie-slim AS builder + +# Any value inside one of the disable ARGs will be accepted. +ARG DISABLE_EXTRACT="yes" +ARG DISABLE_MINIFY="yes" +ARG DISABLE_TRANSLATE="yes" +# NODE_OPTIONS="--max_old_space_size=4096" +# If your process gets OOM killed, perhaps the above will help. + +RUN mkdir -p /opt/meshcentral/meshcentral +WORKDIR /opt/meshcentral +COPY ./ /opt/meshcentral/meshcentral/ + +# Check the Docker build arguments and if they are empty do the task. +RUN if [ -n "$DISABLE_EXTRACT" ] || [ -n "$DISABLE_MINIFY" ] || [ -n "$DISABLE_TRANSLATE" ]; then \ + echo -e "----------\nPREPARING ENVIRONMENT...\n----------"; \ + cd meshcentral && \ + npm install html-minifier-terser@7.2.0 jsdom@26.0.0 esprima@4.0.1 && \ + cd translate && \ + case "$DISABLE_EXTRACT" in \ + false|no|FALSE|NO) \ + echo -e "----------\nSTARTING THE EXTRACTING PROCESS...\n----------"; \ + node translate.js extractall;; \ + *) \ + echo "Setting EXTRACT as disabled.";; \ + esac && \ + case "$DISABLE_MINIFY" in \ + false|no|FALSE|NO) \ + echo -e "----------\nSTARTING THE MINIFYING PROCESS...\n----------"; \ + node translate.js minifyall;; \ + *) \ + echo "Setting MINIFY as disabled.";; \ + esac && \ + case "$DISABLE_TRANSLATE" in \ + false|no|FALSE|NO) \ + echo -e "----------\nSTARTING THE TRANSLATING PROCESS...\n----------"; \ + node translate.js translateall;; \ + *) \ + echo "Setting TRANSLATE as disabled.";; \ + esac; \ + npm uninstall html-minifier-terser jsdom esprima; \ + fi +# Possible more updated alternative? @minify-html/node@0.15.0 -> https://www.npmjs.com/package/@minify-html/node + +RUN rm -rf /opt/meshcentral/meshcentral/docker /opt/meshcentral/meshcentral/node_modules /opt/meshcentral/meshcentral/docs + +### STAGE 2 PRECOMPILE DEPS MODULE + +FROM node:22-trixie-slim AS dep-compiler + +ENV NODE_ENV="production" + +RUN apt-get update && \ + echo -e "----------\nINSTALLING DEBIAN PACKAGES...\n----------"; \ + apt-get install -y --no-install-recommends --no-install-suggests \ + bash gcc g++ jq make python3 tzdata + +COPY --from=builder /opt/meshcentral/meshcentral /opt/meshcentral/meshcentral +WORKDIR /opt/meshcentral/meshcentral + +RUN jq '.dependencies += {"modern-syslog": "1.2.0", "telegram": "2.26.22"}' package.json > temp.json && mv temp.json package.json \ + && npm i --package-lock-only \ + && npm ci --omit=dev \ + && npm cache clean --force + +### STAGE 3 fun. building from source... + +FROM golang:trixie AS mongo-tools-compiler + +ARG INCLUDE_MONGODB_TOOLS="false" + +RUN apt-get update && \ + apt-get install -y --no-install-recommends --no-install-suggests \ + git lsb-release + +RUN case "$INCLUDE_MONGODB_TOOLS" in \ + true|yes|TRUE|YES) \ + git clone https://github.com/mongodb/mongo-tools /mongo-tools; \ + cd /mongo-tools; \ + ./make build -pkgs=mongodump,mongorestore;; \ + false|no|FALSE|NO) \ + echo "Not building MongoDB Tools from source, what a shame!"; \ + mkdir -p /mongo-tools/bin;; \ + *) \ + echo "Invalid value for build argument INCLUDE_MONGODB_TOOLS, possible values: 'yes', 'true', 'no' or 'false'"; \ + exit 1;; \ + esac + +### STAGE 4 BUILDING. + +FROM node:22-trixie-slim AS finalizer + +# Copy files from previous layers +COPY --from=dep-compiler /opt/meshcentral/meshcentral /opt/meshcentral/meshcentral +COPY --from=mongo-tools-compiler /mongo-tools/bin/ /tmp/bin/ + +# environment variables +ENV NODE_ENV="production" \ + CONFIG_FILE="/opt/meshcentral/meshcentral-data/config.json" \ + DYNAMIC_CONFIG="false" + +# environment variables for the above defined MeshCentral Config.json. Can be done like that following: https://docs.docker.com/reference/dockerfile/#env +ENV ALLOW_PLUGINS="false" \ + ALLOW_NEW_ACCOUNTS="false" \ + ALLOWED_ORIGIN="false" \ + IFRAME="false" \ + REGEN_SESSIONKEY="false" \ + WEBRTC="false" \ + LOCAL_SESSION_RECORDING="true" \ + MINIFY="true" \ + HOSTNAME="localhost" \ + REVERSE_PROXY="" \ + REVERSE_PROXY_TLS_PORT="443" \ + TRUSTED_PROXY="" \ + ARGS="" + +# Database +# Multi-variable declaration to reduce layers. +ENV USE_MONGODB="false" \ + USE_POSTGRESQL="false" \ + USE_MARIADB="false" + +# Preinstallation args one per line due to: https://docs.docker.com/reference/dockerfile/#arg +ARG PREINSTALL_LIBS="false" +ARG INCLUDE_MONGODB_TOOLS="false" +ARG INCLUDE_POSTGRESQL_TOOLS="false" +ARG INCLUDE_MARIADB_TOOLS="false" + +# MongoDB Variables +# The following MONGO_URL variable overwrites most other mongoDb related varialbes. +ENV MONGO_HOST="" \ + MONGO_PORT="27017" \ + MONGO_USERNAME="" \ + MONGO_PASS="" \ + MONGO_URL="" + +# PostgreSQL Variables +ENV PSQL_HOST="" \ + PSQL_PORT="5432" \ + PSQL_USER="" \ + PSQL_PASS="" \ + PSQL_DATABASE="" + +# MariaDB/MySQL Variables. +ENV MARIADB_HOST="" \ + MARIADB_PORT="3306" \ + MARIADB_USER="" \ + MARIADB_PASS="" \ + MARIADB_DATABASE="" + +WORKDIR /opt/meshcentral + +RUN apt-get update && \ + echo -e "----------\nINSTALLING DEBIAN PACKAGES...\n----------"; \ + apt-get install -y --no-install-recommends --no-install-suggests \ + bash curl jq tzdata && \ + rm -rf \ + /var/cache/* \ + /usr/share/man/ \ + /usr/share/doc/ \ + /var/log/* \ + /var/spool/* \ + /var/tmp/* \ + /usr/lib/debug/ && \ + npm install -g npm@latest + +RUN case "$PREINSTALL_LIBS" in \ + true|yes|TRUE|YES) \ + cd meshcentral && \ + echo -e "----------\nPREINSTALLING LIBRARIES...\n----------"; \ + npm install ssh2@1.16.0 nodemailer@6.10.1 image-size@2.0.2 wildleek@2.0.0 otplib@12.0.1 yub@0.11.1;; \ + false|no|FALSE|NO) \ + echo "Not pre-installing libraries.";; \ + *) \ + echo -e "Invalid value for build argument INCLUDE_POSTGRESQL_TOOLS, possible values: 'yes', 'true', 'no' or 'false'"; \ + exit 1;; \ + esac + +# NOTE: ALL MODULES MUST HAVE A VERSION NUMBER AND THE VERSION MUST MATCH THAT USED IN meshcentraljs mainStart() +RUN case "$INCLUDE_MONGODB_TOOLS" in \ + true|yes|TRUE|YES) \ + mv /tmp/bin/* /usr/bin; \ + cd meshcentral && \ + echo -e "----------\nPREINSTALLING MONGODB LIBRARIES...\n----------"; \ + npm install mongodb@4.17.2 @mongodb-js/saslprep@1.3.1;; \ + false|no|FALSE|NO) \ + echo "Not including MongoDB Tools.";; \ + *) \ + echo "Invalid value for build argument INCLUDE_MONGODB_TOOLS, possible values: 'yes', 'true', 'no' or 'false'"; \ + exit 1;; \ + esac + +RUN case "$INCLUDE_POSTGRESQL_TOOLS" in \ + true|yes|TRUE|YES) \ + apt-get install -y --no-install-recommends --no-install-suggests postgresql-client-17; \ + cd meshcentral && \ + echo -e "----------\nPREINSTALLING POSTGRESQL LIBRARIES...\n----------"; \ + npm install pg@8.14.1;; \ + false|no|FALSE|NO) \ + echo "Not including PostgreSQL Tools.";; \ + *) \ + echo -e "Invalid value for build argument INCLUDE_POSTGRESQL_TOOLS, possible values: 'yes', 'true', 'no' or 'false'"; \ + exit 1;; \ + esac + +RUN case "$INCLUDE_MARIADB_TOOLS" in \ + true|yes|TRUE|YES) \ + apt-get install -y --no-install-recommends --no-install-suggests default-mysql-client mariadb-client; \ + cd meshcentral && \ + echo -e "----------\nPREINSTALLING MARIADB/MYSQL LIBRARIES...\n----------"; \ + npm install mariadb@3.4.0 mysql2@3.11.4;; \ + false|no|FALSE|NO) \ + echo "Not including MariaDB/MySQL Tools.";; \ + *) \ + echo -e "Invalid value for build argument INCLUDE_MARIADB_TOOLS, possible values: 'yes', 'true', 'no' or 'false'"; \ + exit 1;; \ + esac + +# Remove left over files and cache +RUN cd meshcentral \ + && rm -rf /root /tmp/* /var/tmp/* /usr/lib/node_modules/npm/man /usr/lib/node_modules/npm/doc /usr/lib/node_modules/npm/html \ + && npm cache clean --force + +# Expose needed ports +EXPOSE 80 443 + +# These volumes will be created by default even without any declaration, this allows default persistence in Docker/Podman. Dummy-proofing. +VOLUME /opt/meshcentral/meshcentral-data +VOLUME /opt/meshcentral/meshcentral-files +VOLUME /opt/meshcentral/meshcentral-web +VOLUME /opt/meshcentral/meshcentral-backups + +# Copy images from Git repo, place it before ending so recompilation can make good use of cache. +COPY ./docker/entrypoint.sh /opt/meshcentral/entrypoint.sh +COPY ./docker/config.json.template /opt/meshcentral/config.json.template + +ENTRYPOINT ["bash", "/opt/meshcentral/entrypoint.sh"] \ No newline at end of file diff --git a/docker/README.md b/docker/README.md index 40e68450..a09a8630 100644 --- a/docker/README.md +++ b/docker/README.md @@ -27,6 +27,17 @@ So for another quick example: if you want to get a released version with a Mongo So for another quick example: if you want a very slim image with the latest code and only a local database: `ghcr.io/ylianst/meshcentral:master-slim`
So as a last example: if you want to get a MariaDB/MySQL backend with MeshCentral version 1.1.53: `ghcr.io/ylianst/meshcentral:1.1.53-mysql` +## Persistency + +The Docker image has since recently removed its default creation of volumes. It might not be what you want.
+If you still want to use volumes to make data persist across containers use Docker volumes (or Kubernetes PVCs).
+For examples of how to use these volumes, see the examples below. Most data resides inside: + +- /opt/meshcentral/meshcentral-backups +- /opt/meshcentral/meshcentral-data (most important! Server configurations, certificates, etc... reside here.) +- /opt/meshcentral/meshcentral-files +- /opt/meshcentral/meshcentral-web (relevant if you use a custom theme, such as [Stylish-UI](https://github.com/melo-professional/Meshcentral-Stylish-UI)) + ## Environment Variables Below is a breakdown of environment variables used in this setup. diff --git a/docker/build-all-variants.sh b/docker/build-all-variants.sh new file mode 100644 index 00000000..52c277b2 --- /dev/null +++ b/docker/build-all-variants.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +if command -v docker > /dev/null; then + docker build ../. -f Dockerfile -t meshcentral:alpine-slim --build-arg=PREINSTALL_LIBS=true --build-arg=INCLUDE_MONGODB_TOOLS=false --build-arg=INCLUDE_POSTGRESQL_TOOLS=false --build-arg=INCLUDE_MARIADB_TOOLS=false + docker build ../. -f Dockerfile -t meshcentral:alpine-complete --build-arg=PREINSTALL_LIBS=true --build-arg=INCLUDE_MONGODB_TOOLS=true --build-arg=INCLUDE_POSTGRESQL_TOOLS=true --build-arg=INCLUDE_MARIADB_TOOLS=true + docker build ../. -f Dockerfile -t meshcentral:alpine-mongodb --build-arg=PREINSTALL_LIBS=true --build-arg=INCLUDE_MONGODB_TOOLS=true --build-arg=INCLUDE_POSTGRESQL_TOOLS=false --build-arg=INCLUDE_MARIADB_TOOLS=false + docker build ../. -f Dockerfile -t meshcentral:alpine-postgresql --build-arg=PREINSTALL_LIBS=true --build-arg=INCLUDE_MONGODB_TOOLS=false --build-arg=INCLUDE_POSTGRESQL_TOOLS=true --build-arg=INCLUDE_MARIADB_TOOLS=false + docker build ../. -f Dockerfile -t meshcentral:alpine-mysql --build-arg=PREINSTALL_LIBS=true --build-arg=INCLUDE_MONGODB_TOOLS=false --build-arg=INCLUDE_POSTGRESQL_TOOLS=false --build-arg=INCLUDE_MARIADB_TOOLS=true + + docker build ../. -f Dockerfile-debian -t meshcentral:debian-slim --build-arg=PREINSTALL_LIBS=true --build-arg=INCLUDE_MONGODB_TOOLS=false --build-arg=INCLUDE_POSTGRESQL_TOOLS=false --build-arg=INCLUDE_MARIADB_TOOLS=false + docker build ../. -f Dockerfile-debian -t meshcentral:debian-complete --build-arg=PREINSTALL_LIBS=true --build-arg=INCLUDE_MONGODB_TOOLS=true --build-arg=INCLUDE_POSTGRESQL_TOOLS=true --build-arg=INCLUDE_MARIADB_TOOLS=true + docker build ../. -f Dockerfile-debian -t meshcentral:debian-mongodb --build-arg=PREINSTALL_LIBS=true --build-arg=INCLUDE_MONGODB_TOOLS=true --build-arg=INCLUDE_POSTGRESQL_TOOLS=false --build-arg=INCLUDE_MARIADB_TOOLS=false + docker build ../. -f Dockerfile-debian -t meshcentral:debian-postgresql --build-arg=PREINSTALL_LIBS=true --build-arg=INCLUDE_MONGODB_TOOLS=false --build-arg=INCLUDE_POSTGRESQL_TOOLS=true --build-arg=INCLUDE_MARIADB_TOOLS=false + docker build ../. -f Dockerfile-debian -t meshcentral:debian-mysql --build-arg=PREINSTALL_LIBS=true --build-arg=INCLUDE_MONGODB_TOOLS=false --build-arg=INCLUDE_POSTGRESQL_TOOLS=false --build-arg=INCLUDE_MARIADB_TOOLS=true +fi diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 04580c23..65f86b7c 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -14,12 +14,22 @@ trap graceful_shutdown SIGTERM # Make the start more cleared when restarted. echo "-------------------------------------------------------------" date -echo "Config file: $CONFIG_FILE" +if [ -n "$CONFIG_FILE" ]; then + echo "Config file: $CONFIG_FILE" +else + exit 1 +fi # Failsafe to create a new config if the expected config is not there. if [ -f "${CONFIG_FILE}" ]; then echo "Pre-existing config found, not recreating..." else + if [ ! -d $(dirname "$CONFIG_FILE") ]; then + echo "Creating meshcentral-data directory..." + mkdir -p /opt/meshcentral/meshcentral-data + fi + + echo "Placing template into the relevant directory: $(dirname $CONFIG_FILE)" cp /opt/meshcentral/config.json.template "${CONFIG_FILE}" fi @@ -260,7 +270,7 @@ if [[ ${DYNAMIC_CONFIG,,} =~ ^(true|yes)$ ]]; then cat "$CONFIG_FILE" else - echo "Leaving config as-is." + echo "Leaving config as-is. Dynamic Configuration is off." fi # Actually start MeshCentral. diff --git a/docker/tools/docker.build.sh b/docker/tools/docker.build.sh deleted file mode 100644 index e025ea35..00000000 --- a/docker/tools/docker.build.sh +++ /dev/null @@ -1,132 +0,0 @@ -#!/bin/bash - -MSG=""; -PRUNE="false"; -OVERRIDE_TAGS="false"; -ENABLE_LOG="false"; -LOG_FILE="$(dirname -- "$( readlink -f -- "$0"; )")/build.log"; - -function appendOutput() -{ - if [ -z "${MSG}" ]; then echo -e "\n" > /dev/tty; fi - - ARGS=$@; - LINE="${ARGS}\n"; - if [ -z "${ENABLE_LOG}" ] || [ "${ENABLE_LOG}" != "true" ]; then echo -e "${LINE}" > /dev/tty; else echo -e "${LINE}" 2>&1 | tee -a ${LOG_FILE}; fi - - MSG="${MSG}${LINE}"; -} - -function runDockerBuild() -{ - if [ "${PRUNE}" == "true" ]; then - if [ -z "${ENABLE_LOG}" ] || [ "${ENABLE_LOG}" != "true" ]; then docker system prune -a -f; - else docker system prune -a -f | tee -a ${LOG_FILE}; fi - fi - - STARTTS=$(date +%s); - ARGS=$@; - - APP_VERSION=$(grep -o '"version":\s*"[^"]*"' ./package.json | cut -f4- -d\" | tr -d '"'); - BASE_TAGS=""; - if [ -z "${OVERRIDE_TAGS}" ] || [ "${OVERRIDE_TAGS}" != "true" ]; then - BASE_TAGS="-t meshcentral:latest -t meshcentral:${APP_VERSION}"; - fi - - BUILD_CMD="docker build -f docker/Dockerfile --force-rm --no-cache ${ARGS} ${BASE_TAGS} ."; - appendOutput "Current build: ${BUILD_CMD}"; - - if [ -z "${ENABLE_LOG}" ] || [ "${ENABLE_LOG}" != "true" ]; then ${BUILD_CMD}; else ${BUILD_CMD} | tee -a ${LOG_FILE}; fi - if [ $? -ne 0 ]; then exit $?; fi - - IMAGEID=$(docker images --format "{{.ID}} {{.CreatedAt}}" | sort -rk 2 | awk 'NR==1{print $1}'); - appendOutput "\tImageId: ${IMAGEID}"; - - ENDTS=$(date +%s); - DIFSEC=$((${ENDTS}-${STARTTS})); - if [ ${DIFSEC} -ge 60 ]; then - TMPMIN=$((${DIFSEC}/60)); - TMPSEC=$((${DIFSEC}%60)); - - if [ ${TMPMIN} -ge 60 ]; then - TMPHOUR=$((${TMPMIN}/60)); - TMPMIN=$((${TMPMIN}%60)); - - appendOutput "\tBuild time: ${TMPHOUR} hr ${TMPMIN} min ${TMPSEC} sec"; - else appendOutput "\tBuild time: ${TMPMIN} min ${TMPSEC} sec"; fi - else appendOutput "\tBuild time: ${DIFSEC} sec"; fi - - IMG_SIZE=$(docker image inspect ${IMAGEID} | grep -o '"Size":\s*[^,]*' | cut -f2- -d ':' | tr -d ' '); - expr $IMG_SIZE + 0 > /dev/null; - appendOutput "\tImage size: ${IMG_SIZE} ($((${IMG_SIZE}/1024/1024))M)\n"; - - return 0; -} - -parent_path=$(dirname -- $(dirname -- "$( readlink -f -- "$0"; )")); -if [ "${parent_path}" != "$(pwd -P)" ]; then - echo -e "change working directory to: ${parent_path}" > /dev/tty; - cd "${parent_path}"; -fi - -if ! [ -z $1 ]; then - for arg in "$@" - do - case "${arg}" in - --prune) - PRUNE="true"; - shift 1; - ;; - --log) - ENABLE_LOG="true"; - shift 1; - ;; - --no-tags) - OVERRIDE_TAGS="true"; - shift 1; - ;; - --help) - __usage="\n - Usage: ./$(basename ${0}) [OPTIONS] [BUILD ARGUMENTS]\n - \n - Options:\n - \t--log \t\twrite output to build.log file\n - \t--no-tags \tdo not use default tags (meshcentral:latest and meshcentral:%VERSION%)\n - \t--prune \tWARNING: This will remove:\n - \t\t\t - all stopped docker containers\n - \t\t\t - all docker networks not used by at least one container\n - \t\t\t - all docker images without at least one container associated to them\n - \t\t\t - all docker build cache\n - \n - Build arguments: \tAll build arguments are forwarded to the docker build command, so you can use any option accepted by 'docker build'\n - \t\t\t(https://docs.docker.com/engine/reference/commandline/build/#options)\n\n - \t--build-arg INCLUDE_MONGODBTOOLS=yes \tIncludes mongodb-tools (mongodump, ...) in the image\n - \t--build-arg DISABLE_MINIFY=yes \t\tDisables minification of files\n - \t--build-arg DISABLE_TRANSLATE=yes \tDisables translation of files\n - "; - echo -e $__usage; - exit 0; - ;; - *) - break; - ;; - esac - done -fi - -MAINARGS=$@; - -#runDockerBuild --build-arg DISABLE_MINIFY=yes --build-arg DISABLE_TRANSLATE=yes ${MAINARGS}; -#runDockerBuild --build-arg DISABLE_TRANSLATE=yes ${MAINARGS}; -#runDockerBuild --build-arg DISABLE_MINIFY=yes ${MAINARGS}; -runDockerBuild ${MAINARGS}; - -#runDockerBuild --build-arg INCLUDE_MONGODBTOOLS=yes --build-arg DISABLE_MINIFY=yes --build-arg DISABLE_TRANSLATE=yes ${MAINARGS}; -#runDockerBuild --build-arg INCLUDE_MONGODBTOOLS=yes --build-arg DISABLE_TRANSLATE=yes ${MAINARGS}; -#runDockerBuild --build-arg INCLUDE_MONGODBTOOLS=yes --build-arg DISABLE_MINIFY=yes ${MAINARGS}; -#runDockerBuild --build-arg INCLUDE_MONGODBTOOLS=yes ${MAINARGS}; - -echo ""; -if [ -z "${ENABLE_LOG}" ] || [ "${ENABLE_LOG}" != "true" ]; then echo -e "${MSG}"; else echo -e "${MSG}" 2>&1 | tee -a ${LOG_FILE}; fi - -exit 0;