Skip to content

Commit

Permalink
Streamline Dockerfile, remove unused deps
Browse files Browse the repository at this point in the history
 * 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.
  • Loading branch information
Lasall committed Oct 8, 2024
1 parent 4284119 commit 0f3c4bf
Show file tree
Hide file tree
Showing 13 changed files with 52 additions and 57 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
docs/
data/
cache/
output/

# Default ignore folders and files for VS Code, Python

Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -36,7 +36,7 @@ pre-commit install
Or run them manually:

```bash
pre-commit --all
pre-commit run --all-files
```

### Tests
Expand Down
36 changes: 23 additions & 13 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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}"]
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,7 @@ test:

# Run entire setup on docker
docker-run:
@docker compose up
@docker compose up --remove-orphans

docker-build:
@docker compose build
8 changes: 0 additions & 8 deletions README-DE.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,6 @@ source .venv/bin/activate

(wenn zsh verwendet wird, vor allem MacOS-Nutzende).

Sollte `pip install` die mariadb-Abhängigkeit nicht installieren können,
dann helfen folgende Kommandos:

* Debian/Ubuntu: `sudo apt-get install -y libmariadb-dev`
* Macos/Homebrew: `brew install mariadb-connector-c`

gefolgt von einem erneuten `pip install -r requirements.txt`.

## Nutzung

Einstellungen in `config.py` anpassen.
Expand Down
7 changes: 0 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,6 @@ source .venv/bin/activate
```
(if using zsh, primarily for MacOS users).

If `pip install` fails to install the mariadb dependency, the following commands may help:

* Debian/Ubuntu: `sudo apt-get install -y libmariadb-dev`
* MacOS/Homebrew: `brew install mariadb-connector-c`

Followed by a renewed `pip install -r requirements.txt`.

## Usage

Adjust `config.py`.
Expand Down
16 changes: 3 additions & 13 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
5 changes: 2 additions & 3 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
build==1.2.2.post1
-r requirements.txt
pytest==8.3.3
pytest-xprocess==1.0.2
requests==2.32.3
pytest-cov==5.0.0
pre-commit
4 changes: 0 additions & 4 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions src/akkudoktoreos/config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from datetime import datetime, timedelta

output_dir = "output"

prediction_hours = 48
optimization_hours = 24
strafe = 10
Expand Down
7 changes: 6 additions & 1 deletion src/akkudoktoreos/visualize.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import datetime
import os

# Set the backend for matplotlib to Agg
import matplotlib
Expand All @@ -7,6 +8,7 @@
from matplotlib.backends.backend_pdf import PdfPages

from akkudoktoreos.class_sommerzeit import ist_dst_wechsel
from akkudoktoreos.config import output_dir

matplotlib.use("Agg")

Expand All @@ -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)
Expand Down
11 changes: 8 additions & 3 deletions src/akkudoktoreosserver/flask_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@
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__)

Expand Down Expand Up @@ -255,11 +260,11 @@ def flask_optimize():
return jsonify(result) # Return optimization results as JSON


@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


Expand Down

0 comments on commit 0f3c4bf

Please sign in to comment.