codeforge-dev 1.4.0
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.
- package/.devcontainer/.env +22 -0
- package/.devcontainer/CHANGELOG.md +197 -0
- package/.devcontainer/CLAUDE.md +117 -0
- package/.devcontainer/README.md +222 -0
- package/.devcontainer/config/main-system-prompt.md +502 -0
- package/.devcontainer/config/settings.json +47 -0
- package/.devcontainer/devcontainer.json +94 -0
- package/.devcontainer/features/README.md +113 -0
- package/.devcontainer/features/agent-browser/README.md +65 -0
- package/.devcontainer/features/agent-browser/devcontainer-feature.json +23 -0
- package/.devcontainer/features/agent-browser/install.sh +79 -0
- package/.devcontainer/features/ast-grep/README.md +24 -0
- package/.devcontainer/features/ast-grep/devcontainer-feature.json +24 -0
- package/.devcontainer/features/ast-grep/install.sh +51 -0
- package/.devcontainer/features/ccstatusline/README.md +296 -0
- package/.devcontainer/features/ccstatusline/devcontainer-feature.json +19 -0
- package/.devcontainer/features/ccstatusline/install.sh +290 -0
- package/.devcontainer/features/ccusage/README.md +205 -0
- package/.devcontainer/features/ccusage/devcontainer-feature.json +38 -0
- package/.devcontainer/features/ccusage/install.sh +132 -0
- package/.devcontainer/features/claude-code/README.md +498 -0
- package/.devcontainer/features/claude-code/config/settings.json +36 -0
- package/.devcontainer/features/claude-code/config/system-prompt.md +118 -0
- package/.devcontainer/features/claude-code/config/world-building-sp.md +1432 -0
- package/.devcontainer/features/claude-code/devcontainer-feature.json +42 -0
- package/.devcontainer/features/claude-code/install.sh +466 -0
- package/.devcontainer/features/claude-monitor/README.md +74 -0
- package/.devcontainer/features/claude-monitor/devcontainer-feature.json +38 -0
- package/.devcontainer/features/claude-monitor/install.sh +99 -0
- package/.devcontainer/features/lsp-servers/README.md +85 -0
- package/.devcontainer/features/lsp-servers/devcontainer-feature.json +40 -0
- package/.devcontainer/features/lsp-servers/install.sh +116 -0
- package/.devcontainer/features/mcp-qdrant/CHANGES.md +399 -0
- package/.devcontainer/features/mcp-qdrant/README.md +474 -0
- package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +57 -0
- package/.devcontainer/features/mcp-qdrant/install.sh +295 -0
- package/.devcontainer/features/mcp-qdrant/poststart-hook.sh +129 -0
- package/.devcontainer/features/mcp-reasoner/README.md +177 -0
- package/.devcontainer/features/mcp-reasoner/devcontainer-feature.json +20 -0
- package/.devcontainer/features/mcp-reasoner/install.sh +177 -0
- package/.devcontainer/features/mcp-reasoner/poststart-hook.sh +67 -0
- package/.devcontainer/features/notify-hook/README.md +86 -0
- package/.devcontainer/features/notify-hook/devcontainer-feature.json +23 -0
- package/.devcontainer/features/notify-hook/install.sh +38 -0
- package/.devcontainer/features/splitrail/README.md +140 -0
- package/.devcontainer/features/splitrail/devcontainer-feature.json +34 -0
- package/.devcontainer/features/splitrail/install.sh +129 -0
- package/.devcontainer/features/tree-sitter/README.md +138 -0
- package/.devcontainer/features/tree-sitter/devcontainer-feature.json +52 -0
- package/.devcontainer/features/tree-sitter/install.sh +173 -0
- package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +106 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-file.py +101 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/lint-file.py +137 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/.claude-plugin/plugin.json +8 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/SKILL.md +387 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/references/cli-flags-and-output.md +312 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/references/sdk-and-mcp.md +569 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/SKILL.md +309 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/references/compose-services.md +438 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/references/dockerfile-patterns.md +340 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/SKILL.md +412 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/references/container-lifecycle.md +388 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/references/resources-and-security.md +444 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/SKILL.md +344 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/middleware-and-lifespan.md +254 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/pydantic-models.md +245 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/routing-and-dependencies.md +255 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/sse-and-streaming.md +318 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/SKILL.md +345 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/references/agents-and-tools.md +271 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/references/models-and-streaming.md +422 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/SKILL.md +220 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/cross-vendor-principles.md +139 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/patterns-and-antipatterns.md +376 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/skill-authoring-patterns.md +356 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/SKILL.md +329 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/advanced-queries.md +314 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/javascript-patterns.md +323 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/python-patterns.md +354 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/schema-and-pragmas.md +326 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/SKILL.md +356 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/ai-sdk-svelte.md +128 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/component-patterns.md +332 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/layercake.md +203 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/migration-guide.md +350 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/runes-and-reactivity.md +328 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/spa-and-routing.md +262 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/svelte-dnd-action.md +181 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/SKILL.md +414 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/references/fastapi-testing.md +411 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/references/svelte-testing.md +538 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codeforge-lsp/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/block-dangerous.py +110 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected.py +108 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272create-pr.md +337 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272new.md +166 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272review-commit.md +290 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272work.md +257 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/plugin.json +8 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/system-prompt.md +184 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/.claude-plugin/plugin.json +6 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/config/planning-instructions.md +14 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/functional-conjuring-map.md +989 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/hooks/hooks.json +33 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/__pycache__/post-enhance-task.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhance-planning.py +71 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-plan.sh +68 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-task.sh +120 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-plan.py +133 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-task.py +253 -0
- package/.devcontainer/scripts/setup-aliases.sh +80 -0
- package/.devcontainer/scripts/setup-config.sh +28 -0
- package/.devcontainer/scripts/setup-irie-claude.sh +32 -0
- package/.devcontainer/scripts/setup-plugins.sh +80 -0
- package/.devcontainer/scripts/setup.sh +58 -0
- package/LICENSE.txt +674 -0
- package/README.md +267 -0
- package/package.json +44 -0
- package/setup.js +83 -0
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
# Resources and Security -- Deep Dive
|
|
2
|
+
|
|
3
|
+
## 1. Volume Management
|
|
4
|
+
|
|
5
|
+
### CRUD Operations
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
# Create
|
|
9
|
+
volume = client.volumes.create(
|
|
10
|
+
name="app-data",
|
|
11
|
+
driver="local",
|
|
12
|
+
driver_opts={"type": "tmpfs", "device": "tmpfs", "o": "size=100m"},
|
|
13
|
+
labels={"env": "production"},
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# List
|
|
17
|
+
volumes = client.volumes.list()
|
|
18
|
+
volumes = client.volumes.list(filters={"label": "env=production"})
|
|
19
|
+
|
|
20
|
+
# Get by name
|
|
21
|
+
volume = client.volumes.get("app-data")
|
|
22
|
+
print(volume.name)
|
|
23
|
+
print(volume.attrs)
|
|
24
|
+
|
|
25
|
+
# Remove
|
|
26
|
+
volume.remove(force=False)
|
|
27
|
+
|
|
28
|
+
# Prune unused
|
|
29
|
+
result = client.volumes.prune(filters={"label": "env=staging"})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Using Volumes with Containers
|
|
33
|
+
|
|
34
|
+
**Dict syntax:**
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
container = client.containers.run(
|
|
38
|
+
"postgres:16",
|
|
39
|
+
detach=True,
|
|
40
|
+
volumes={
|
|
41
|
+
"pgdata": {"bind": "/var/lib/postgresql/data", "mode": "rw"},
|
|
42
|
+
"/host/backups": {"bind": "/backups", "mode": "ro"},
|
|
43
|
+
},
|
|
44
|
+
)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Mount objects (preferred):**
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from docker.types import Mount
|
|
51
|
+
|
|
52
|
+
container = client.containers.run(
|
|
53
|
+
"postgres:16",
|
|
54
|
+
detach=True,
|
|
55
|
+
mounts=[
|
|
56
|
+
Mount(target="/var/lib/postgresql/data", source="pgdata", type="volume"),
|
|
57
|
+
Mount(target="/backups", source="/host/backups", type="bind", read_only=True),
|
|
58
|
+
Mount(target="/tmp", type="tmpfs", tmpfs_size=100 * 1024 * 1024),
|
|
59
|
+
],
|
|
60
|
+
)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Mount types: `"volume"` (managed by Docker), `"bind"` (host path), `"tmpfs"` (memory-backed).
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 2. Bind Mount Patterns
|
|
68
|
+
|
|
69
|
+
### Read-Only Configuration
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from docker.types import Mount
|
|
73
|
+
|
|
74
|
+
mounts = [
|
|
75
|
+
Mount(target="/app/config", source="/etc/myapp", type="bind", read_only=True),
|
|
76
|
+
]
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Writable Data Directory
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
mounts = [
|
|
83
|
+
Mount(target="/app/data", source="/var/lib/myapp", type="bind", read_only=False),
|
|
84
|
+
]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Bind Mount Security Considerations
|
|
88
|
+
|
|
89
|
+
- Bind mounts expose host filesystem paths directly to the container.
|
|
90
|
+
- A writable bind mount to a sensitive host path (e.g., `/`, `/etc`, `/var/run/docker.sock`) grants significant host access.
|
|
91
|
+
- Prefer named volumes for application data. Use bind mounts only for configuration injection or development workflows.
|
|
92
|
+
- Mount the Docker socket (`/var/run/docker.sock`) only when container management is an explicit requirement, and combine with read-only root filesystem and dropped capabilities.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 3. Network Operations
|
|
97
|
+
|
|
98
|
+
### Create Networks
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
# Basic bridge network
|
|
102
|
+
network = client.networks.create("app-net", driver="bridge")
|
|
103
|
+
|
|
104
|
+
# With IPAM configuration
|
|
105
|
+
import docker.types
|
|
106
|
+
ipam_pool = docker.types.IPAMPool(subnet="192.168.52.0/24", gateway="192.168.52.254")
|
|
107
|
+
ipam_config = docker.types.IPAMConfig(pool_configs=[ipam_pool])
|
|
108
|
+
|
|
109
|
+
network = client.networks.create(
|
|
110
|
+
"app-net",
|
|
111
|
+
driver="bridge",
|
|
112
|
+
ipam=ipam_config,
|
|
113
|
+
internal=False,
|
|
114
|
+
attachable=True,
|
|
115
|
+
labels={"env": "dev"},
|
|
116
|
+
)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Connect and Disconnect
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
# Connect with aliases (DNS names within the network)
|
|
123
|
+
network.connect(container, aliases=["web-app", "frontend"])
|
|
124
|
+
|
|
125
|
+
# Connect with static IP
|
|
126
|
+
network.connect(container, ipv4_address="192.168.52.10")
|
|
127
|
+
|
|
128
|
+
# Disconnect
|
|
129
|
+
network.disconnect(container, force=False)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Inspect Connected Containers
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
network.reload()
|
|
136
|
+
for c in network.containers:
|
|
137
|
+
print(f"{c.name}: {c.status}")
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Remove and Prune
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
network.remove()
|
|
144
|
+
client.networks.prune(filters={"until": "24h"})
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 4. Resource Limits
|
|
150
|
+
|
|
151
|
+
### Memory
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
container = client.containers.run(
|
|
155
|
+
"myapp",
|
|
156
|
+
detach=True,
|
|
157
|
+
mem_limit="512m", # hard limit: "100000b", "1000k", "128m", "1g"
|
|
158
|
+
mem_reservation="256m", # soft limit
|
|
159
|
+
memswap_limit="1g", # memory + swap combined
|
|
160
|
+
oom_kill_disable=False, # keep OOM killer enabled
|
|
161
|
+
)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### CPU
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
container = client.containers.run(
|
|
168
|
+
"myapp",
|
|
169
|
+
detach=True,
|
|
170
|
+
nano_cpus=500_000_000, # 0.5 CPU (units: 1e-9 CPUs)
|
|
171
|
+
cpuset_cpus="0-3", # pin to specific CPUs
|
|
172
|
+
cpu_shares=1024, # relative weight (default 1024)
|
|
173
|
+
)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Alternative CPU limit via CFS quota:
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
container = client.containers.run(
|
|
180
|
+
"myapp",
|
|
181
|
+
detach=True,
|
|
182
|
+
cpu_period=100000, # CFS period in microseconds
|
|
183
|
+
cpu_quota=50000, # 50% of one CPU
|
|
184
|
+
)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Block I/O
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
container = client.containers.run(
|
|
191
|
+
"myapp",
|
|
192
|
+
detach=True,
|
|
193
|
+
blkio_weight=500,
|
|
194
|
+
device_read_bps=[{"Path": "/dev/sda", "Rate": 1048576}], # 1 MB/s
|
|
195
|
+
device_write_bps=[{"Path": "/dev/sda", "Rate": 1048576}],
|
|
196
|
+
)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### PID Limit
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
container = client.containers.run("myapp", detach=True, pids_limit=100)
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Runtime Updates
|
|
206
|
+
|
|
207
|
+
Update resource limits on a running container:
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
container.update(
|
|
211
|
+
mem_limit="1g",
|
|
212
|
+
cpu_shares=2048,
|
|
213
|
+
restart_policy={"Name": "on-failure", "MaximumRetryCount": 5},
|
|
214
|
+
)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 5. Security Options
|
|
220
|
+
|
|
221
|
+
### Capabilities
|
|
222
|
+
|
|
223
|
+
Drop all capabilities and add only what is needed:
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
container = client.containers.run(
|
|
227
|
+
"myapp",
|
|
228
|
+
detach=True,
|
|
229
|
+
cap_drop=["ALL"],
|
|
230
|
+
cap_add=["NET_BIND_SERVICE"], # bind to ports < 1024
|
|
231
|
+
)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Common capabilities:
|
|
235
|
+
- `NET_ADMIN`: network configuration
|
|
236
|
+
- `SYS_PTRACE`: debugging, strace
|
|
237
|
+
- `NET_BIND_SERVICE`: bind to privileged ports
|
|
238
|
+
- `DAC_OVERRIDE`: bypass file permission checks
|
|
239
|
+
|
|
240
|
+
### Read-Only Root Filesystem
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
container = client.containers.run(
|
|
244
|
+
"myapp",
|
|
245
|
+
detach=True,
|
|
246
|
+
read_only=True,
|
|
247
|
+
tmpfs={"/tmp": "size=100m", "/run": "size=10m"},
|
|
248
|
+
)
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Combine `read_only=True` with `tmpfs` for directories that need write access. This prevents runtime modification of application code.
|
|
252
|
+
|
|
253
|
+
### Security Labels and Options
|
|
254
|
+
|
|
255
|
+
```python
|
|
256
|
+
container = client.containers.run(
|
|
257
|
+
"myapp",
|
|
258
|
+
detach=True,
|
|
259
|
+
security_opt=[
|
|
260
|
+
"no-new-privileges", # prevent privilege escalation
|
|
261
|
+
"label:type:svirt_apache_t", # SELinux label
|
|
262
|
+
],
|
|
263
|
+
)
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Namespace Isolation
|
|
267
|
+
|
|
268
|
+
```python
|
|
269
|
+
container = client.containers.run(
|
|
270
|
+
"myapp",
|
|
271
|
+
detach=True,
|
|
272
|
+
ipc_mode="private", # isolate IPC namespace
|
|
273
|
+
pid_mode="container:other", # share PID namespace with another container
|
|
274
|
+
network_mode="none", # no network access
|
|
275
|
+
userns_mode="host", # share host user namespace
|
|
276
|
+
)
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Non-Root User
|
|
280
|
+
|
|
281
|
+
```python
|
|
282
|
+
container = client.containers.run(
|
|
283
|
+
"myapp",
|
|
284
|
+
detach=True,
|
|
285
|
+
user="1000:1000", # UID:GID
|
|
286
|
+
)
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### GPU Access
|
|
290
|
+
|
|
291
|
+
```python
|
|
292
|
+
import docker.types
|
|
293
|
+
|
|
294
|
+
container = client.containers.run(
|
|
295
|
+
"nvidia/cuda:12.0-runtime",
|
|
296
|
+
detach=True,
|
|
297
|
+
device_requests=[
|
|
298
|
+
docker.types.DeviceRequest(count=-1, capabilities=[["gpu"]]), # all GPUs
|
|
299
|
+
],
|
|
300
|
+
)
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## 6. Image Management
|
|
306
|
+
|
|
307
|
+
### Pull
|
|
308
|
+
|
|
309
|
+
```python
|
|
310
|
+
image = client.images.pull("python", tag="3.12-slim")
|
|
311
|
+
|
|
312
|
+
# With authentication
|
|
313
|
+
image = client.images.pull(
|
|
314
|
+
"registry.example.com/private/app",
|
|
315
|
+
auth_config={"username": "user", "password": "token"},
|
|
316
|
+
)
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Build
|
|
320
|
+
|
|
321
|
+
```python
|
|
322
|
+
image, build_logs = client.images.build(
|
|
323
|
+
path="/path/to/context",
|
|
324
|
+
tag="myapp:latest",
|
|
325
|
+
nocache=False,
|
|
326
|
+
buildargs={"VERSION": "1.0", "ENV": "production"},
|
|
327
|
+
target="production", # multi-stage target
|
|
328
|
+
platform="linux/amd64",
|
|
329
|
+
rm=True, # remove intermediate containers
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
for log_line in build_logs:
|
|
333
|
+
if "stream" in log_line:
|
|
334
|
+
print(log_line["stream"], end="")
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Tag and Push
|
|
338
|
+
|
|
339
|
+
```python
|
|
340
|
+
image = client.images.get("myapp:latest")
|
|
341
|
+
image.tag("registry.example.com/myapp", tag="v1.0")
|
|
342
|
+
client.images.push("registry.example.com/myapp", tag="v1.0")
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Save and Load
|
|
346
|
+
|
|
347
|
+
```python
|
|
348
|
+
# Export to tarball
|
|
349
|
+
image = client.images.get("myapp:latest")
|
|
350
|
+
with open("/tmp/myapp.tar", "wb") as f:
|
|
351
|
+
for chunk in image.save(named=True):
|
|
352
|
+
f.write(chunk)
|
|
353
|
+
|
|
354
|
+
# Import from tarball
|
|
355
|
+
with open("/tmp/myapp.tar", "rb") as f:
|
|
356
|
+
images = client.images.load(f.read())
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
## 7. Error Handling Reference
|
|
362
|
+
|
|
363
|
+
```python
|
|
364
|
+
from docker.errors import (
|
|
365
|
+
ContainerError, # non-zero exit code (detach=False)
|
|
366
|
+
ImageNotFound, # image does not exist
|
|
367
|
+
NotFound, # container/resource not found
|
|
368
|
+
APIError, # general Docker daemon error
|
|
369
|
+
BuildError, # image build failure
|
|
370
|
+
)
|
|
371
|
+
from requests.exceptions import ReadTimeout, ConnectionError
|
|
372
|
+
|
|
373
|
+
try:
|
|
374
|
+
container = client.containers.run("myapp", detach=True)
|
|
375
|
+
container.wait(timeout=60)
|
|
376
|
+
except ImageNotFound:
|
|
377
|
+
# Image needs to be pulled or built
|
|
378
|
+
client.images.pull("myapp", tag="latest")
|
|
379
|
+
except NotFound:
|
|
380
|
+
# Container was removed (e.g., auto-remove)
|
|
381
|
+
pass
|
|
382
|
+
except ContainerError as e:
|
|
383
|
+
print(f"Exit code: {e.exit_status}")
|
|
384
|
+
print(f"Output: {e.stderr.decode()}")
|
|
385
|
+
except ReadTimeout:
|
|
386
|
+
# wait() timed out
|
|
387
|
+
container.stop(timeout=5)
|
|
388
|
+
except APIError as e:
|
|
389
|
+
print(f"Docker API error: {e.status_code} {e.explanation}")
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## 8. aiodocker -- Async Alternative
|
|
395
|
+
|
|
396
|
+
For asyncio applications, `aiodocker` provides native async/await support:
|
|
397
|
+
|
|
398
|
+
```python
|
|
399
|
+
import aiodocker
|
|
400
|
+
|
|
401
|
+
async def run_container():
|
|
402
|
+
docker = aiodocker.Docker()
|
|
403
|
+
try:
|
|
404
|
+
container = await docker.containers.create_or_replace(
|
|
405
|
+
config={
|
|
406
|
+
"Cmd": ["python", "-c", "print('hello')"],
|
|
407
|
+
"Image": "python:3.12-slim",
|
|
408
|
+
},
|
|
409
|
+
name="async-worker",
|
|
410
|
+
)
|
|
411
|
+
await container.start()
|
|
412
|
+
|
|
413
|
+
# Stream logs
|
|
414
|
+
async for line in container.log(stdout=True, follow=True):
|
|
415
|
+
print(line)
|
|
416
|
+
|
|
417
|
+
await container.wait()
|
|
418
|
+
await container.delete(force=True)
|
|
419
|
+
finally:
|
|
420
|
+
await docker.close()
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Key Differences from docker-py
|
|
424
|
+
|
|
425
|
+
| Aspect | docker-py | aiodocker |
|
|
426
|
+
|--------|-----------|-----------|
|
|
427
|
+
| Style | Synchronous (blocking) | Asyncio-native |
|
|
428
|
+
| Config format | Keyword arguments | Raw Docker Engine API dicts |
|
|
429
|
+
| Client cleanup | Implicit | Explicit `await docker.close()` |
|
|
430
|
+
| Method names | `run()`, `remove()`, `logs()` | `create_or_replace()`, `delete()`, `log()` |
|
|
431
|
+
| Streaming | Thread-blocking generators | Async iterators |
|
|
432
|
+
|
|
433
|
+
### When to Use aiodocker
|
|
434
|
+
|
|
435
|
+
- The application already runs an asyncio event loop (FastAPI, aiohttp).
|
|
436
|
+
- Container operations happen alongside other async I/O (database queries, HTTP requests).
|
|
437
|
+
- Log streaming needs to be non-blocking.
|
|
438
|
+
|
|
439
|
+
### When to Use docker-py
|
|
440
|
+
|
|
441
|
+
- Scripts and CLI tools.
|
|
442
|
+
- Synchronous applications.
|
|
443
|
+
- The official `docker` library is needed for compatibility.
|
|
444
|
+
- Higher-level convenience methods (`run()`, `exec_run()`) are preferred over raw API dicts.
|