From 183e45c69830f644eda12b8fa1765fd1b51b9c4a Mon Sep 17 00:00:00 2001 From: Jakub Kaczmarzyk Date: Thu, 14 Oct 2021 20:41:15 -0400 Subject: [PATCH] replace dockerfile (#1410) * replaces Dockerfile using bazel-based build system This commit updates the Dockerfile to work with anki's bazel-based build system. The anki Dockerfile was originally added in https://github.com/ankitects/anki/pull/753 back in September 2020. The file was moved to `docs/Dockerfile` in 0d354da93aed3e5cfe5f5229c4543d2abc2d7352, with a note that the file had to be updated to work with anki's updated build system. The file `docs/Dockerfile` was removed in 7cd2e9618f9aa5aeae43272c3faf294e70aa462d. * install setuptools and wheel + xkb libraries * install anki virtual env in fresh base image * move Dockerfile out of root directory * add readme file for dockerized anki --- docs/docker/Dockerfile | 67 ++++++++++++++++++++++++ docs/docker/README.md | 112 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 docs/docker/Dockerfile create mode 100644 docs/docker/README.md diff --git a/docs/docker/Dockerfile b/docs/docker/Dockerfile new file mode 100644 index 000000000..cf41a9091 --- /dev/null +++ b/docs/docker/Dockerfile @@ -0,0 +1,67 @@ +# This Dockerfile uses three stages. +# 1. Compile anki (and dependencies) and build python wheels. +# 2. Create a virtual environment containing anki and its dependencies. +# 3. Create a final image that only includes anki's virtual environment and required +# system packages. + +ARG PYTHON_VERSION="3.9" +ARG DEBIAN_FRONTEND="noninteractive" + +# Build anki. +FROM python:$PYTHON_VERSION AS build +RUN curl -fsSL https://github.com/bazelbuild/bazelisk/releases/download/v1.7.4/bazelisk-linux-amd64 \ + > /usr/local/bin/bazel \ + && chmod +x /usr/local/bin/bazel \ + # Bazel expects /usr/bin/python + && ln -s /usr/local/bin/python /usr/bin/python +WORKDIR /opt/anki +COPY . . +# Build python wheels. +RUN ./scripts/build + +# Install pre-compiled Anki. +FROM python:${PYTHON_VERSION}-slim as installer +WORKDIR /opt/anki/ +COPY --from=build /opt/anki/bazel-dist/ wheels/ +# Use virtual environment. +RUN python -m venv venv \ + && ./venv/bin/python -m pip install --no-cache-dir setuptools wheel \ + && ./venv/bin/python -m pip install --no-cache-dir /opt/anki/wheels/*.whl + +# We use another build stage here so we don't include the wheels in the final image. +FROM python:${PYTHON_VERSION}-slim as final +COPY --from=installer /opt/anki/venv /opt/anki/venv +ENV PATH=/opt/anki/venv/bin:$PATH +# Install run-time dependencies. +RUN apt-get update \ + && apt-get install --yes --no-install-recommends \ + libasound2 \ + libdbus-1-3 \ + libfontconfig1 \ + libfreetype6 \ + libgl1 \ + libglib2.0-0 \ + libnss3 \ + libxcb-icccm4 \ + libxcb-image0 \ + libxcb-keysyms1 \ + libxcb-randr0 \ + libxcb-render-util0 \ + libxcb-shape0 \ + libxcb-xinerama0 \ + libxcb-xkb1 \ + libxcomposite1 \ + libxcursor1 \ + libxi6 \ + libxkbcommon0 \ + libxkbcommon-x11-0 \ + libxrandr2 \ + libxrender1 \ + libxtst6 \ + && rm -rf /var/lib/apt/lists/* +# Add non-root user. +RUN useradd --create-home anki +USER anki +WORKDIR /work +ENTRYPOINT ["/opt/anki/venv/bin/anki"] +LABEL maintainer="Jakub Kaczmarzyk " diff --git a/docs/docker/README.md b/docs/docker/README.md new file mode 100644 index 000000000..ae36fe76b --- /dev/null +++ b/docs/docker/README.md @@ -0,0 +1,112 @@ +# Anki in Docker + +This README contains the instructions for building and running the Anki Docker image. + +Docker provides a standard for installing software on many systems +(Windows, macOS, Linux), and it allows one to build software without cluttering a system +with dependencies. The Dockerfile contains the instructions for building the Docker image, +and it also serves as instructions for how to build Anki from source on Linux. + +# Build the Docker image + +For best results, enable BuildKit (`export DOCKER_BUILDKIT=1`). + +When in this current directory, one can build the Docker image like this: + +```bash +docker build --tag anki --file Dockerfile ../../ +``` + +When this is done, run `docker image ls` to see that the image has been created. + +If one wants to build from the project's root directory, use this command: + +```bash +docker build --tag anki --file docs/docker/Dockerfile . +``` + +# Run the Docker image + +Anki starts a graphical user interface, and this requires some extra setup on the user's +end. These instructions were tested on Linux (Debian 11) and will have to be adapted for +other operating systems. + +To allow the Docker container to pull up a graphical user interface, we need to run the +following: + +```bash +xhost +local:root +``` + +Once done using Anki, undo this with + +```bash +xhost -local:root +``` + +Then, we will construct our `docker run` command: + +```bash +docker run --rm -it \ + --name anki \ + --volume $HOME/.local/share:$HOME/.local/share:rw \ + --volume /etc/passwd:/etc/passwd:ro \ + --user $(id -u):$(id -g) \ + --volume /tmp/.X11-unix:/tmp/.X11-unix:rw \ + --env DISPLAY=$DISPLAY \ + anki +``` + +Here is a breakdown of some of the arguments: + +- Mount the current user's `~/.local/share` directory onto the container. Anki saves things + into this directory, and if we don't mount it, we will lose any changes once the + container exits. We mount this as read-write (`rw`) because we want to make changes here. + + ```bash + --volume $HOME/.local/share:$HOME/.local/share:rw + ``` + +- Mount `/etc/passwd` so we can enter the container as ourselves. We mount this as + read-only because we definitely do not want to modify this. + + ```bash + --volume /etc/passwd:/etc/passwd:ro + ``` + +- Enter the container with our user ID and group ID, so we stay as ourselves. + + ```bash + --user $(id -u):$(id -g) + ``` + +- Mount the X11 directory that allows us to open displays. + + ```bash + --volume /tmp/.X11-unix:/tmp/.X11-unix:rw + ``` + +- Pass the `DISPLAY` variable to the container, so it knows where to display graphics. + + ```bash + --env DISPLAY=$DISPLAY + ``` + +# Running Dockerized Anki easily from the command line + +One can create a shell function that executes the `docker run` command. Then one can +simply run `anki` on the command line, and Anki will open in Docker. Make sure to change +the image name to whatever you used when building Anki. + +```bash +anki() { + docker run --rm -it \ + --name anki \ + --volume $HOME/.local/share:$HOME/.local/share:rw \ + --volume /etc/passwd:/etc/passwd:ro \ + --user $(id -u):$(id -g) \ + --volume /tmp/.X11-unix:/tmp/.X11-unix:rw \ + --env DISPLAY=$DISPLAY \ + anki "$@" +} +```