Streamline Dockerfile, remove unused deps

* Dockerfile: Use non-root user, buildx cache, setup for readonly
   container, remove unused apt deps.
   For now don't install pip package and keep development flask server
   as this will be replaced in the future (fastapi). Then a proper
   webserver (e.g. nginx) should be used and the pip package can be
   created and deployed just to the run-stage (with the webserver).
 * docker-compose: Set to readonly (anonymous volumes declared in
   Dockerfile should maintain all writable data).
   Mount config.py for easier development. Should be replaced by
   environment support for all config file variables.
 * Remove unused runtime dependencies: mariadb, joblib, pytest,
   pytest-cov.
 * Move pytest-cov to dev dependencies.
 * Add output_dir to config.py.
 * Fix visualization_results.pdf endpoint.
 * Update docs.
This commit is contained in:
Dominique Lasserre 2024-10-07 20:56:10 +02:00 committed by Andreas
parent 59dcf8c459
commit b620250536
12 changed files with 65 additions and 51 deletions

View File

@ -20,9 +20,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt install -y libmariadb3 libmariadb-dev
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-dev.txt
- name: Run Pytest

3
.gitignore vendored
View File

@ -1,3 +1,6 @@
cache/
output/
# Default ignore folders and files for VS Code, Python
.vscode/*

View File

@ -24,7 +24,7 @@ To make collaboration easier, we require pull requests to pass code style and un
Our code style checks use [`pre-commit`](https://pre-commit.com).
```bash
pip install -r requirements.txt
pip install -r requirements-dev.txt
```
To run formatting automatically before every commit:
@ -36,7 +36,7 @@ pre-commit install
Or run them manually:
```bash
pre-commit --all
pre-commit run --all-files
```
### Tests

View File

@ -3,23 +3,33 @@ FROM python:${PYTHON_VERSION}-slim
LABEL source="https://github.com/Akkudoktor-EOS/EOS"
EXPOSE 5000
ENV VIRTUAL_ENV="/opt/venv"
ENV PATH="${VIRTUAL_ENV}/bin:${PATH}"
ENV MPLCONFIGDIR="/tmp/mplconfigdir"
ENV EOS_DIR="/opt/eos"
ENV EOS_CACHE_DIR="${EOS_DIR}/cache"
ENV EOS_OUTPUT_DIR="${EOS_DIR}/output"
WORKDIR /opt/eos
WORKDIR ${EOS_DIR}
COPY . .
RUN adduser --system --group --no-create-home eos \
&& mkdir -p "${MPLCONFIGDIR}" \
&& chown eos "${MPLCONFIGDIR}" \
&& mkdir -p "${EOS_CACHE_DIR}" \
&& chown eos "${EOS_CACHE_DIR}" \
&& mkdir -p "${EOS_OUTPUT_DIR}" \
&& chown eos "${EOS_OUTPUT_DIR}"
ARG APT_OPTS="--yes --auto-remove --no-install-recommends --no-install-suggests"
COPY requirements.txt .
RUN DEBIAN_FRONTEND=noninteractive \
apt-get update \
&& apt-get install ${APT_OPTS} gcc libhdf5-dev libmariadb-dev pkg-config mariadb-common libmariadb3 \
&& rm -rf /var/lib/apt/lists/* \
&& pip install --no-cache-dir -r requirements.txt \
&& pip install --no-cache-dir build \
&& pip install --no-cache-dir -e . \
&& apt remove ${APT_OPTS} gcc libhdf5-dev libmariadb-dev pkg-config
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
COPY src .
USER eos
ENTRYPOINT []
CMD ["python", "-m", "akkudoktoreos.flask_server"]
CMD ["python", "-m", "akkudoktoreosserver.flask_server"]
VOLUME ["${MPLCONFIGDIR}", "${EOS_CACHE_DIR}", "${EOS_OUTPUT_DIR}"]

View File

@ -7,15 +7,16 @@ all: help
# Target to display help information
help:
@echo "Available targets:"
@echo " venv - Set up a Python 3 virtual environment."
@echo " pip - Install dependencies from requirements.txt."
@echo " pip-dev - Install dependencies from requirements-dev.txt."
@echo " install - Install EOS in editable form (development mode) into virtual environment."
@echo " docker-run - Run entire setup on docker
@echo " docs - Generate HTML documentation (in build/docs/html/)."
@echo " run - Run flask_server in the virtual environment (needs install before)."
@echo " dist - Create distribution (in dist/)."
@echo " clean - Remove generated documentation, distribution and virtual environment."
@echo " venv - Set up a Python 3 virtual environment."
@echo " pip - Install dependencies from requirements.txt."
@echo " pip-dev - Install dependencies from requirements-dev.txt."
@echo " install - Install EOS in editable form (development mode) into virtual environment."
@echo " docker-run - Run entire setup on docker"
@echo " docker-build - Rebuild docker image"
@echo " docs - Generate HTML documentation (in build/docs/html/)."
@echo " run - Run flask_server in the virtual environment (needs install before)."
@echo " dist - Create distribution (in dist/)."
@echo " clean - Remove generated documentation, distribution and virtual environment."
# Target to set up a Python 3 virtual environment
venv:
@ -71,4 +72,7 @@ test:
# Run entire setup on docker
docker-run:
@docker compose up
@docker compose up --remove-orphans
docker-build:
@docker compose build

View File

@ -5,28 +5,18 @@ networks:
services:
eos:
image: 'akkudoktor/eos:${EOS_VERSION}'
read_only: true
build:
context: .
dockerfile: 'Dockerfile'
args:
PYTHON_VERSION: '${PYTHON_VERSION}'
depends_on:
- 'mariadb'
init: true
environment:
FLASK_RUN_PORT: '${EOS_PORT}'
networks:
- 'eos'
volumes:
- ./src/akkudoktoreos/config.py:/opt/eos/akkudoktoreos/config.py:ro
ports:
- '${EOS_PORT}:${EOS_PORT}'
mariadb:
image: 'mariadb:${MARIADB_VERSION}-jammy'
environment:
MARIADB_ROOT_PASSWORD: '${MARIADB_ROOT_PASSWORD}'
MARIADB_DATABASE: '${MARIADB_DATABASE}'
MARIADB_USER: '${MARIADB_USER}'
MARIADB_PASSWORD: '${MARIADB_PASSWORD}'
networks:
- 'eos'
volumes:
- ./data/mariadb:/var/lib/mysql

View File

@ -1,8 +1,8 @@
build==1.2.2.post1
-r requirements.txt
myst-parser==4.0.0
sphinx==8.0.2
sphinx_rtd_theme==3.0.1
pytest==8.3.3
pytest-cov==5.0.0
pytest-xprocess==1.0.2
requests==2.32.3
pre-commit

View File

@ -1,11 +1,7 @@
numpy==2.1.2
mariadb==1.1.10
matplotlib==3.9.2
flask==3.0.3
scikit-learn==1.5.2
deap==1.4.1
joblib==1.4.2
requests==2.32.3
pytest==8.3.3
pytest-cov==5.0.0
pandas==2.2.3

View File

@ -1,5 +1,7 @@
from datetime import datetime, timedelta
output_dir = "output"
prediction_hours = 48
optimization_hours = 24
strafe = 10

View File

@ -1,4 +1,5 @@
import datetime
import os
# Set the backend for matplotlib to Agg
import matplotlib
@ -7,6 +8,7 @@ import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
from akkudoktoreos.class_sommerzeit import ist_dst_wechsel
from akkudoktoreos.config import output_dir
matplotlib.use("Agg")
@ -28,7 +30,10 @@ def visualisiere_ergebnisse(
#####################
# 24-hour visualization
#####################
with PdfPages(filename) as pdf:
if not os.path.exists(output_dir):
os.makedirs(output_dir)
output_file = os.path.join(output_dir, filename)
with PdfPages(output_file) as pdf:
# Load and PV generation
plt.figure(figsize=(14, 14))
plt.subplot(3, 3, 1)

View File

@ -18,7 +18,12 @@ from akkudoktoreos.class_load_corrector import LoadPredictionAdjuster
from akkudoktoreos.class_optimize import optimization_problem
from akkudoktoreos.class_pv_forecast import PVForecast
from akkudoktoreos.class_strompreis import HourlyElectricityPriceForecast
from akkudoktoreos.config import get_start_enddate, optimization_hours, prediction_hours
from akkudoktoreos.config import (
get_start_enddate,
optimization_hours,
output_dir,
prediction_hours,
)
app = Flask(__name__)
@ -262,11 +267,11 @@ def flask_optimize():
return jsonify(result)
@app.route("/visualisierungsergebnisse.pdf")
@app.route("/visualization_results.pdf")
def get_pdf():
# Endpoint to serve the generated PDF with visualization results
return send_from_directory(
"", "visualisierungsergebnisse.pdf"
os.path.abspath(output_dir), "visualization_results.pdf"
) # Adjust the directory if needed

View File

@ -4,6 +4,7 @@ from pathlib import Path
import pytest
from akkudoktoreos.class_optimize import optimization_problem
from akkudoktoreos.config import output_dir
DIR_TESTDATA = Path(__file__).parent / "testdata"
@ -35,5 +36,5 @@ def test_optimize(fn_in, fn_out):
assert set(ergebnis) == set(expected_output_data)
# The function creates a visualization result PDF as a side-effect.
fp_viz = Path(".") / "visualization_results.pdf"
fp_viz = Path(output_dir) / "visualization_results.pdf"
assert fp_viz.exists()