-
-
Notifications
You must be signed in to change notification settings - Fork 108
Expand file tree
/
Copy pathDockerfile.dev
More file actions
131 lines (112 loc) · 5.55 KB
/
Dockerfile.dev
File metadata and controls
131 lines (112 loc) · 5.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# syntax=docker/dockerfile:1.7
#
# Two stages live here:
#
# - `base`: minimal image used as the `container:` for every CI job. Just
# enough to run `bun install`, `bun run …`, `just`, `psql`, `rsync`, ssh.
# Published as `ghcr.io/zkldi/tachi-ci`.
# - `dev`: superset of `base` with all the devcontainer QoL (fish, neovim,
# gh, ripgrep, fd, bat, fzf, mkdocs, minio-client, locales, sudo, the
# `tachi` user, ...). Published as `ghcr.io/zkldi/tachi-dev`.
#
# Always use `--no-install-recommends`. Debian's recommends-by-default pulls
# the full LLVM/Mesa/Vulkan/GCC chain in via various transitive deps and adds
# ~750MB of crap that nothing here actually needs.
# ---------------------------------------------------------------------------
# bun-src: just here so we can `COPY --from=` the binary into our stages.
#
# We deliberately track the same floating tag prod uses (see
# `docker/Dockerfile.server`, `FROM oven/bun:alpine`). The `debian` variant
# is used here because our base is `debian:13-slim` (glibc), not Alpine
# (musl). If/when prod pins a specific bun version, pin this to match.
# ---------------------------------------------------------------------------
FROM oven/bun:debian AS bun-src
# ---------------------------------------------------------------------------
# base: CI image
# ---------------------------------------------------------------------------
FROM debian:13-slim AS base
WORKDIR /tachi
# Add the official PostgreSQL APT repository so we can install client tools
# that match the server version (v18). The Debian-packaged postgresql-client
# only provides v17 on Debian 13 (trixie). `gnupg` is only needed to dearmor
# the keyring and is purged afterwards.
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates curl gnupg \
&& curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \
| gpg --dearmor -o /etc/apt/trusted.gpg.d/pgdg.gpg \
&& echo "deb https://apt.postgresql.org/pub/repos/apt trixie-pgdg main" \
> /etc/apt/sources.list.d/pgdg.list \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
# essentials for running the workspace in CI
git jq unzip just \
# vitest spawns workers via node; bun runs vitest itself but the
# worker subprocesses are node. With --no-install-recommends this
# pulls libnode115 but skips npm + nodejs-doc.
nodejs \
# postgres client tools (psql, pg_dump, pg_restore, pg_isready, ...)
postgresql-client-18 \
# rsync + ssh client for the homepage deploy job
rsync openssh-client \
&& apt-get purge -y gnupg \
&& apt-get autoremove -y \
&& rm -rf /var/lib/apt/lists/*
# bun — copied from the official oven/bun image (see BUN_VERSION arg at top).
# `bunx` is a symlink to `bun` in the upstream image; we recreate it here.
COPY --from=bun-src /usr/local/bin/bun /usr/local/bin/bun
RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx
# expose the db CLI globally
RUN ln -sf /tachi/typescript/db-cli/src/index.ts /usr/local/bin/tachidb
# ---------------------------------------------------------------------------
# dev: devcontainer image
# ---------------------------------------------------------------------------
FROM base AS dev
# so apt doesn't complain about the lack of a dialog-like program
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
# shell + editor + admin
fish neovim sudo locales \
# search / files / network / parallel
ripgrep fd-find bat fzf parallel wget \
# python stack for docs work (mkdocs is run via Dockerfile.docs in CI,
# but devs build/preview docs locally from here)
python-is-python3 python3-pip mkdocs mkdocs-material \
# github CLI for `gh auth login`-style flows
gh \
# MinIO CLI (binary is `minio-client`, not Midnight Commander's `mc`)
minio-client \
# `xdg-open` so the client vite plugin can launch a browser without
# crashing on missing binary (see typescript/client/vite.config.ts).
xdg-utils \
&& rm -rf /var/lib/apt/lists/*
ENV DEBIAN_FRONTEND=readline
# `fd` is called `fdfind` on debian. Awesome.
RUN ln -s "$(which fdfind)" /usr/bin/fd
# setup locales
# https://stackoverflow.com/questions/28405902/how-to-set-the-locale-inside-a-debian-ubuntu-docker-container
RUN echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen && locale-gen
ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
# https://github.com/python-babel/babel/issues/990
# it wouldn't be python without needing absurd global state manipulation to fix
# an incoherent error message
RUN rm -f /etc/localtime && ln -s /usr/share/zoneinfo/Etc/UTC /etc/localtime
# Fix locale issue perl repeatedly complains about
RUN echo "LC_ALL=en_US.UTF-8\nLANG=en_US.UTF-8" > /etc/default/locale
# create tachi user and give them sudo
RUN addgroup --gid 1000 tachi \
&& adduser --disabled-password --uid 1000 --gid 1000 --home /home/tachi tachi \
&& echo "tachi ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers
# Make the /tachi working directory owned by our user instead of root. Docker volumes
# are mounted as root UNLESS the folder already exists inside the host and has non-root
# ownership. This is the only way to declare a volume in docker has non-root ownership.
# Unbelievably obscure.
RUN chown -R tachi:tachi /tachi
USER tachi
# see above comment about non-root volumes
RUN mkdir node_modules
# keep container alive indefinitely
# Exclude .git from chown to avoid permission errors on macOS Docker mounts
# TODO(zk): What the fuck is this?
ENTRYPOINT ["sh", "-c", "sudo find /tachi -maxdepth 1 ! -name '.git' ! -name '/tachi' -exec chown -R tachi:tachi {} + 2>/dev/null || true; exec /bin/fish"]