-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathDockerfile
More file actions
196 lines (181 loc) · 10.7 KB
/
Copy pathDockerfile
File metadata and controls
196 lines (181 loc) · 10.7 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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# Dotfiles test/devbox container
# Build: docker build -t dotfiles .
# Run: docker run -it dotfiles
FROM ubuntu:24.04
# Build arguments for chezmoi configuration
# >>> dotfiles-init:args (generated by scripts/init/dotfiles_init.py gen) — DO NOT EDIT BY HAND >>>
ARG CHEZMOI_PROFILE=ubuntu_server
ARG CHEZMOI_EMAIL=docker@example.com
ARG CHEZMOI_NAME="Docker User"
ARG CHEZMOI_INSTALL_CODING_AGENTS=false
ARG CHEZMOI_INSTALL_LLM_TOOLS=false
ARG CHEZMOI_INSTALL_AI_DESKTOP_APPS=false
ARG CHEZMOI_INSTALL_PYTHON_UV_TOOLS=false
ARG CHEZMOI_INSTALL_JS_CLI_TOOLS=false
ARG CHEZMOI_INSTALL_DOTNET_TOOLS=false
ARG CHEZMOI_INSTALL_EXTRA_RUNTIMES=false
ARG CHEZMOI_INSTALL_AUDITD=false
ARG CHEZMOI_INSTALL_HOMELAB_TOOLS=false
ARG CHEZMOI_INSTALL_IAC_TOOLS=false
ARG CHEZMOI_INSTALL_MEDIA_TOOLS=false
ARG CHEZMOI_INSTALL_BITWARDEN=false
ARG CHEZMOI_INSTALL_MEDIA_CONTROL=false
ARG CHEZMOI_INSTALL_BREW_APPS=false
ARG CHEZMOI_INSTALL_GAMING_APPS=false
ARG CHEZMOI_INSTALL_INPUT_METHOD=false
ARG CHEZMOI_DISCORD_CHANNEL=none
ARG CHEZMOI_INSTALL_NIRI=false
ARG CHEZMOI_INSTALL_NETWORKING_TOOLS=false
ARG CHEZMOI_INSTALL_TUNNEL_TOOLS=false
ARG CHEZMOI_USE_CHINESE_MIRROR=false
ARG CHEZMOI_GITLEAKS_ALL_REPOS=false
ARG CHEZMOI_BACKUP_MODE=off
ARG CHEZMOI_ALLOW_PARTIAL_FAILURE=false
ARG CHEZMOI_NO_ROOT=false
ARG CHEZMOI_MOTD_STYLE=figlet
ARG CHEZMOI_PRIMARY_SHELL=zsh
ARG CHEZMOI_ENABLE_VIM_MODE=true
ARG CHEZMOI_REPO=daviddwlee84
# <<< dotfiles-init:args <<<
# Avoid interactive prompts during apt install
ENV DEBIAN_FRONTEND=noninteractive
# Configure HTTP mirror BEFORE installing ca-certificates (if in China)
# This solves the chicken-and-egg problem: HTTPS mirrors need ca-certificates,
# but installing ca-certificates from default repos fails under GFW
# Uses HTTP (not HTTPS) since ca-certificates isn't installed yet
RUN if [ "${CHEZMOI_USE_CHINESE_MIRROR}" = "true" ]; then \
ARCH=$(dpkg --print-architecture) && \
if [ "$ARCH" = "amd64" ]; then \
MIRROR_URL="http://repo.huaweicloud.com/ubuntu"; \
else \
MIRROR_URL="http://repo.huaweicloud.com/ubuntu-ports"; \
fi && \
printf '%s\n' \
"Types: deb" \
"URIs: ${MIRROR_URL}" \
"Suites: noble noble-updates noble-backports" \
"Components: main restricted universe multiverse" \
"Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg" \
"" \
"Types: deb" \
"URIs: ${MIRROR_URL}" \
"Suites: noble-security" \
"Components: main restricted universe multiverse" \
"Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg" \
> /etc/apt/sources.list.d/ubuntu.sources; \
fi
# Install ca-certificates (now using HTTP mirror if in China, default repos otherwise)
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Upgrade to HTTPS mirror after ca-certificates is installed (if in China)
# HTTPS is more secure for subsequent package installations
RUN if [ "${CHEZMOI_USE_CHINESE_MIRROR}" = "true" ]; then \
ARCH=$(dpkg --print-architecture) && \
if [ "$ARCH" = "amd64" ]; then \
MIRROR_URL="https://repo.huaweicloud.com/ubuntu"; \
else \
MIRROR_URL="https://repo.huaweicloud.com/ubuntu-ports"; \
fi && \
printf '%s\n' \
"Types: deb" \
"URIs: ${MIRROR_URL}" \
"Suites: noble noble-updates noble-backports" \
"Components: main restricted universe multiverse" \
"Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg" \
"" \
"Types: deb" \
"URIs: ${MIRROR_URL}" \
"Suites: noble-security" \
"Components: main restricted universe multiverse" \
"Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg" \
> /etc/apt/sources.list.d/ubuntu.sources; \
fi
# Install minimal dependencies
# - python3: required for ansible to run modules on localhost
# - jq: required by modify_ chezmoi scripts (e.g. dot_agents/modify_dot_skill-lock.json.tmpl)
# which run during `chezmoi apply` BEFORE the ansible base role
# installs jq system-wide. Without it chezmoi exits with
# `.agents/.skill-lock.json: exit status 127` (jq: command not found).
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
sudo \
git \
python3 \
jq \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user with sudo access
RUN useradd -m -s /bin/bash devuser \
&& echo "devuser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/devuser \
&& chmod 0440 /etc/sudoers.d/devuser
# Copy local dotfiles source into image
# This allows testing local changes without pushing to GitHub
COPY --chown=devuser:devuser . /tmp/dotfiles-source
# Switch to non-root user
USER devuser
WORKDIR /home/devuser
# Make ~/.local/bin available to all subsequent CMDs (bats, chezmoi, mise,
# uv, just, fd, etc. all live there after ansible's user-level installs).
# Docker's CMD doesn't load ~/.bashrc, so without this the test service's
# `command: ["bats", ...]` exits 127 even though bats is installed.
ENV PATH="/home/devuser/.local/bin:${PATH}"
# Install chezmoi binary
# Retry up to 3 times to handle network issues (especially behind GFW)
RUN for i in 1 2 3; do \
echo "Attempt $i: Installing chezmoi to ~/.local/bin..." && \
sh -c "$(curl -fsLS --retry 3 --retry-delay 5 get.chezmoi.io/lb)" && \
echo "chezmoi installed successfully" && break || \
{ echo "Attempt $i failed, retrying..."; sleep 10; }; \
done
# Initialize and apply dotfiles with prompt values passed via flags
# This avoids interactive prompts during Docker build
# Set PATH to include ~/.local/bin so run_once scripts can find uv tools (ansible)
# Use local source instead of cloning from GitHub to test local changes
# Note: installBrewApps=false and installAiDesktopApps=false by default
# >>> dotfiles-init:init-run (generated by scripts/init/dotfiles_init.py gen) — DO NOT EDIT BY HAND >>>
RUN export PATH="$HOME/.local/bin:$PATH" && \
~/.local/bin/chezmoi init --apply --source=/tmp/dotfiles-source \
--promptChoice "Which profile=${CHEZMOI_PROFILE}" \
--promptString "What is your email address=${CHEZMOI_EMAIL}" \
--promptString "What is your full name=${CHEZMOI_NAME}" \
--promptBool "Install coding agents (Claude Code, OpenCode, Cursor, Copilot, Gemini, etc.)=${CHEZMOI_INSTALL_CODING_AGENTS}" \
--promptBool "Install local LLM tools (Ollama, LiteLLM, llmfit, models)=${CHEZMOI_INSTALL_LLM_TOOLS}" \
--promptBool "Install AI desktop apps via macOS Homebrew Brewfile (Claude, ChatGPT, OpenCode, Antigravity, Codex, Ollama app)=${CHEZMOI_INSTALL_AI_DESKTOP_APPS}" \
--promptBool "Install Python CLI tools via uv (mlflow, sqlit-tui, tmuxp, etc.)=${CHEZMOI_INSTALL_PYTHON_UV_TOOLS}" \
--promptBool "Install standalone JS/npm CLI utilities (readability-cli for terminal web reader, etc.)=${CHEZMOI_INSTALL_JS_CLI_TOOLS}" \
--promptBool "Install .NET SDK via mise and dotnet global tools (azure-cost-cli, etc.)=${CHEZMOI_INSTALL_DOTNET_TOOLS}" \
--promptBool "Install extra mise runtimes (rust, bun, ruby) and their cargo/gem tools=${CHEZMOI_INSTALL_EXTRA_RUNTIMES}" \
--promptBool "Install Linux audit framework (auditd) + baseline rules (identity / sudoers / sshd_config / privileged-exec watches)=${CHEZMOI_INSTALL_AUDITD}" \
--promptBool "Install homelab hardware-monitoring tools (lm-sensors / smartmontools / ipmitool / nvme-cli / storcli), gated on detected hardware=${CHEZMOI_INSTALL_HOMELAB_TOOLS}" \
--promptBool "Install Infrastructure-as-Code tools (Azure CLI, Terraform, OpenTofu)=${CHEZMOI_INSTALL_IAC_TOOLS}" \
--promptBool "Install media/AV CLI tools (ffmpeg, ImageMagick, exiftool, libvips)=${CHEZMOI_INSTALL_MEDIA_TOOLS}" \
--promptBool "Install Bitwarden CLI (and Desktop on ubuntu_desktop/macOS — snap or .deb on Linux, Cask on macOS) with SSH Agent integration=${CHEZMOI_INSTALL_BITWARDEN}" \
--promptBool "Install system media-control CLIs (nowplaying-cli/switchaudio-osx on macOS, playerctl on Linux) for the sys* shell helpers=${CHEZMOI_INSTALL_MEDIA_CONTROL}" \
--promptBool "Install general GUI apps via Homebrew Brewfile (terminals, browsers, utilities, etc.; excludes AI desktop apps)=${CHEZMOI_INSTALL_BREW_APPS}" \
--promptBool "Install gaming apps (Steam)=${CHEZMOI_INSTALL_GAMING_APPS}" \
--promptBool "Install Traditional Chinese input methods (McBopomofo, RIME)=${CHEZMOI_INSTALL_INPUT_METHOD}" \
--promptChoice "Discord install channel (flatpak|deb|none)=${CHEZMOI_DISCORD_CHANNEL}" \
--promptBool "Install niri (scrollable-tiling Wayland compositor, built from source)=${CHEZMOI_INSTALL_NIRI}" \
--promptBool "Install networking CLI tools (nmap, mtr, httpie, gping, trippy, etc.)=${CHEZMOI_INSTALL_NETWORKING_TOOLS}" \
--promptBool "Install tunnel tools (ngrok, cloudflared — expose localhost, SSH tunnels)=${CHEZMOI_INSTALL_TUNNEL_TOOLS}" \
--promptBool "Are you in China (behind GFW) and need to use mirrors=${CHEZMOI_USE_CHINESE_MIRROR}" \
--promptBool "Enable gitleaks for ALL git repos (not just those with .pre-commit-config.yaml)=${CHEZMOI_GITLEAKS_ALL_REPOS}" \
--promptChoice "Backup mode for existing dotfiles (smart|full|off)=${CHEZMOI_BACKUP_MODE}" \
--promptBool "Allow partial Ansible failures (continue installing other tools if one role fails)=${CHEZMOI_ALLOW_PARTIAL_FAILURE}" \
--promptBool "No sudo/root access - skip all system package installations=${CHEZMOI_NO_ROOT}" \
--promptChoice "SSH login banner style (figlet|fastfetch-slim|fastfetch-full)=${CHEZMOI_MOTD_STYLE}" \
--promptChoice "Primary interactive shell (zsh|bash)=${CHEZMOI_PRIMARY_SHELL}" \
--promptBool "Enable vim-style modal editing in shells (zsh-vi-mode, set -o vi, ble.sh vi-mode) and tmux vim navigation (vim-tmux-navigator C-h/j/k/l, mode-keys vi); does NOT affect Neovim=${CHEZMOI_ENABLE_VIM_MODE}"
# <<< dotfiles-init:init-run <<<
# Make the source dir discoverable via chezmoi's default lookup path.
# `chezmoi init --apply --source=/tmp/dotfiles-source` only uses the
# override for the initial render — it does NOT persist sourceDir into
# ~/.config/chezmoi/chezmoi.toml or copy the source into the default
# ~/.local/share/chezmoi/. Without this symlink, a bare `chezmoi apply`
# (e.g. tests/smoke/docker_install.bats test #1) exits 1 with
# `chezmoi: stat /home/devuser/.local/share/chezmoi: no such file or
# directory`. The symlink mirrors what `chezmoi init <git-url>` would
# do when cloning a real repo.
RUN mkdir -p "$HOME/.local/share" \
&& ln -sfn /tmp/dotfiles-source "$HOME/.local/share/chezmoi"
# Default to bash shell
CMD ["/bin/bash"]