Skip to content

Commit

Permalink
Improve size, security, and usability of the Dockerfile.
Browse files Browse the repository at this point in the history
This improves a few things about the Dockerfile:

1. Size
Caches are forgone, less bytecode is cached from build steps,
less is copied from the build context, and the final application is
stored in a zip.
A build arg has also been added to keep the spun-up containers smaller
by optionally suppressing writing bytecode files at runtime.

2. Security
`.env` files (and anything else sitting around with the build context)
are never committed to any layer of a container image.
The new `.dockerignore` prevents many such files from even being
visible during the build process.

3. Usability
The base image is now a fixed version of Python officially tested for
compatibility with Discord Autodelete, so the build process will remain
more stable over time. The container's `CMD` has been replaced with an
`ENTRYPOINT` so that arguments can easily be passed to it at runtime.
And, finally, code comments have been added to explain the role of the
Dockerfile in the context of this repository.
  • Loading branch information
Eta0 committed May 19, 2023
1 parent 3b04261 commit 59c90ff
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 6 deletions.
11 changes: 11 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# .env files with secrets should not be embedded in container images;
# mount them at runtime instead, either as a file,
# or directly as environment variables.
.env

**/__pycache__
**/*.pyc

*.egg-info
*.sqlite
*.log
60 changes: 54 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,58 @@
FROM python:alpine
# syntax=docker/dockerfile:1.2

RUN apk add sqlite-dev
## What's this?
# This Dockerfile creates a container image containing
# Python, Discord Autodelete's dependencies,
# and a zipapp of Discord Autodelete itself.

WORKDIR /bot
COPY ./ /bot
## Do I need this?
# This is *not* required to run Discord Autodelete;
# it is just another way of doing so, for people who like containers.

RUN python -m pip install -e .[speed]
## Notes for building
# This image must be built with BuildKit features available, e.g.
# by running `DOCKER_BUILDKIT=1 docker build .` in the source root.

CMD ["python", "-m", "discord_autodelete"]
## Notes for running (IMPORTANT)
# The resulting container MUST be run attached to persistent storage
# of some type, specifying the --database path accordingly.
# All autodelete configurations are stored in the --database file,
# so if it is lost, the bot's settings on all servers will vanish too.

FROM python:3.11.3-alpine3.18
RUN apk add --no-cache sqlite

WORKDIR /tmp/install
# Install dependencies and create a pre-compiled zipapp
RUN --mount=type=bind,target=.,rw \
# Modifications to this directory are ephemeral.
# Don't leave traces of bytecode compiled during this step
# due to python -m ... invocations, but newly installed packages
# can keep any deliberately pre-compiled bytecode.
export PYTHONDONTWRITEBYTECODE=1 && \
# Install dependencies n' such
python -m pip install --no-cache-dir .[speed] && \
# pip's cache can be a little stubborn
python -m pip cache purge && \
# Only .py files are needed for the rest of the install
find -type f ! -iname *.py -delete && \
# Pre-compile (zipapps are hard to add __pycache__ to later)
python -m compileall discord_autodelete && \
# Zip the entire directory to end up with a folder structure like
# ./discord_autodelete.zip/discord_autodelete/__init__.py
python -m zipfile -c ./discord_autodelete.zip discord_autodelete && \
# Install the finished zip
mkdir /app && cp ./discord_autodelete.zip /app/discord_autodelete.zip
WORKDIR /app

# Add discord_autodelete to the Python modules path for "-m" execution
ENV PYTHONPATH="/app/discord_autodelete.zip${PYTHONPATH:+:$PYTHONPATH}"

# Set this to disable all runtime Python bytecode file generation in the
# resulting image, slightly reducing performance, but also significantly
# reducing each container's disk usage footprint.
ARG NO_BYTECODE=""
ENV PYTHONDONTWRITEBYTECODE="{$NO_BYTECODE:+1}"

# --cwd-env is necessary for load_dotenv not to break from running as a zipapp
ENTRYPOINT ["python", "-m", "discord_autodelete", "--cwd-env"]

0 comments on commit 59c90ff

Please sign in to comment.