diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..78de158 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM alpine:latest + +RUN apk add python3 py3-pip +RUN pip3 install Flask cachelib + +# By default run on port 5000, because README.md currently mentions it +ARG PORT=5000 +EXPOSE $PORT + +COPY . BuildYourOwnLisp +WORKDIR BuildYourOwnLisp +# Make the containerized Flask server visible from the host machine +RUN sed --in-place s'/\(app.run(.*\))/\1, host="0.0.0.0")/' lispy.py +# Set PORT environment variable to ARG 'PORT' for lispy.py +ENV PORT=$PORT +CMD python3 lispy.py diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d23a532 --- /dev/null +++ b/Makefile @@ -0,0 +1,31 @@ +.PHONY: +# Make target-specific variables; so as to not pollute the Makefile +byol-docker: PORT := 5000 +# prev-byol is deliberately a recursively expanded variable as +# automatic variable $@ is not available outside of the recipes. +# If a docker image with the name 'byol-docker' already exists +# when this Make target is called, it expands to the id of that +# image; else, it expands to an empty string. +byol-docker: prev-byol = $(shell \ + docker inspect --format '{{ .ID }}' $@ \ + | sed s'/\(.*:\)\(.*\)/\2/' || echo "") +byol-docker: +# We need to delete (docker rmi) the existing 'byol-docker' image +# before we create a new one or else untagged images start +# piling up. However, we can't `docker rmi` that image before the +# build or else we'd lose the cache and will have to start over +# from the base image. Neither can we use `docker rmi --no-prune` +# as it, too, will pile up images since not all untagged +# parents of last image can be used as cache for the new build. +# (A quick look at the Dockerfile will show that any practical +# rebuild of the image will at least branch off from the Dockerfile +# instruction 'COPY . BuildYourOwnLisp') Therefore, we use $(eval) +# to create a Make variable, 'last-byol-image', and set it to the +# id of the previous byol docker image, so as to `rmi` it once the +# build is complete. + $(eval last-byol-image := $(prev-byol)) + docker build --build-arg PORT=$(PORT) --tag $@ . +# Now that the build is complete, delete the previous byol-docker image +# Also, ignore if this recipe's failure (when last-byol-image is "") + -docker rmi $(last-byol-image) > /dev/null 2>&1 + docker run --rm --publish $(PORT):$(PORT) $@ diff --git a/README.md b/README.md index 8a2f82d..04de640 100644 --- a/README.md +++ b/README.md @@ -34,3 +34,10 @@ env PORT=5000 python lispy.py ``` This will serve the site locally at `http://127.0.0.1:5000/`. You can browse it from there. + +Or, if you have docker installed, and don't want to install the dependencies locally, run: +``` +docker build --tag buildyourownlisp --build-arg PORT=5000 . +docker run --rm --publish 5000:5000 buildyourownlisp +``` +Or, perhaps, just let `make` take care of it all with `make [PORT=5000] byol-docker` \ No newline at end of file