Link Search Menu Expand Document

Docker

Basic usage

The idea behind the docker wrapper script is simple: usage patterns should be indistinguishable from regular Napkin usage. It is possible to invoke any Napkin command, for example:

sh <(docker run --rm soostone/napkin-exe cat /bin/napkin-docker) init --project-name example
sh <(docker run --rm soostone/napkin-exe cat /bin/napkin-docker) validate --spec-file example/specs/spec.yaml --interactive
sh <(docker run --rm soostone/napkin-exe cat /bin/napkin-docker) haddock
sh <(docker run --rm soostone/napkin-exe cat /bin/napkin-docker) version

Advanced usage

If your Napkin project requires some extra haskell packages, which is usually specified in spec.yaml file:

spec.yaml

haskell_packages:
  - cassava
  - cassava-embed

It is still possible to use docker wrapper script like so:

shell

NAPKIN_EXTRA_PACKAGES="cassava cassava-embed" sh <(docker run --rm soostone/napkin-exe cat /bin/napkin-docker) validate
Building custom napkin image with extra cassava cassava-embed packages, it can take a minute...
sha256:707aab0cdce3d14929134cad2d8102bb463ef4377cdad3e1c59afa62d5342689
OK

Under the hood, wrapper script will build an extra layer to the base image with extra packages installed, so Napkin can see and use them with the following Nix expression:

nixpkgs.nix

(import https://github.com/NixOS/nixpkgs/archive/$NAPKIN_NIX_REVISION.tar.gz {})
  .haskell.packages.$NAPKIN_GHC_VERSION_COMPACT
  .ghcWithPackages (p: with p; [$NAPKIN_EXTRA_PACKAGES])

Note, that packages, specified with NAPKIN_EXTRA_PACKAGES variable, are pulled from Nix, so every package should exist in Nix, for example: cassava).

Technical details

Assumptions and internals

Docker wrapper script provides a way to run Napkin inside a container. Being executed inside a container, it needs access to the project files you are working on. Wrapper script makes an assumption, that it will be executed from the project root folder and mounts current folder from the host machine to the /project folder inside a container: --volume $PWD:/project.

Since Napkin uses user’s $HOME folder to cache BigQuery credentials in SQLite database, wrapper script also needs to mount .napkin folder from the host to the container: --volume $HOME/.napkin:/home/napkin/.napkin.

Occasionally, Napkin wants to open some links in the user’s browser (docs, BigQuery oAuth flow, etc.). Since there is no access to the host’s browser from the running container, wrapper scripts mounts a host-container pipe (temp folder based), sets up own tiny browser wrapper inside a container --volume $open:/tmp/open --volume $inbox:/tmp/inbox, listens to any invocations on the host, and opens host’s browser normally with help of standard open (on Mac) or xdg-open (on Linux) utilities. It is also possible to specify preferred browser with BROWSER environment variable.

BigQuery oAuth flow requires program to have a valid HTTP callback (has to be on localhost in case of standalone desktop program). But since Napkin in being run inside a container, wrapper script publishes the port from a container to host machine --publish $oauth_port:9901, which possible to override with corresponding environment variable: oauth_port="${NAPKIN_OAUTH_PORT:=9901}".

Commit policy

Wrapper script, extracted out of docker container to the host filesystem, contains exact versions of Napkin, nixpkgs and GHC compiler.

napkin-docker

image="soostone/napkin-exe:v0.5.7-9db950fa"
NAPKIN_GHC_VERSION_COMPACT="ghc8107"
NAPKIN_GHC_VERSION="ghc-8.10.7"

That is precisely why on first use you see such output from docker in your terminal (but on on subsequent invocations):

shell

sh <(docker run --rm soostone/napkin-exe cat /bin/napkin-docker) version
Unable to find image 'soostone/napkin-exe:v0.5.7-9db950fa' locally
v0.5.7-9db950fa: Pulling from soostone/napkin-exe
Digest: sha256:cccb09930b22216a7ab97f0eef0d4299d4a62a3e44928d23e88085eb25d98159
Status: Downloaded newer image for soostone/napkin-exe:v0.5.7-9db950fa
Napkin version: 0.5.7
Git commit hash: 9db950fad2469ed88522976f700c3f7446eb5176
Built at: 2021-12-02 17:35:21.03233944 UTC

Since wrapper script has docker image tag as soostone/napkin-exe:v0.5.7-9db950fa and not just soostone/napkin-exe:latest, it does an extra pull, but quickly realize then images are the same.

It is recommended to commit the wrapper script to the project git repository, so that other team members will use it.