Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build Docker images with Nix #36

Draft
wants to merge 21 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
---
name: Magic Wormhole Images
name: Debian Images

on:
push:
branches: [ "main" ]
tags: [ "*" ]
branches:
- main
paths:
- '.github/workflows/docker-image.yml'
- '*/Dockerfile'
- '*/Pipfile*'
- 'mailbox/welcome.motd'
pull_request:
branches: [ "main" ]
branches:
- main
paths:
- '.github/workflows/docker-image.yml'
- '*/Dockerfile'
- '*/Pipfile*'
- 'mailbox/welcome.motd'

jobs:
build:
name: Build images
runs-on: ubuntu-latest
strategy:
matrix:
Expand Down
67 changes: 67 additions & 0 deletions .github/workflows/docker-nix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
name: NixOS Images

on:
push:
branches:
- main
paths:
- '.github/workflows/docker-nix.yml'
- 'nixpkgs.json'
- '*.nix'
- '*/*.nix'
- 'nix/**'
pull_request:
branches:
- main
paths:
- '.github/workflows/docker-nix.yml'
- 'nixpkgs.json'
- '*.nix'
- '*/*.nix'
- 'nix/**'

jobs:
build:
name: Build images
runs-on: ubuntu-latest
strategy:
matrix:
target:
- directory: mailbox
image: leastauthority/magic-wormhole-mailbox
- directory: relay
image: leastauthority/magic-wormhole-relay
- directory: wormhole
image: leastauthority/magic-wormhole
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Install Nix
uses: cachix/install-nix-action@v20
with:
nix_path: nixpkgs=channel:nixos-22.11

- name: Build image with Nix
run: |
docker load --input $(nix-build ${{ matrix.target.directory }})

- name: Get image tag
run: echo "tag=$(docker images "${{ matrix.target.image }}" --format "{{.Tag}}")" >> $GITHUB_ENV

- name: Extract Python requirements
run: |
docker run --rm -t \
--entrypoint python \
-v $(pwd)/nix/helpers:/helpers \
${{ matrix.target.image }}:${{ env.tag }} /helpers/requirements-from-nix.py \
| grep -vE '==[0-9]+(\.[0-9]+){0,2}-dev' \
> requirements.txt
# The grep above avoids dupplicated requirements from dev!?

- name: Scan Python requirements
uses: pypa/gh-action-pip-audit@v1.0.0
with:
inputs: requirements.txt
continue-on-error: true # TODO: comment on PR and run weekly
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/.idea
result*
7 changes: 7 additions & 0 deletions default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{ pkgs ? import ./nixpkgs.nix { } }:
{
# Build our Docker images
mailbox = pkgs.callPackage ./mailbox { };
relay = pkgs.callPackage ./relay { };
wormhole = pkgs.callPackage ./wormhole { };
}
19 changes: 19 additions & 0 deletions mailbox/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{ pkgs ? import ../nixpkgs.nix { } }:
let
# Call our lib to build the image
output = pkgs.callPackage ../nix/lib/docker-image.nix {
pname = "magic-wormhole-mailbox-server";
iname = "leastauthority/magic-wormhole-mailbox";
config = {
WorkingDir = "/app";
Volumes = { "/db" = { }; };
Cmd = [
"twist"
"wormhole-mailbox"
"--usage-db=/db/usage-relay.sqlite"
"--blur-usage=3600"
"--channel-db=/db/relay.sqlite"
];
};
};
in output
20 changes: 20 additions & 0 deletions nix/helpers/requirements-from-nix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env python

import os
import re

# Pattern for Python modules
p = re.compile('python[0-9]+\.[0-9]+-(.+)-([0-9]+(\.[0-9]+){0,2})(-.+)?')

# Iterate through Nix store
for dir in os.listdir(os.getenv("NIX_STORE_DIR","/nix/store")):
# Remove the fix hash part
pkg = dir[33:]
# Match Python modules
m = p.match(pkg)
# Print as requirement
if m:
name = m.group(1)
version = m.group(2)
suffix = m.group(4) or ""
print('{}=={}{}'.format(name, version, suffix))
19 changes: 19 additions & 0 deletions nix/lib/docker-image.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{ dockerTools, python3, lib, pname, iname ? pname, config ? {} }:
let
# Inject mailbox in the standard Python env
pyenv = python3.buildEnv.override {
extraLibs = [ python3.pkgs.${pname} ];
ignoreCollisions = true;
};
# Parse Python package and NixOS versions to tag the image
pkgVersion = python3.pkgs.${pname}.version;
libVersion = lib.lists.flatten (lib.lists.sublist 1 1 (builtins.split "([^.]+)\.([^.]+)\.([^.]+)\.([^.]+)" lib.version));
nixVersion = builtins.concatStringsSep "." (lib.lists.take 3 libVersion);
in
# Build the image with our custom CMD
dockerTools.buildLayeredImage {
name = iname;
tag = "${pkgVersion}-nixos-${nixVersion}";
config = config;
contents = [ pyenv ];
}
5 changes: 5 additions & 0 deletions nixpkgs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "source",
"url": "https://releases.nixos.org/nixos/21.11/nixos-21.11.337975.eabc3821918/nixexprs.tar.xz",
"sha256": "1fq3zz7qfavksdbqvicns7hg61q3hhbxs2ibm818gy629hwkvsvm"
}
2 changes: 2 additions & 0 deletions nixpkgs.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Import local nixpkg.json which pins all our Nix packages
import (builtins.fetchTarball (builtins.fromJSON (builtins.readFile ./nixpkgs.json)))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to consider using a tool like npins or niv here, it will also make updating the pin much more pleasant

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was looking into niv, but I could not see how/if it is used for PrivateStorageio!
(I've just made a copy/paste :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@exarkun : how do we update nixpkgs in PrivateStorageio?

Copy link
Member

@hacklschorsch hacklschorsch May 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The shell script ci-tools/update-nixpkgs calls, in its function update_nixpkgs on line 160, update-nixpkgs defined in tools/default.nix line 17 via shell.nix line 6. That in turn calls the python script tools/update-nixpkgs to update nixpkgs.json.

The python script already broke once because the HTTP library it uses changed its API and we didn't have its version pinned.

That's why the moment @exarkun turns his back I'll replace the whole thing by my 12 line update-nixpkgs.sh shell script I have still sitting in my working directory which just creates a new JSON from a heredoc hr hr hr

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @hacklschorsch.
I was surprised there is not some nix command to do this...
And I was already trying to implement this in bash. :-)
I guess I'll not go further here.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I think there are nix commands built-in when using flakes …

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not dare pushing this experiment to the flake level :-)
Nice to know this could help to simplify the update of the nixpkgs.

I'll see later if I can spend some extra time to improve this (with npins, niv or flake).
Maybe interesting case for a "Nix Intro" session?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I won't be there this week because national holiday, but next week I could talk a bit about these

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No business value in adding yet another way to update one three line json file.

19 changes: 19 additions & 0 deletions relay/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{ pkgs ? import ../nixpkgs.nix { } }:
let
output = pkgs.callPackage ../nix/lib/docker-image.nix {
pname = "magic-wormhole-transit-relay";
iname = "leastauthority/magic-wormhole-relay";
config = {
WorkingDir = "/app";
Volumes = { "/db" = { }; };
Cmd = [
"twist"
"transitrelay"
"--usage-db=/db/usage-transitrelay.sqlite"
"--blur-usage=3600"
"--port=tcp:4001"
"--websocket=tcp:4002"
];
};
};
in output
14 changes: 14 additions & 0 deletions wormhole/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{ pkgs ? import ../nixpkgs.nix { } }:
let
# Call our lib to build the image
output = pkgs.callPackage ../nix/lib/docker-image.nix {
pname = "magic-wormhole";
iname = "leastauthority/magic-wormhole";
config = {
WorkingDir = "/app";
EntryPoint = [
"wormhole"
];
};
};
in output