Skip to content

Commit 9fcbb04

Browse files
committed
create nix dockerfile
1 parent f64de0b commit 9fcbb04

12 files changed

+615
-294
lines changed

.github/workflows/nix-build.yaml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: Build and Deploy Dockerfile
2+
3+
on:
4+
push:
5+
branches:
6+
- nix-dockerfile
7+
8+
env:
9+
DOCKER_TAG: ${{ secrets.DOCKER_HUB_USERNAME }}/audiobookrequest
10+
11+
jobs:
12+
website:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
with:
17+
submodules: recursive
18+
- name: Install Nix
19+
uses: DeterminateSystems/nix-installer-action@main
20+
- name: Enable magic Nix cache
21+
uses: DeterminateSystems/magic-nix-cache-action@main
22+
- name: Set version
23+
run: |
24+
if [ "${{ github.event_name }}" == "release" ]; then
25+
VERSION="${{ github.event.release.tag_name }}"
26+
echo $VERSION > static/version
27+
else
28+
github_sha_hash=${{ github.sha }}
29+
echo nightly:${github_sha_hash:0:7} > static/version
30+
fi
31+
- name: Build Docker image using Nix
32+
run: nix build ".#docker"
33+
34+
- name: Load image
35+
run: |
36+
export IMAGE_TAG=$(docker load < result | grep -Po 'Loaded image: \K.*')
37+
echo "Loaded image ${IMAGE_TAG}"
38+
echo "IMAGE_TAG=${IMAGE_TAG}" >> $GITHUB_ENV
39+
40+
- name: Login to Docker Hub
41+
uses: docker/login-action@v3
42+
with:
43+
username: ${{ secrets.DOCKER_HUB_USERNAME }}
44+
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
45+
46+
- name: Push image
47+
run: |
48+
if [ "${{ github.event_name }}" == "release" ]; then
49+
VERSION="${{ github.event.release.tag_name }}"
50+
MAJOR=$(echo $VERSION | cut -d. -f1)
51+
MINOR=$(echo $VERSION | cut -d. -f2)
52+
PATCH=$(echo $VERSION | cut -d. -f3)
53+
docker tag $IMAGE_TAG "${DOCKER_TAG}:$VERSION"
54+
docker tag $IMAGE_TAG "${DOCKER_TAG}:$MAJOR.$MINOR"
55+
docker tag $IMAGE_TAG "${DOCKER_TAG}:$MAJOR"
56+
docker push "${DOCKER_TAG}:$VERSION"
57+
docker push "${DOCKER_TAG}:$MAJOR.$MINOR"
58+
docker push "${DOCKER_TAG}:$MAJOR"
59+
else
60+
docker tag $IMAGE_TAG "${DOCKER_TAG}:nix-test"
61+
docker push "${DOCKER_TAG}:nix-test"
62+
fi

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ __pycache__
66
static/globals.css
77
config
88
node_modules
9+
result

Dockerfile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,11 @@ RUN uv sync --frozen --no-cache
2929

3030
COPY alembic/ alembic/
3131
COPY alembic.ini alembic.ini
32-
COPY styles/ styles/
3332
COPY static/ static/
3433
COPY templates/ templates/
3534
COPY app/ app/
3635

37-
RUN /bin/tailwindcss -i styles/globals.css -o static/globals.css -m
36+
RUN /bin/tailwindcss -i static/tw.css -o static/globals.css -m
3837

3938
ENV ABR_APP__PORT=8000
4039
ARG VERSION

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,9 @@ Website can be visited at http://localhost:8000.
200200

201201
```sh
202202
npm i
203-
uv run tailwindcss -i styles/globals.css -o static/globals.css --watch
203+
uv run tailwindcss -i static/tw.css -o static/globals.css --watch
204204
# Alternatively npx can be used to run tailwindcss
205-
npx @tailwindcss/cli@4 -i styles/globals.css -o static/globals.css --watch
205+
npx @tailwindcss/cli@4 -i static/tw.css -o static/globals.css --watch
206206
```
207207

208208
3. _Optional:_ Start browser-sync. This hot reloads the website when the html template or python files are modified:

flake.lock

Lines changed: 117 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 107 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,115 @@
11
{
2-
description = "A Nix-flake-based Python development environment";
3-
4-
inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1.*.tar.gz";
2+
description = "AudioBookRequest";
53

4+
inputs = {
5+
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
6+
flake-utils = {
7+
url = "github:numtide/flake-utils";
8+
inputs.nixpkgs.follows = "nixpkgs";
9+
};
10+
pyproject-nix = {
11+
url = "github:pyproject-nix/pyproject.nix";
12+
inputs.nixpkgs.follows = "nixpkgs";
13+
};
14+
uv2nix = {
15+
url = "github:pyproject-nix/uv2nix";
16+
inputs.pyproject-nix.follows = "pyproject-nix";
17+
inputs.nixpkgs.follows = "nixpkgs";
18+
};
19+
pyproject-build-systems = {
20+
url = "github:pyproject-nix/build-system-pkgs";
21+
inputs.pyproject-nix.follows = "pyproject-nix";
22+
inputs.uv2nix.follows = "uv2nix";
23+
inputs.nixpkgs.follows = "nixpkgs";
24+
};
25+
};
626

7-
outputs = { self, nixpkgs, ... }:
27+
outputs = { self, nixpkgs, flake-utils, pyproject-nix, uv2nix, pyproject-build-systems, ... }: flake-utils.lib.eachDefaultSystem (system:
828
let
9-
supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
10-
forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f {
11-
pkgs = import nixpkgs { inherit system; };
12-
});
29+
pkgs = import nixpkgs { inherit system; };
30+
python = pkgs.python312;
31+
workspace = uv2nix.lib.workspace.loadWorkspace { workspaceRoot = ./.; };
32+
33+
pyprojectOverrides = final: prev: {
34+
# both fastapi and fastapi-cli add the binary causing "FileCollisionError: Two or more packages are trying to provide the same file with different contents"
35+
fastapi-cli = prev.fastapi-cli.overrideAttrs(_: { postInstall = "rm $out/bin/fastapi"; });
36+
};
37+
38+
overlay = workspace.mkPyprojectOverlay { sourcePreference = "wheel"; };
39+
pythonSet = (pkgs.callPackage pyproject-nix.build.packages { inherit python; }).overrideScope (
40+
pkgs.lib.composeManyExtensions [
41+
pyproject-build-systems.overlays.default
42+
overlay
43+
pyprojectOverrides
44+
]
45+
);
1346
in
14-
{
47+
rec {
48+
packages = rec {
49+
# Creates a separate nix store virtualenv with the default dependencies (no devDependencies)
50+
default = pythonSet.mkVirtualEnv "audiobookrequest-venv" workspace.deps.default;
1551

16-
devShells = forEachSupportedSystem ({ pkgs }: {
17-
default = pkgs.mkShell {
18-
venvDir = ".venv";
19-
packages = with pkgs; [ python312 nodejs_23 sqlite nodePackages.browser-sync uv ] ++
20-
(with pkgs.python312Packages; [
21-
venvShellHook
22-
]);
52+
53+
docker =
54+
let
55+
npmDeps = pkgs.importNpmLock.buildNodeModules {
56+
package = pkgs.lib.importJSON ./package.json;
57+
packageLock = pkgs.lib.importJSON ./package-lock.json;
58+
nodejs = pkgs.nodejs_23;
59+
};
60+
tw-init = pkgs.writeShellScriptBin "tw-init" ''
61+
ln -s ${npmDeps}/node_modules node_modules
62+
cp ${./static/tw.css} tw.css # copy over the file since tailwind looks for daisyui relative to the input file
63+
${pkgs.tailwindcss_4}/bin/tailwindcss -i tw.css -o $out/app/static/globals.css -m
64+
'';
65+
run = pkgs.writeShellScriptBin "run" ''
66+
${default}/bin/alembic upgrade heads
67+
${default}/bin/fastapi run --port $ABR_APP__PORT
68+
'';
69+
gitignore = pkgs.nix-gitignore.gitignoreSource [ ] ./.;
70+
in
71+
pkgs.dockerTools.buildImage {
72+
name = "audiobookrequest";
73+
74+
copyToRoot = pkgs.buildEnv {
75+
name = "test";
76+
paths = [];
77+
postBuild = ''
78+
mkdir -p $out/app/static
79+
${tw-init}/bin/tw-init
80+
cp ${gitignore}/alembic.ini $out/app/alembic.ini
81+
cp -r ${gitignore}/alembic $out/app/alembic
82+
cp -r ${gitignore}/templates $out/app/templates
83+
cp -r ${gitignore}/static $out/app/static
84+
cp -r ${gitignore}/app $out/app/app
85+
'';
86+
};
87+
88+
config = {
89+
WorkingDir = "/app";
90+
Cmd = [ "${run}/bin/run" ];
91+
ExposedPorts = {
92+
"8000/tcp" = {};
93+
};
94+
Env = [
95+
"ABR_APP__PORT=8000"
96+
"ABR_APP__VERSION=${builtins.readFile ./static/version}"
97+
];
98+
};
2399
};
24-
});
25-
};
100+
};
101+
102+
# What is run when we use `nix run . -- dev`
103+
apps.default = {
104+
type = "app";
105+
program = "${packages.default}/bin/fastapi";
106+
};
107+
108+
# Create a .venv and activates it. Allows for the venv to easily be selected in the editor for the python interpreter
109+
devShells.default = pkgs.mkShell {
110+
venvDir = ".venv";
111+
packages = with pkgs; [ nodejs_23 sqlite nodePackages.browser-sync python312Packages.venvShellHook uv ];
112+
postShellHook = "uv sync";
113+
};
114+
});
26115
}

0 commit comments

Comments
 (0)