diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 56ca480e..c81863d3 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,6 +5,7 @@ # these updates when the pull request(s) in the appropriate skeleton are merged # and Lineage processes these changes. +version: 2 updates: - directory: / package-ecosystem: docker diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 25c47ea9..56885331 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -27,27 +27,8 @@ permissions: contents: read jobs: - diagnostics: - name: Run diagnostics - runs-on: ubuntu-latest - steps: - # Note that a duplicate of this step must be added at the top of - # each job. - - id: harden-runner - name: Harden the runner - uses: step-security/harden-runner@v2 - with: - egress-policy: audit - - id: github-status - name: Check GitHub status - uses: crazy-max/ghaction-github-status@v4 - - id: dump-context - name: Dump context - uses: crazy-max/ghaction-dump-context@v2 analyze: name: Analyze - needs: - - diagnostics runs-on: ubuntu-latest permissions: actions: read diff --git a/Dockerfile b/Dockerfile index 820d7bab..399ba415 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,25 +1,18 @@ # syntax=docker/dockerfile:1 ARG PYTHON_VERSION=3.13.0 -ARG WEEWX_UID=421 -ARG WEEWX_VERSION=4.10.2 +ARG WEEWX_UID=1000 ARG WEEWX_HOME="/home/weewx" FROM --platform=$BUILDPLATFORM tonistiigi/xx AS xx FROM --platform=$BUILDPLATFORM python:${PYTHON_VERSION} AS build-stage -ARG WEEWX_VERSION -ARG ARCHIVE="weewx-${WEEWX_VERSION}.tar.gz" - COPY --from=xx / / RUN apt-get update && apt-get install -y clang lld ARG TARGETPLATFORM RUN xx-apt install -y libc6-dev -# RUN apk --no-cache add cargo gcc libffi-dev make musl-dev openssl-dev python3-dev tar -RUN apt-get install -y wget - WORKDIR /tmp RUN \ --mount=type=cache,mode=0777,target=/var/cache/apt \ @@ -30,18 +23,9 @@ pip install --upgrade virtualenv virtualenv /opt/venv EOF -COPY src/hashes README.md requirements.txt setup.py ./ +COPY pyproject.toml README.md requirements.txt ./ COPY src/_version.py ./src/_version.py -# Download sources and verify hashes -RUN wget -O "${ARCHIVE}" "https://weewx.com/downloads/released_versions/${ARCHIVE}" -RUN wget -O weewx-mqtt.zip https://github.com/matthewwall/weewx-mqtt/archive/master.zip -RUN wget -O weewx-interceptor.zip https://github.com/matthewwall/weewx-interceptor/archive/master.zip -RUN sha256sum -c < hashes - -# WeeWX setup -RUN tar --extract --gunzip --directory /root --strip-components=1 --file "${ARCHIVE}" - # Python setup RUN python -m venv /opt/venv ENV PATH="/opt/venv/bin:$PATH" @@ -49,8 +33,6 @@ RUN pip install --no-cache --requirement requirements.txt WORKDIR /root -# RUN bin/wee_extension --install /tmp/weewx-mqtt.zip -# RUN bin/wee_extension --install /tmp/weewx-interceptor.zip COPY src/entrypoint.sh src/_version.py ./ FROM python:${PYTHON_VERSION}-slim AS final-stage @@ -69,19 +51,20 @@ LABEL org.opencontainers.image.vendor="Geekpad" RUN addgroup --system --gid ${WEEWX_UID} weewx \ && adduser --system --uid ${WEEWX_UID} --ingroup weewx weewx -RUN apt-get update && apt-get install -y libusb-1.0-0 gosu busybox-syslogd tzdata +RUN apt-get update && apt-get install -y git libusb-1.0-0 WORKDIR ${WEEWX_HOME} COPY --from=build-stage /opt/venv /opt/venv COPY --from=build-stage /root ${WEEWX_HOME} -RUN mkdir /data && \ - cp weewx.conf /data && \ - chown -R weewx:weewx ${WEEWX_HOME} +RUN mkdir /data \ + && chown -R weewx:weewx /data VOLUME ["/data"] ENV PATH="/opt/venv/bin:$PATH" +ENV PIP_TARGET="/data/lib/python/site-packages" +ENV PYTHONPATH="/data/lib/python/site-packages" +USER weewx ENTRYPOINT ["./entrypoint.sh"] -CMD ["/data/weewx.conf"] diff --git a/README.md b/README.md index ebd21355..d0bbe642 100644 --- a/README.md +++ b/README.md @@ -13,51 +13,26 @@ This docker container can be used to quickly get a [WeeWX](http://weewx.com) instance up and running. -This container has the following WeeWX extensions pre-installed: - -- [interceptor](https://github.com/matthewwall/weewx-interceptor) -- [mqtt](https://github.com/weewx/weewx/wiki/mqtt) - ## Running ## -### Running with Docker ### - -Pull `felddy/weewx` from the Docker repository: - -```console -docker pull felddy/weewx -``` - -### Run ### - The easiest way to start the container is to create a `docker-compose.yml` similar to the following. If you use a serial port to connect to your weather station, make sure the -container has permissions to access the port. The uid/gid can -be set using the environment variables below. +container has permissions to access the port. Modify any paths or devices as needed: ```yaml --- -version: "3.8" - -volumes: - data: +name: "weewx" services: weewx: - image: felddy/weewx - init: true - restart: "yes" + image: felddy/weewx:5.1.0 volumes: - type: bind source: ./data target: /data - environment: - - TIMEZONE=UTC - - WEEWX_UID=weewx - - WEEWX_GID=dialout devices: - "/dev/ttyUSB0:/dev/ttyUSB0" ``` @@ -72,7 +47,7 @@ services: the container and generate a configuration file: ```console - docker compose run weewx + docker compose run --rm weewx ``` 1. The configuration file will be created in the `data` directory. You should @@ -102,7 +77,7 @@ services: 1. Update your configuration file (a backup will be created): ```console - docker compose run weewx --upgrade + docker compose run --rm weewx station upgrade ``` 1. Read through the new configuration and verify. @@ -113,22 +88,77 @@ services: 1. Start the container up with the new image version: ```console - docker compose up -d + docker compose up --detach ``` +## Migrating ## + +If you are migrating a WeeWX installation, you need to configure the logger to +write to the console. Add the following to your `weewx.conf` file to see the log +output in the container logs: + +```ini +[Logging] + [[root]] + level = INFO + handlers = console, +``` + +## Installing WeeWX Extensions ## + +If arguments are passed to the container, they are forwarded on to the +[`weectl`](https://weewx.com/docs/5.1/utilities/weectl-about/) command. This +can be used to install extensions: + +```console +docker compose run --rm weewx \ + extension install --yes \ + https://github.com/matthewwall/weewx-windy/archive/master.zip +``` + +```console +docker compose run --rm weewx \ + extension install --yes \ + https://github.com/matthewwall/weewx-mqtt/archive/master.zip +``` + +## Installing Python Packages ## + +To install and persist Python packages, use the `pip` command. The libraries +will be installed into the `data` volume, ensuring they persist between +container restarts. + +```console +docker compose run --rm --entrypoint pip weewx \ + install git+https://github.com/felddy/weewx-home-assistant@v1.0.0 +``` + +## Image tags ## + +The images of this container are tagged with [semantic +versions](https://semver.org) that align with the [version and build of +WeeWX](https://weewx.com/docs.html) that they support. + +> [!TIP] +> It is recommended that users use the major version tag: `:5` Using the major +> tag will ensure that you receive the most recent version of the software that +> is compatible with your saved data, and prevents inadvertent upgrades to a new +> major version. + +| Image:tag | Description | +|-----------|-------------| +|`felddy/weewx:5`| The most recent image matching the major version number. Most users will use this tag. | +|`felddy/weewx:5.1`| The most recent image matching the major and minor version numbers. | +|`felddy/weewx:5.1.0`| An exact image version. | + +See the [tags tab](https://hub.docker.com/r/felddy/weewx/tags) on Docker +Hub for a list of all the supported tags. + ## Volumes ## | Mount point | Purpose | |-------------|----------------| -| `/data` | configuration file and sqlite database storage | - -## Environment Variables ## - -| Variable | Purpose | Default | -|----------------|---------|---------| -| `TIMEZONE` | Container [TZ database name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List) | `UTC` | -| `WEEWX_UID` | `uid` the daemon will be run under | `weewx` | -| `WEEWX_GID` | `gid` the deamon will be run under | `weewx` | +| `/data` | [WeeWX root](https://weewx.com/docs/5.1/usersguide/where/#location-of-weewx-components) directory | ## Building from source ## @@ -136,7 +166,7 @@ Build the image locally using this git repository as the [build context](https:/ ```console docker build \ - --tag felddy/weewx:4.8.0 \ + --tag felddy/weewx:5.1.0 \ https://github.com/felddy/weewx-docker.git#develop ``` @@ -160,21 +190,9 @@ Docker: docker buildx build \ --platform linux/amd64 \ --output type=docker \ - --tag felddy/weewx:4.8.0 . + --tag felddy/weewx:5.1.0 . ``` -## Debugging ## - -There are a few helper arguments that can be used to diagnose container issues -in your environment. - -| Purpose | Command | -|---------|---------| -| Generate the default configuration | `docker compose run weewx` | -| Upgrade a previous configuration | `docker compose run weewx --upgrade` | -| Generate a test (simulator) configuration | `docker compose run weewx --gen-test-config` | -| Drop into a shell in the container | `docker compose run weewx --shell` | - ## Contributing ## We welcome contributions! Please see [`CONTRIBUTING.md`](CONTRIBUTING.md) for diff --git a/docker-compose.yml b/docker-compose.yml index 31763625..ed584168 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,24 +1,15 @@ --- -version: "3.8" +name: "weewx" volumes: data: services: weewx: - build: - context: . - dockerfile: Dockerfile - image: felddy/weewx:4.8.0 - init: true - restart: "no" + image: felddy/weewx:5.1.0 # devices: # - "/dev/ttyUSB0:/dev/ttyUSB0" volumes: - type: bind source: ./data target: /data - environment: - - TIMEZONE=UTC - - WEEWX_UID=weewx - - WEEWX_GID=dialout diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..e8068bc0 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,47 @@ +[build-system] +build-backend = "setuptools.build_meta" +requires = ["setuptools", "wheel"] + +[project] +authors = [{ name = "Mark Feldhousen", email = "markf@geekpad.com" }] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Web Environment", + "Intended Audience :: System Administrators", + "License :: OSI Approved :: MIT License", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Topic :: Scientific/Engineering :: Atmospheric Science", +] +dependencies = ["ephem", "pyserial", "pyusb", "setuptools", "weewx == 5.1.0"] +description = "Containerized WeeWX" +dynamic = ["version"] +keywords = ["container", "docker", "weewx"] +license = { file = "LICENSE" } +name = "weewx-docker" +readme = "README.md" +requires-python = ">=3.10" + +[project.urls] +homepage = "https://github.com/felddy" +issues = "https://github.com/felddy/weewx-docker/issues" +source = "https://github.com/felddy/weewx-docker" + +[project.optional-dependencies] +test = [ + "coverage", + "coveralls", + "docker", + "pre-commit", + "pytest", + "pytest-cov", + "semver", +] + +[tool.setuptools.dynamic] +version = { attr = "_version.__version__" } diff --git a/setup.py b/setup.py deleted file mode 100644 index 4ca2ba48..00000000 --- a/setup.py +++ /dev/null @@ -1,88 +0,0 @@ -""" -This is the setup module for the weewx docker project. - -Based on: - -- https://packaging.python.org/distributing/ -- https://github.com/pypa/sampleproject/blob/master/setup.py -- https://blog.ionelmc.ro/2014/05/25/python-packaging/#the-structure -""" - -# Standard Python Libraries -from glob import glob -from os.path import basename, splitext - -# Third-Party Libraries -from setuptools import find_packages, setup - - -def readme(): - """Read in and return the contents of the project's README.md file.""" - with open("README.md", encoding="utf-8") as f: - return f.read() - - -def package_vars(version_file): - """Read in and return the variables defined by the version_file.""" - pkg_vars = {} - with open(version_file) as f: - exec(f.read(), pkg_vars) # nosec - return pkg_vars - - -setup( - name="weewx_docker", - # Versions should comply with PEP440 - version=package_vars("src/_version.py")["__version__"], - description="weewx_docker python library", - long_description=readme(), - long_description_content_type="text/markdown", - url="https://github.com/felddy", - # The project's main homepage - download_url="https://github.com/felddy/weewx-docker", - # Author details - author="Mark Feldhousen", - author_email="markf@geekpad.com", - license="License :: OSI Approved :: MIT License", - # See https://pypi.python.org/pypi?%3Aaction=list_classifiers - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Environment :: Web Environment", - "Intended Audience :: System Administrators", - "License :: OSI Approved :: MIT License", - "Natural Language :: English", - "Operating System :: OS Independent", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Topic :: Scientific/Engineering :: Atmospheric Science", - ], - python_requires=">=3.6", - # What does your project relate to? - keywords="weewx", - packages=find_packages(where="src"), - package_dir={"": "src"}, - py_modules=[splitext(basename(path))[0] for path in glob("src/*.py")], - install_requires=[ - "configobj == 5.0.9", - "paho-mqtt == 2.1.0", - "pyserial == 3.5", - "pyusb == 1.2.1", - "semver == 3.0.2", - "setuptools == 75.6.0", - "wheel == 0.45.1", - ], - extras_require={ - "test": [ - "coverage", - "coveralls", - "docker", - "pre-commit", - "pytest", - "pytest-cov", - ] - }, -) diff --git a/src/_version.py b/src/_version.py index cf44e2fd..0d72820f 100644 --- a/src/_version.py +++ b/src/_version.py @@ -1 +1 @@ -__version__ = "4.10.2" +__version__ = "5.1.0" diff --git a/src/entrypoint.sh b/src/entrypoint.sh index 1fe7c278..e42c0269 100755 --- a/src/entrypoint.sh +++ b/src/entrypoint.sh @@ -4,60 +4,38 @@ set -o nounset set -o errexit set -o pipefail -CONF_FILE="/data/weewx.conf" +WEEWX_ROOT="/data" +CONF_FILE="${WEEWX_ROOT}/weewx.conf" -# echo version before starting syslog so we don't confound our tests -if [ "$1" = "--version" ]; then - gosu weewx:weewx ./bin/weewxd --version +# echo version +if [ $# -gt 0 ] && [ "$1" = "--version" ]; then + weewxd --version exit 0 fi -if [ "$(id -u)" = 0 ]; then - # set timezone using environment - ln -snf /usr/share/zoneinfo/"${TIMEZONE:-UTC}" /etc/localtime - # start the syslog daemon as root - /sbin/syslogd -n -S -O - & - if [ "${WEEWX_UID:-weewx}" != 0 ]; then - # drop privileges and restart this script - echo "Switching uid:gid to ${WEEWX_UID:-weewx}:${WEEWX_GID:-weewx}" - gosu "${WEEWX_UID:-weewx}:${WEEWX_GID:-weewx}" "$(readlink -f "$0")" "$@" - exit 0 - fi -fi +if [ ! -f "${CONF_FILE}" ]; then + weectl station create --no-prompt ${WEEWX_ROOT} + echo "A new set of configurations was created." -copy_default_config() { - # create a default configuration on the data volume - echo "Creating a configration file on the container data volume." - cp weewx.conf "${CONF_FILE}" - echo "The default configuration has been copied." - # Change the default location of the SQLITE database to the volume - echo "Setting SQLITE_ROOT to the container volume." - sed "s/SQLITE_ROOT =.*/SQLITE_ROOT = \/data/g" "${CONF_FILE}" > /tmp/weewx.conf - mv /tmp/weewx.conf "${CONF_FILE}" -} - -if [ "$1" = "--gen-test-config" ]; then - copy_default_config - echo "Generating a test configuration." - ./bin/wee_config --reconfigure --no-prompt "${CONF_FILE}" - exit 0 -fi + # Append the logging configuration to the generated weewx.conf + cat << EOF >> "${CONF_FILE}" -if [ "$1" = "--shell" ]; then - /bin/sh - exit $? -fi +[Logging] + [[root]] + level = INFO + handlers = console, +EOF -if [ "$1" = "--upgrade" ]; then - ./bin/wee_config --upgrade --no-prompt --dist-config weewx.conf "${CONF_FILE}" - exit $? + echo "Console logging configuration has been appended to ${CONF_FILE}." + echo "Please review and update ${CONF_FILE} as needed, then restart the container." + exit 0 fi -if [ ! -f "${CONF_FILE}" ]; then - copy_default_config - echo "Running configuration tool." - ./bin/wee_config --reconfigure "${CONF_FILE}" - exit 1 -fi +# if we have any parameters we'll send them to weectl -./bin/weewxd "$@" +if [ $# -gt 0 ]; then + weectl "$@" --config ${CONF_FILE} + exit 0 +else + weewxd --config ${CONF_FILE} +fi diff --git a/src/hashes b/src/hashes deleted file mode 100644 index 0a389c97..00000000 --- a/src/hashes +++ /dev/null @@ -1,3 +0,0 @@ -d7f445560ac5be6424d4b81995109dcf05bd564a3b2fce201bf58ab46dda43fc weewx-4.10.2.tar.gz -89f1fff4e86582befb8190e823537df0c8b89fd962a3f7ece72f33998c769504 weewx-mqtt.zip -9bf17503313023860fd30f49b4146ffb6cd5186e81ead257b1bb8571158434a7 weewx-interceptor.zip