diff --git a/docker/2.1-appuser/Dockerfile b/docker/2.1-appuser/Dockerfile new file mode 100644 index 000000000..14a79c0a7 --- /dev/null +++ b/docker/2.1-appuser/Dockerfile @@ -0,0 +1,115 @@ +FROM alpine:3.24 + +ENV VERSION=2.1.2 \ + DOWNLOAD_SHA256=fd905380691ac65ea5a93779e8214941829e3d6e038d5edff9eac5fd74cbed02 \ + GPG_KEYS=A0D6EEA1DCAE49A635A3B2F0779B22DFB3E717B7 + +LABEL \ + org.opencontainers.image.authors="Roger Light " \ + org.opencontainers.image.title="eclipse-mosquitto" \ + org.opencontainers.image.description="Eclipse Mosquitto MQTT Broker" \ + org.opencontainers.image.url="https://mosquitto.org/" \ + org.opencontainers.image.documentation="https://mosquitto.org/documentation/" \ + org.opencontainers.image.source="https://github.com/eclipse-mosquitto/mosquitto" \ + org.opencontainers.image.licenses="EPL-2.0 OR BSD-3-Clause" \ + org.opencontainers.image.version=${VERSION} + +# UID/GID will set the mosquitto UID/GID at build time (Dockerfile) +ARG UID=1883 +ARG GID=1883 +# PUID/PGID will set the mosquitto UID/GID at run time (docker-entrypoint.sh) +# and run mosquitto under the changed user +ENV PUID=${UID} +ENV PGID=${GID} + +RUN set -x && \ + apk --no-cache add \ + shadow \ + tini \ + && \ + apk --no-cache add --virtual build-deps \ + argon2-dev \ + build-base \ + cjson-dev \ + cmake \ + cunit-dev \ + gnupg \ + gtest-dev \ + libedit-dev \ + libmicrohttpd-dev \ + linux-headers \ + openssl-dev \ + samurai \ + sqlite-dev \ + uthash-dev \ + util-linux-dev && \ + wget https://mosquitto.org/files/source/mosquitto-${VERSION}.tar.gz -O /tmp/mosq.tar.gz && \ + echo "$DOWNLOAD_SHA256 /tmp/mosq.tar.gz" | sha256sum -c - && \ + wget https://mosquitto.org/files/source/mosquitto-${VERSION}.tar.gz.asc -O /tmp/mosq.tar.gz.asc && \ + export GNUPGHOME="$(mktemp -d)" && \ + found=''; \ + for server in \ + hkps://keys.openpgp.org \ + hkp://keyserver.ubuntu.com:80 \ + pgp.mit.edu \ + ; do \ + echo "Fetching GPG key $GPG_KEYS from $server"; \ + gpg --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$GPG_KEYS" && found=yes && break; \ + done; \ + test -z "$found" && echo >&2 "error: failed to fetch GPG key $GPG_KEYS" && exit 1; \ + gpg --batch --verify /tmp/mosq.tar.gz.asc /tmp/mosq.tar.gz && \ + gpgconf --kill all && \ + rm -rf "$GNUPGHOME" /tmp/mosq.tar.gz.asc && \ + mkdir -p /build/mosq && \ + tar --strip=1 -xf /tmp/mosq.tar.gz -C /build/mosq && \ + rm /tmp/mosq.tar.gz && \ + cmake -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DHTTP_API_DIR='\"/usr/share/mosquitto/dashboard\"' \ + -DWITH_DOCS=OFF \ + -S /build/mosq \ + -B /build/mosq/build && \ + cmake --build /build/mosq/build && \ + addgroup -S -g "${PGID}" mosquitto 2>/dev/null && \ + adduser -S -u "${PUID}" -D -H -h /var/empty -s /sbin/nologin -G mosquitto -g mosquitto mosquitto 2>/dev/null && \ + mkdir -p /mosquitto/config /mosquitto/data /mosquitto/log && \ + install -d /usr/sbin/ && \ + install -s -m755 /build/mosq/build/client/mosquitto_pub /usr/bin/mosquitto_pub && \ + install -s -m755 /build/mosq/build/client/mosquitto_rr /usr/bin/mosquitto_rr && \ + install -s -m755 /build/mosq/build/client/mosquitto_sub /usr/bin/mosquitto_sub && \ + install -s -m644 /build/mosq/build/lib/libmosquitto.so.1 /usr/lib/libmosquitto.so.1 && \ + install -s -m755 /build/mosq/build/src/mosquitto /usr/sbin/mosquitto && \ + install -s -m755 /build/mosq/build/apps/mosquitto_ctrl/mosquitto_ctrl /usr/bin/mosquitto_ctrl && \ + install -s -m755 /build/mosq/build/apps/mosquitto_passwd/mosquitto_passwd /usr/bin/mosquitto_passwd && \ + install -s -m755 /build/mosq/build/apps/mosquitto_signal/mosquitto_signal /usr/bin/mosquitto_signal && \ + install -s -m755 /build/mosq/build/plugins/acl-file/mosquitto_acl_file.so /usr/lib/mosquitto_acl_file.so && \ + install -s -m755 /build/mosq/build/plugins/dynamic-security/mosquitto_dynamic_security.so /usr/lib/mosquitto_dynamic_security.so && \ + install -s -m755 /build/mosq/build/plugins/password-file/mosquitto_password_file.so /usr/lib/mosquitto_password_file.so && \ + install -s -m755 /build/mosq/build/plugins/persist-sqlite/mosquitto_persist_sqlite.so /usr/lib/mosquitto_persist_sqlite.so && \ + install -s -m755 /build/mosq/build/plugins/sparkplug-aware/mosquitto_sparkplug_aware.so /usr/lib/mosquitto_sparkplug_aware.so && \ + install -m644 /build/mosq/docker/2.1-alpine/mosquitto.conf /mosquitto/config/mosquitto.conf && \ + install -m644 /build/mosq/docker/2.1-ubuntu/mosquitto.conf /mosquitto-no-auth.conf && \ + install -d /usr/share/mosquitto && \ + cp -r /build/mosq/dashboard/src /usr/share/mosquitto/dashboard && \ + install -Dm644 /build/mosq/epl-v20 /usr/share/licenses/mosquitto/epl-v20 && \ + install -Dm644 /build/mosq/edl-v10 /usr/share/licenses/mosquitto/edl-v10 && \ + chown -R mosquitto:mosquitto /mosquitto && \ + apk --no-cache add \ + argon2-libs \ + ca-certificates \ + cjson \ + libedit \ + libmicrohttpd \ + sqlite-libs \ + tzdata && \ + apk del build-deps && \ + rm -rf /build + +VOLUME ["/mosquitto/data", "/mosquitto/log"] + +# Set up the entry point script and default command +COPY --chmod=0755 docker-entrypoint.sh / +EXPOSE 1883 +ENTRYPOINT ["/sbin/tini","-g", "--", "/docker-entrypoint.sh"] +CMD ["/usr/sbin/mosquitto", "-c", "/mosquitto/config/mosquitto.conf"] diff --git a/docker/2.1-appuser/README.md b/docker/2.1-appuser/README.md new file mode 100644 index 000000000..2bd388ba6 --- /dev/null +++ b/docker/2.1-appuser/README.md @@ -0,0 +1,101 @@ +# Eclipse Mosquitto Docker Image +Containers built with this Dockerfile build as source from published tarballs. + +## Mount Points +A docker mount point has been created in the image to be used for configuration. +``` +/mosquitto/config +``` + +Two docker volumes have been created in the image to be used for persistent storage and logs. +``` +/mosquitto/data +/mosquitto/log +``` + +## User/Group on docker (env PUID/PGID) + +The image runs mosquitto under the mosquitto user and group. +Default uid and gid are 1883. + +- uid and gid can be specified at build time with `--build-arg UID={uid}` and`--build-arg GID={gid}` +- uid and gid can be specified at runtime with `--env PUID={uid}` and `--env PGID={gid}` + +The `docker-entrypoint.sh` script modifies +group mosquitto's gid and user mosquitto's uid. +Those will fail silently, if uid or gid is already occupied. +The filesystem ownership will be changed, if group/user modification succeded. + +## Running without a configuration file +Mosquitto 2.0 and up requires you to configure listeners and authentication +before it will allow connections from anything other than the loopback +interface. In the context of a container, this means you would normally need to +provide a configuration file with your settings. + +However, this container provides a default configuration which listens on port +1883 for unauthenticated access, and port 9883 for the local http dashboard. +If you wish to run mosquitto without any authentication, and without setting +any other configuration options, you can run without a configuration by binding +the appropriate network ports: +``` +docker run -it -p 1883:1883 -p localhost:9883:9883 eclipse-mosquitto: +``` + +## Configuration +To use a custom configuration file, create a **local** config directory with a +mosquitto.conf inside, then mount this directory to `/mosquitto/config` + +``` +docker run -it -p 1883:1883 -v :/mosquitto/config eclipse-mosquitto: +``` + +Your configuration file must include a `listener`, and you must configure some +form of authentication or allow unauthenticated access. If you do not do this, +clients will be unable to connect. + + +File based authentication and authorisation: +``` +listener 1883 +plugin /usr/lib/mosquitto_password_file.so +plugin_opt_password_file /mosquitto/data/mosquitto.password_file + +plugin /usr/lib/mosquitto_acl_file.so +plugin_opt_acl_file /mosquitto/data/mosquitto.aclfile +``` + +Plugin based authentication and authorisation: +``` +listener 1883 +plugin /usr/lib/mosquitto_dynamic_security.so +plugin_opt_config_file /mosquitto/data/mosquitto-dynsec.json +``` + +Unauthenticated access: +``` +listener 1883 +allow_anonymous true +``` + +:boom: if the mosquitto configuration (mosquitto.conf) was modified +to use non-default ports, the docker run command will need to be updated +to expose the ports that have been configured, for example: + +``` +docker run -it -p 1883:1883 -p 8080:8080 -v :/mosquitto/config eclipse-mosquitto: +``` + +Configuration can be changed to: + +* persist data to `/mosquitto/data` +* log to `/mosquitto/log/mosquitto.log` + +i.e. add the following to `mosquitto.conf`: +``` +persistence_location /mosquitto/data/ +plugin /usr/lib/mosquitto_persist_sqlite.so + +log_dest file /mosquitto/log/mosquitto.log +``` + +**Note**: For any volume used, the data will be persistent between containers. diff --git a/docker/2.1-appuser/docker-entrypoint.sh b/docker/2.1-appuser/docker-entrypoint.sh new file mode 100644 index 000000000..6505f11cf --- /dev/null +++ b/docker/2.1-appuser/docker-entrypoint.sh @@ -0,0 +1,34 @@ +#!/bin/ash +### docker-entrypoint.sh for alpine linux +set -e + +# get current uid/gid for user mosquitto +CURRENT_UID=$(/usr/bin/id -u mosquitto) +CURRENT_GID=$(/usr/bin/id -g mosquitto) + +# prepare user/group and permissions +if [ "$(/usr/bin/id -u)" != '0' ]; then + # we are an unprivileged user, don't modify system + echo "running as: $(/usr/bin/id)" +else + # change user and/or group to PUID/PGID + if [[ "${PGID}" != "${CURRENT_GID}" ]]; then + /usr/sbin/groupmod --non-unique --gid "${PGID}" mosquitto 2>/dev/null || true + fi + if [[ "${PUID}" != "${CURRENT_UID}" ]]; then + # split to multiple usermod calls, ensure consistency + # modify uid + /usr/sbin/usermod --non-unique --uid "${PUID}" mosquitto || true + # modify primary group + /usr/sbin/usermod --gid "${PGID}" mosquitto || true + # modify additional group membership (this should be unneccessary, groupmod was called with --non-unique) + [[ "${PGID}" != "$(/bin/grep -e "^mosquitto:" /etc/group | /usr/bin/cut -d ":" -f3)" ]] && /usr/sbin/usermod --groups mosquitto mosquitto || true + + fi + # modify filesystem ownership, otherwise /mosquitto will be inaccessible (and mode=0750) + #/bin/chown --recursive "mosquitto:mosquitto" /mosquitto 2>/dev/null || true + /usr/bin/find /mosquitto -xdev -exec chown mosquitto:mosquitto {} \; +fi + +# execute CMD +exec "$@"