remote-docker-cli 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -150,4 +150,8 @@ cython_debug/
150
150
  /.hatch/
151
151
  /build_artifacts/
152
152
 
153
- uv.lock
153
+ .opencode
154
+ uv.lock
155
+
156
+ # rdocker kaggle notebook staging dir (created by `rdocker kaggle upload`)
157
+ .kaggle/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: remote-docker-cli
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: A CLI tool for managing remote Docker hosts
5
5
  Project-URL: Homepage, https://gitee.com/kzhuo/remote-docker
6
6
  Project-URL: Issues, https://gitee.com/kzhuo/remote-docker/issues
@@ -24,8 +24,8 @@ Classifier: Topic :: System :: Systems Administration
24
24
  Requires-Python: >=3.10
25
25
  Requires-Dist: click
26
26
  Requires-Dist: pyyaml
27
- Provides-Extra: all
28
- Requires-Dist: paramiko>=3.0; extra == 'all'
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=7.0; extra == 'dev'
29
29
  Provides-Extra: ssh
30
30
  Requires-Dist: paramiko>=3.0; extra == 'ssh'
31
31
  Description-Content-Type: text/markdown
@@ -64,6 +64,29 @@ Description-Content-Type: text/markdown
64
64
 
65
65
  `skopeo copy` 会带上 `--override-arch` 选项,自动按本地机器架构 (`amd64` / `arm64` / ...) 拉取对应镜像清单。
66
66
 
67
+ ### 可选通道:Kaggle(无需 SSH 跳板机)
68
+
69
+ ```
70
+ 本地机器 Kaggle (Notebook)
71
+ ┌────────────────────┐ ┌──────────────────────────────┐
72
+ │ docker-compose.yml │ │ /kaggle/working/<name>/ │
73
+ └────────┬───────────┘ │ ├── nginx_latest.tar │
74
+ │ 解析 + 自动补 :latest │ ├── redis_7-alpine.tar │
75
+ ▼ │ └── ... │
76
+ 镜像列表 ──`kaggle kernels push`───▶ │ skopeo copy --override-arch │
77
+ (在 .kaggle/<name>/ 暂存) │ │
78
+ │ tar -czf <name>.tar.gz . │
79
+ └──────────────┬───────────────┘
80
+ │ output
81
+ ▼
82
+ ./<name>.tar.gz ← 本地产物
83
+ │ docker load
84
+ ▼
85
+ 本地 Docker 引擎
86
+ ```
87
+
88
+ 详见 [Kaggle 通道](#kaggle-通道) 一节。
89
+
67
90
  ---
68
91
 
69
92
  ## 安装
@@ -285,18 +308,18 @@ rdocker fetch --name mybundle --output-dir ./dist --try
285
308
  - `--output-dir, -o` — 本地输出目录(默认:`.`)
286
309
  - `--try` — 干跑模式
287
310
 
288
- ### `rdocker load [--name <bundle> | --file <tar.gz>] [--try]`
289
- 解压本地 `.tar.gz` 并依次 `docker load` 每个镜像;如果本地文件不存在且指定了 `--name`,会自动从远端 fetch。
311
+ ### `rdocker load <tar.gz> [--try]`
312
+ 解压本地 `.tar.gz` 并依次 `docker load` 每个镜像。`FILE` 是必填的位置参数;不再支持 `--name`/`--file` 选项,也不再自动从远端 fetch —— 需要远端文件时请显式 `rdocker fetch` / `rdocker kaggle fetch` 之后再 `rdocker load`。
290
313
 
291
314
  ```bash
292
- rdocker load --name mybundle
293
- rdocker load --file ./mybundle.tar.gz
294
- rdocker load --name mybundle --try # 本地无文件时打印会触发的 scp + load
315
+ rdocker load ./mybundle.tar.gz
316
+ rdocker load ./myapp.tar.gz --try # 打印将要执行的 tar 解压 + docker load 命令
295
317
  ```
296
318
 
319
+ 参数:
320
+ - `FILE` — 本地 `.tar.gz` 文件路径(必填,必须存在)
321
+
297
322
  选项:
298
- - `--name, -n` — Bundle 名称(与 `--file` 二选一)
299
- - `--file, -f` — 本地 `.tar.gz` 文件路径
300
323
  - `--try` — 干跑模式
301
324
 
302
325
  ### `rdocker cleanup [--name <bundle>] [--try]`
@@ -313,6 +336,82 @@ rdocker cleanup --name mybundle --try
313
336
 
314
337
  ---
315
338
 
339
+ ## Kaggle 通道
340
+
341
+ 无 SSH 跳板机时,可把镜像拉取与打包放到 Kaggle 的一次性 notebook 上跑,产出的 `.tar.gz` 走 `kaggle kernels output` 下载到本地,再被 `rdocker load` 直接消费。
342
+
343
+ ### 前置条件
344
+
345
+ 1. Kaggle 账号(任意注册方式都可)。
346
+ 2. `pip install kaggle`(Python ≥ 3.10)。
347
+ 3. 配置 Kaggle 凭据,使 `kaggle config view` 能输出非空 `username`:
348
+ - 首次会引导你把 API token 放到 `~/.kaggle/credentials.json`,**或**
349
+ - 设置环境变量 `KAGGLE_USERNAME` / `KAGGLE_KEY`。
350
+ 4. 验证:`kaggle config view` 应当看到一行 `- username: <你的名字>`。
351
+
352
+ ### 三步工作流
353
+
354
+ ```bash
355
+ # 1. 解析 compose 并推送一个 notebook 到 Kaggle
356
+ rdocker kaggle upload docker-compose.yml --name myapp
357
+
358
+ # 2. 等待 kernel 在 Kaggle 网站跑完(通常几分钟)
359
+ # 可在 https://www.kaggle.com/<username>/rdocker-myapp 看日志
360
+
361
+ # 3. 下载产出的 .tar.gz 到本地
362
+ rdocker kaggle fetch --name myapp
363
+
364
+ # 4. 加载到本地 Docker
365
+ rdocker load ./myapp.tar.gz
366
+ ```
367
+
368
+ ### `rdocker kaggle upload <compose_file> [--name <bundle>] [--try]`
369
+
370
+ 解析 `docker-compose.yml`、在 `.kaggle/<bundle>/` 暂存一个 `rdocker.py` 与 `kernel-metadata.json`、调用 `kaggle kernels push` 推上去。`--try` 模式下不写盘也不推送,只在 stdout 打印将要上传的 notebook 完整内容(含 skopeo 安装段、镜像循环、最终 tar 打包),方便审核。
371
+
372
+ ```bash
373
+ rdocker kaggle upload docker-compose.yml # --name 缺省 = cwd 短名
374
+ rdocker kaggle upload docker-compose.yml --name prod --registry-auth admin:pass
375
+ rdocker kaggle upload docker-compose.yml --try # 只打印不推送
376
+ ```
377
+
378
+ 选项:
379
+ - `--name, -n` — Bundle 名称(缺省 = cwd 短名)
380
+ - `--registry-auth, -a` — 镜像仓库认证 `user:pass`
381
+ - `--try` — 干跑:只打印 notebook 内容
382
+
383
+ ### `rdocker kaggle fetch [--name <bundle>] [--output-dir <dir>] [--try]`
384
+
385
+ 从 Kaggle 下载 `<bundle>.tar.gz` 到本地。下载后可被 `rdocker load <bundle>.tar.gz` 直接消费。
386
+
387
+ ```bash
388
+ rdocker kaggle fetch --name myapp # 下载到 cwd
389
+ rdocker kaggle fetch --name myapp --output-dir ./dist # 下载到 ./dist
390
+ rdocker kaggle fetch --name myapp --try # 只打印命令
391
+ ```
392
+
393
+ 选项:
394
+ - `--name, -n` — Bundle 名称(缺省 = cwd 短名)
395
+ - `--output-dir, -o` — 本地输出目录(默认:`.`)
396
+ - `--try` — 干跑:只打印 `kaggle kernels output` 命令
397
+
398
+ ### 内部机制
399
+
400
+ - **username 解析**:`rdocker` 不直接读 `~/.kaggle/credentials.json`,而是 `subprocess.run(["kaggle", "config", "view"])` 并解析 `- username: <name>` 行 —— 自动跟随 Kaggle CLI 自身的配置源优先级(环境变量 > `~/.kaggle/` > `/etc/kaggle.json`)。
401
+ - **kernel 命名**:固定为 `<username>/rdocker-<bundle>`,私有(`is_private: true`),便于 `fetch` 端稳定定位。
402
+ - **架构**:`skopeo --override-arch <local_arch>` 的 arch 在本地计算后注入 notebook,确保拉到的镜像清单与本地 Docker 引擎匹配。
403
+ - **skopeo 兜底**:notebook 第一段是 `which skopeo || apt-get install -y skopeo || pip install skopeo`(Kaggle 基础镜像通常自带,但本工具不依赖此假设)。
404
+
405
+ ### 常见问题
406
+
407
+ - **kaggle CLI 缺失 / 未配置** → `pip install kaggle` 后 `kaggle config view` 验证。`rdocker` 会把错误指向这两步。
408
+ - **kernel 跑失败** → 在 https://www.kaggle.com/<username>/rdocker-<bundle> 看 stderr;常因镜像仓库私有需 `--registry-auth`,或 compose 中含 Kaggle 网络策略拉不到的镜像。
409
+ - **arch 不匹配** → `rdocker` 默认按本地 `platform.machine()` 注入 `--override-arch`;如需覆盖,临时改 `KAGGLE_NOTEBOOK_TEMPLATE` 中的 `ARCH` 注入值(进阶用法)。
410
+ - **output 还没生成** → `kaggle kernels output` 报错时直接看返回的 stderr;常见原因是 kernel 仍在排队(免费版 CPU 偶尔排队几分钟)或已失败。
411
+ - **`.kaggle/` 目录膨胀** → 该目录在 CWD 下,是 `kaggle kernels push` 的暂存区,可随时 `rm -rf .kaggle`。
412
+
413
+ ---
414
+
316
415
  ## 环境变量
317
416
 
318
417
  | 变量 | 对应配置 | 说明 |
@@ -32,6 +32,29 @@
32
32
 
33
33
  `skopeo copy` 会带上 `--override-arch` 选项,自动按本地机器架构 (`amd64` / `arm64` / ...) 拉取对应镜像清单。
34
34
 
35
+ ### 可选通道:Kaggle(无需 SSH 跳板机)
36
+
37
+ ```
38
+ 本地机器 Kaggle (Notebook)
39
+ ┌────────────────────┐ ┌──────────────────────────────┐
40
+ │ docker-compose.yml │ │ /kaggle/working/<name>/ │
41
+ └────────┬───────────┘ │ ├── nginx_latest.tar │
42
+ │ 解析 + 自动补 :latest │ ├── redis_7-alpine.tar │
43
+ ▼ │ └── ... │
44
+ 镜像列表 ──`kaggle kernels push`───▶ │ skopeo copy --override-arch │
45
+ (在 .kaggle/<name>/ 暂存) │ │
46
+ │ tar -czf <name>.tar.gz . │
47
+ └──────────────┬───────────────┘
48
+ │ output
49
+ ▼
50
+ ./<name>.tar.gz ← 本地产物
51
+ │ docker load
52
+ ▼
53
+ 本地 Docker 引擎
54
+ ```
55
+
56
+ 详见 [Kaggle 通道](#kaggle-通道) 一节。
57
+
35
58
  ---
36
59
 
37
60
  ## 安装
@@ -253,18 +276,18 @@ rdocker fetch --name mybundle --output-dir ./dist --try
253
276
  - `--output-dir, -o` — 本地输出目录(默认:`.`)
254
277
  - `--try` — 干跑模式
255
278
 
256
- ### `rdocker load [--name <bundle> | --file <tar.gz>] [--try]`
257
- 解压本地 `.tar.gz` 并依次 `docker load` 每个镜像;如果本地文件不存在且指定了 `--name`,会自动从远端 fetch。
279
+ ### `rdocker load <tar.gz> [--try]`
280
+ 解压本地 `.tar.gz` 并依次 `docker load` 每个镜像。`FILE` 是必填的位置参数;不再支持 `--name`/`--file` 选项,也不再自动从远端 fetch —— 需要远端文件时请显式 `rdocker fetch` / `rdocker kaggle fetch` 之后再 `rdocker load`。
258
281
 
259
282
  ```bash
260
- rdocker load --name mybundle
261
- rdocker load --file ./mybundle.tar.gz
262
- rdocker load --name mybundle --try # 本地无文件时打印会触发的 scp + load
283
+ rdocker load ./mybundle.tar.gz
284
+ rdocker load ./myapp.tar.gz --try # 打印将要执行的 tar 解压 + docker load 命令
263
285
  ```
264
286
 
287
+ 参数:
288
+ - `FILE` — 本地 `.tar.gz` 文件路径(必填,必须存在)
289
+
265
290
  选项:
266
- - `--name, -n` — Bundle 名称(与 `--file` 二选一)
267
- - `--file, -f` — 本地 `.tar.gz` 文件路径
268
291
  - `--try` — 干跑模式
269
292
 
270
293
  ### `rdocker cleanup [--name <bundle>] [--try]`
@@ -281,6 +304,82 @@ rdocker cleanup --name mybundle --try
281
304
 
282
305
  ---
283
306
 
307
+ ## Kaggle 通道
308
+
309
+ 无 SSH 跳板机时,可把镜像拉取与打包放到 Kaggle 的一次性 notebook 上跑,产出的 `.tar.gz` 走 `kaggle kernels output` 下载到本地,再被 `rdocker load` 直接消费。
310
+
311
+ ### 前置条件
312
+
313
+ 1. Kaggle 账号(任意注册方式都可)。
314
+ 2. `pip install kaggle`(Python ≥ 3.10)。
315
+ 3. 配置 Kaggle 凭据,使 `kaggle config view` 能输出非空 `username`:
316
+ - 首次会引导你把 API token 放到 `~/.kaggle/credentials.json`,**或**
317
+ - 设置环境变量 `KAGGLE_USERNAME` / `KAGGLE_KEY`。
318
+ 4. 验证:`kaggle config view` 应当看到一行 `- username: <你的名字>`。
319
+
320
+ ### 三步工作流
321
+
322
+ ```bash
323
+ # 1. 解析 compose 并推送一个 notebook 到 Kaggle
324
+ rdocker kaggle upload docker-compose.yml --name myapp
325
+
326
+ # 2. 等待 kernel 在 Kaggle 网站跑完(通常几分钟)
327
+ # 可在 https://www.kaggle.com/<username>/rdocker-myapp 看日志
328
+
329
+ # 3. 下载产出的 .tar.gz 到本地
330
+ rdocker kaggle fetch --name myapp
331
+
332
+ # 4. 加载到本地 Docker
333
+ rdocker load ./myapp.tar.gz
334
+ ```
335
+
336
+ ### `rdocker kaggle upload <compose_file> [--name <bundle>] [--try]`
337
+
338
+ 解析 `docker-compose.yml`、在 `.kaggle/<bundle>/` 暂存一个 `rdocker.py` 与 `kernel-metadata.json`、调用 `kaggle kernels push` 推上去。`--try` 模式下不写盘也不推送,只在 stdout 打印将要上传的 notebook 完整内容(含 skopeo 安装段、镜像循环、最终 tar 打包),方便审核。
339
+
340
+ ```bash
341
+ rdocker kaggle upload docker-compose.yml # --name 缺省 = cwd 短名
342
+ rdocker kaggle upload docker-compose.yml --name prod --registry-auth admin:pass
343
+ rdocker kaggle upload docker-compose.yml --try # 只打印不推送
344
+ ```
345
+
346
+ 选项:
347
+ - `--name, -n` — Bundle 名称(缺省 = cwd 短名)
348
+ - `--registry-auth, -a` — 镜像仓库认证 `user:pass`
349
+ - `--try` — 干跑:只打印 notebook 内容
350
+
351
+ ### `rdocker kaggle fetch [--name <bundle>] [--output-dir <dir>] [--try]`
352
+
353
+ 从 Kaggle 下载 `<bundle>.tar.gz` 到本地。下载后可被 `rdocker load <bundle>.tar.gz` 直接消费。
354
+
355
+ ```bash
356
+ rdocker kaggle fetch --name myapp # 下载到 cwd
357
+ rdocker kaggle fetch --name myapp --output-dir ./dist # 下载到 ./dist
358
+ rdocker kaggle fetch --name myapp --try # 只打印命令
359
+ ```
360
+
361
+ 选项:
362
+ - `--name, -n` — Bundle 名称(缺省 = cwd 短名)
363
+ - `--output-dir, -o` — 本地输出目录(默认:`.`)
364
+ - `--try` — 干跑:只打印 `kaggle kernels output` 命令
365
+
366
+ ### 内部机制
367
+
368
+ - **username 解析**:`rdocker` 不直接读 `~/.kaggle/credentials.json`,而是 `subprocess.run(["kaggle", "config", "view"])` 并解析 `- username: <name>` 行 —— 自动跟随 Kaggle CLI 自身的配置源优先级(环境变量 > `~/.kaggle/` > `/etc/kaggle.json`)。
369
+ - **kernel 命名**:固定为 `<username>/rdocker-<bundle>`,私有(`is_private: true`),便于 `fetch` 端稳定定位。
370
+ - **架构**:`skopeo --override-arch <local_arch>` 的 arch 在本地计算后注入 notebook,确保拉到的镜像清单与本地 Docker 引擎匹配。
371
+ - **skopeo 兜底**:notebook 第一段是 `which skopeo || apt-get install -y skopeo || pip install skopeo`(Kaggle 基础镜像通常自带,但本工具不依赖此假设)。
372
+
373
+ ### 常见问题
374
+
375
+ - **kaggle CLI 缺失 / 未配置** → `pip install kaggle` 后 `kaggle config view` 验证。`rdocker` 会把错误指向这两步。
376
+ - **kernel 跑失败** → 在 https://www.kaggle.com/<username>/rdocker-<bundle> 看 stderr;常因镜像仓库私有需 `--registry-auth`,或 compose 中含 Kaggle 网络策略拉不到的镜像。
377
+ - **arch 不匹配** → `rdocker` 默认按本地 `platform.machine()` 注入 `--override-arch`;如需覆盖,临时改 `KAGGLE_NOTEBOOK_TEMPLATE` 中的 `ARCH` 注入值(进阶用法)。
378
+ - **output 还没生成** → `kaggle kernels output` 报错时直接看返回的 stderr;常见原因是 kernel 仍在排队(免费版 CPU 偶尔排队几分钟)或已失败。
379
+ - **`.kaggle/` 目录膨胀** → 该目录在 CWD 下,是 `kaggle kernels push` 的暂存区,可随时 `rm -rf .kaggle`。
380
+
381
+ ---
382
+
284
383
  ## 环境变量
285
384
 
286
385
  | 变量 | 对应配置 | 说明 |
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "remote-docker-cli"
7
- version = "0.2.0"
7
+ dynamic = ["version"]
8
8
  description = "A CLI tool for managing remote Docker hosts"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -37,8 +37,8 @@ dependencies = [
37
37
  ssh = [
38
38
  "paramiko>=3.0",
39
39
  ]
40
- all = [
41
- "remote-docker-cli[ssh]",
40
+ dev = [
41
+ "pytest>=7.0",
42
42
  ]
43
43
 
44
44
  [project.scripts]
@@ -49,13 +49,15 @@ Homepage = "https://gitee.com/kzhuo/remote-docker"
49
49
  Issues = "https://gitee.com/kzhuo/remote-docker/issues"
50
50
  Repository = "https://gitee.com/kzhuo/remote-docker"
51
51
 
52
+ [tool.hatch.version]
53
+ path = "src/remote_docker/__init__.py"
54
+
52
55
  [tool.hatch.build.targets.wheel]
53
56
  packages = ["src/remote_docker"]
54
57
 
55
58
  [tool.hatch.build.targets.sdist]
56
59
  include = [
57
60
  "src/remote_docker",
58
- "tests",
59
61
  "README.md",
60
62
  "LICENSE",
61
63
  "pyproject.toml",
@@ -65,4 +67,8 @@ exclude = [
65
67
  ".venv",
66
68
  "venv",
67
69
  "__pycache__",
68
- ]
70
+ ]
71
+
72
+ [tool.pytest.ini_options]
73
+ testpaths = ["src"]
74
+ pythonpath = ["src"]
@@ -1,3 +1,3 @@
1
1
  """remote-docker: A CLI tool for managing remote Docker hosts."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.3.0"