From 73286d7b0d2e245dc5273615376cd7c1d0b5573d Mon Sep 17 00:00:00 2001 From: "Allen D. Householder" Date: Mon, 24 Feb 2025 15:46:21 -0500 Subject: [PATCH] Dockerize the mkdocs dev server (#695) * refine Dockerfile to modularize targets * add Makefile to simplify container build & run process * update readme to explain makefile use * `markdownlint --fix .` * address common error where `ssvc` module is not found due to PYTHONPATH * add `venv` note * explain that ports in docker containers are local to the container * add basic `make` explainer * `markdownlint --fix .` * use long options --- Dockerfile | 21 +++++++++------ Makefile | 61 ++++++++++++++++++++++++++++++++++++++++++ README.md | 78 +++++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 145 insertions(+), 15 deletions(-) create mode 100644 Makefile diff --git a/Dockerfile b/Dockerfile index 37a6d682..79aa5836 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,23 @@ -FROM python:3.12-slim-bookworm - +FROM python:3.12-slim-bookworm AS base +RUN pip install --upgrade pip WORKDIR /app +FROM base AS dependencies + # install requirements COPY requirements.txt . RUN pip install -r requirements.txt - # Copy the files we need -COPY src/ . -COPY data ./data +COPY . /app +# Set the environment variable +ENV PYTHONPATH=/app/src + +FROM dependencies AS test # install pytest RUN pip install pytest - # run the unit tests \ -ENTRYPOINT ["pytest"] -CMD ["test"] +CMD ["pytest","src/test"] + +FROM dependencies AS docs +CMD ["mkdocs", "serve", "--dev-addr", "0.0.0.0:8000"] \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..40f8e7f0 --- /dev/null +++ b/Makefile @@ -0,0 +1,61 @@ +# Project-specific vars +PFX=ssvc +DOCKER=docker +DOCKER_BUILD=$(DOCKER) build +DOCKER_RUN=$(DOCKER) run --tty --rm +PROJECT_VOLUME=--volume $(shell pwd):/app +MKDOCS_PORT=8765 + +# docker names +TEST_DOCKER_TARGET=test +TEST_IMAGE = $(PFX)_test +DOCS_DOCKER_TARGET=docs +DOCS_IMAGE = $(PFX)_docs + +# Targets +.PHONY: all dockerbuild_test dockerrun_test dockerbuild_docs dockerrun_docs docs docker_test clean help + +all: help + +dockerbuild_test: + @echo "Building the test Docker image..." + $(DOCKER_BUILD) --target $(TEST_DOCKER_TARGET) --tag $(TEST_IMAGE) . + +dockerrun_test: + @echo "Running the test Docker image..." + $(DOCKER_RUN) $(PROJECT_VOLUME) $(TEST_IMAGE) + +dockerbuild_docs: + @echo "Building the docs Docker image..." + $(DOCKER_BUILD) --target $(DOCS_DOCKER_TARGET) --tag $(DOCS_IMAGE) . + +dockerrun_docs: + @echo "Running the docs Docker image..." + $(DOCKER_RUN) --publish $(MKDOCS_PORT):8000 $(PROJECT_VOLUME) $(DOCS_IMAGE) + + +docs: dockerbuild_docs dockerrun_docs +docker_test: dockerbuild_test dockerrun_test + +clean: + @echo "Cleaning up..." + $(DOCKER) rmi $(TEST_IMAGE) $(DOCS_IMAGE) || true + +help: + @echo "Usage: make [target]" + @echo "" + @echo "Targets:" + @echo " all - Display this help message" + @echo " docs - Build and run the docs Docker image" + @echo " docker_test - Build and run the test Docker image" + @echo "" + @echo " dockerbuild_test - Build the test Docker image" + @echo " dockerrun_test - Run the test Docker image" + @echo " dockerbuild_docs - Build the docs Docker image" + @echo " dockerrun_docs - Run the docs Docker image" + @echo "" + @echo " clean - Remove the Docker images" + @echo " help - Display this help message" + + + diff --git a/README.md b/README.md index 319c0a0f..e1bc0c1e 100644 --- a/README.md +++ b/README.md @@ -83,9 +83,55 @@ but it worked well enough for what was needed at the time. ## Local development -Install prerequisites: +The simplest way to get started with local development is to use Docker. +We provide a Dockerfile that builds an image with all the dependencies needed to build the site. +We also provide a `Makefile` that simplifies the process of building the site and running a local server, +so you don't have to remember the exact `docker build` and `docker run` commands +to get started. + +### Make Commands + +To display the available `make` commands, run: + +```bash +make help +``` + +To preview any `make` command without actually executing it, run: + +```bash +make -n +``` + +### Run Local Server With Docker + +The easiest way to get started is using make to build a docker image and run the site: + +```bash +make docs +``` + +Then navigate to to see the site. + +Note that the docker container will display a message with the URL to visit, for +example: `Serving on http://0.0.0.0:8000/SSVC/` in the output. However, that port +is only available inside the container. The host port 8765 is mapped to the container's +port 8000, so you should navigate to to see the site. + +Or, if make is not available: + +```bash +docker build --target docs --tag ssvc_docs . +docker run --tty --rm -p 8765:8000 --volume .:/app ssvc_docs +``` + +### Run Local Server Without Docker + +If you prefer to run the site locally without Docker, you can do so with mkdocs. +We recommend using a virtual environment to manage dependencies: ```bash +python3 -m venv ssvc_venv pip install -r requirements.txt ``` @@ -95,6 +141,8 @@ Start a local server: mkdocs serve ``` +By default, the server will run on port 8001. +This is configured in the `mkdocs.yml` file. Navigate to to see the site. (Hint: You can use the `--dev-addr` argument with mkdocs to change the port, e.g. `mkdocs serve --dev-addr localhost:8000`) @@ -103,20 +151,36 @@ Navigate to to see the site. We include a few tests for the `ssvc` module. -### With Docker +### Run Tests With Docker + +The easiest way to run tests is using make to build a docker image and run the tests: ```bash +make docker_test +``` + +Or, if make is not available: -docker build -t ssvc_test . -docker run -it --rm ssvc_test +```bash +docker build --target test --tag ssvc_test . +docker run --tty --rm --volume .:/app ssvc_test ``` -### Without Docker +### Run Tests Without Docker ```bash -pip install pytest # if you haven't already +pip install pytest +pytest src/test +``` -pytest # should find tests in src/test/* +## Environment Variables + +If you encounter a problem with the `ssvc` module not being found, you may need to set the `PYTHONPATH` environment variable. +The Dockerfile takes care of this in the Docker environment. +When not running in Docker, make sure that the `src` directory is in your `PYTHONPATH`: + +```bash +export PYTHONPATH=$PYTHONPATH:$(pwd)/src ``` ## Contributing