0
# Error Handling
1
2
Comprehensive exception hierarchy for robust error handling and debugging with specific exceptions for different failure scenarios.
3
4
## Capabilities
5
6
### Base Exception
7
8
```python { .api }
9
class DockerException(Exception):
10
"""
11
Base class for all Docker SDK exceptions.
12
13
If you want to catch all errors that the Docker SDK might raise,
14
catch this base exception.
15
"""
16
```
17
18
### API Exceptions
19
20
```python { .api }
21
class APIError(requests.exceptions.HTTPError, DockerException):
22
"""
23
An HTTP error from the Docker API.
24
25
Attributes:
26
response: The HTTP response object
27
explanation: Detailed error explanation from Docker API
28
"""
29
30
class NotFound(APIError):
31
"""
32
Exception raised when a resource is not found (HTTP 404).
33
34
Raised by methods like get() when attempting to retrieve
35
non-existent containers, images, networks, etc.
36
"""
37
38
class ImageNotFound(NotFound):
39
"""
40
Exception raised when a Docker image is not found.
41
42
Specialized NotFound exception for image-related operations.
43
"""
44
```
45
46
### Configuration Exceptions
47
48
```python { .api }
49
class InvalidVersion(DockerException):
50
"""
51
Exception raised when an invalid API version is specified.
52
"""
53
54
class InvalidRepository(DockerException):
55
"""
56
Exception raised when an invalid repository name is provided.
57
"""
58
59
class InvalidConfigFile(DockerException):
60
"""
61
Exception raised when Docker configuration file is invalid.
62
"""
63
64
class InvalidArgument(DockerException):
65
"""
66
Exception raised when invalid arguments are provided to API methods.
67
"""
68
69
class TLSParameterError(DockerException):
70
"""
71
Exception raised when TLS configuration parameters are invalid.
72
"""
73
```
74
75
### Operation Exceptions
76
77
```python { .api }
78
class ContainerError(DockerException):
79
"""
80
Exception raised when a container exits with a non-zero status code.
81
82
Attributes:
83
container: The container that failed
84
exit_status: The exit status code
85
command: The command that was executed
86
image: The image used
87
stderr: Standard error output
88
"""
89
90
class BuildError(DockerException):
91
"""
92
Exception raised when a Docker image build fails.
93
94
Attributes:
95
msg: Error message
96
build_log: Build log output
97
"""
98
99
class ImageLoadError(DockerException):
100
"""
101
Exception raised when image loading from tar archive fails.
102
"""
103
104
class StreamParseError(RuntimeError):
105
"""
106
Exception raised when parsing streaming API responses fails.
107
"""
108
109
class NullResource(DockerException, ValueError):
110
"""
111
Exception raised when attempting to perform operations on null resources.
112
"""
113
114
class DeprecatedMethod(DockerException):
115
"""
116
Exception raised when deprecated methods are used.
117
"""
118
```
119
120
### Context Exceptions
121
122
```python { .api }
123
class MissingContextParameter(DockerException):
124
"""
125
Exception raised when required context parameters are missing.
126
"""
127
128
class ContextAlreadyExists(DockerException):
129
"""
130
Exception raised when attempting to create a context that already exists.
131
"""
132
133
class ContextException(DockerException):
134
"""
135
General exception for Docker context operations.
136
"""
137
138
class ContextNotFound(DockerException):
139
"""
140
Exception raised when a Docker context is not found.
141
"""
142
```
143
144
## Usage Examples
145
146
### Basic Error Handling
147
148
```python
149
import docker
150
from docker.errors import APIError, NotFound, ContainerError
151
152
client = docker.from_env()
153
154
# Handle container not found
155
try:
156
container = client.containers.get('nonexistent-container')
157
except NotFound:
158
print("Container not found")
159
except APIError as e:
160
print(f"API Error: {e.explanation}")
161
162
# Handle image not found
163
try:
164
image = client.images.get('nonexistent:image')
165
except docker.errors.ImageNotFound:
166
print("Image not found")
167
# Attempt to pull the image
168
try:
169
image = client.images.pull('nonexistent:image')
170
except APIError as e:
171
print(f"Failed to pull image: {e.explanation}")
172
```
173
174
### Container Operation Error Handling
175
176
```python
177
# Handle container execution errors
178
try:
179
container = client.containers.run(
180
'ubuntu:20.04',
181
'exit 1', # Command that will fail
182
remove=True
183
)
184
except ContainerError as e:
185
print(f"Container failed with exit code: {e.exit_status}")
186
print(f"Command: {e.command}")
187
print(f"Stderr: {e.stderr}")
188
189
# Handle container lifecycle errors
190
try:
191
container = client.containers.get('my-container')
192
container.start()
193
except NotFound:
194
print("Container not found")
195
except APIError as e:
196
if e.response.status_code == 409:
197
print("Container is already started")
198
else:
199
print(f"Failed to start container: {e.explanation}")
200
```
201
202
### Build Error Handling
203
204
```python
205
# Handle build failures
206
try:
207
image, build_logs = client.images.build(
208
path='/path/to/invalid/dockerfile',
209
tag='my-app:latest'
210
)
211
212
# Process build logs
213
for log in build_logs:
214
if 'stream' in log:
215
print(log['stream'].strip())
216
217
except BuildError as e:
218
print(f"Build failed: {e.msg}")
219
if hasattr(e, 'build_log'):
220
print("Build log:")
221
for log_entry in e.build_log:
222
print(log_entry)
223
except APIError as e:
224
print(f"API error during build: {e.explanation}")
225
```
226
227
### Network and Volume Error Handling
228
229
```python
230
# Handle network operations
231
try:
232
network = client.networks.create('my-network')
233
234
# Connect container to network
235
container = client.containers.get('my-container')
236
network.connect(container)
237
238
except APIError as e:
239
if 'already exists' in e.explanation.lower():
240
print("Network already exists")
241
network = client.networks.get('my-network')
242
else:
243
print(f"Network operation failed: {e.explanation}")
244
245
# Handle volume operations
246
try:
247
volume = client.volumes.create(name='my-data')
248
except APIError as e:
249
if e.response.status_code == 409:
250
print("Volume already exists")
251
volume = client.volumes.get('my-data')
252
else:
253
print(f"Volume creation failed: {e.explanation}")
254
```
255
256
### Comprehensive Error Handling
257
258
```python
259
import docker
260
from docker.errors import DockerException
261
import logging
262
263
# Set up logging
264
logging.basicConfig(level=logging.INFO)
265
logger = logging.getLogger(__name__)
266
267
def safe_docker_operation(operation_func, *args, **kwargs):
268
"""
269
Wrapper for safe Docker operations with comprehensive error handling.
270
"""
271
try:
272
return operation_func(*args, **kwargs)
273
274
except ContainerError as e:
275
logger.error(f"Container operation failed: {e.exit_status}")
276
logger.error(f"Command: {e.command}")
277
if e.stderr:
278
logger.error(f"Error output: {e.stderr.decode()}")
279
raise
280
281
except ImageNotFound as e:
282
logger.error(f"Image not found: {e}")
283
raise
284
285
except NotFound as e:
286
logger.error(f"Resource not found: {e}")
287
raise
288
289
except BuildError as e:
290
logger.error(f"Build failed: {e.msg}")
291
raise
292
293
except TLSParameterError as e:
294
logger.error(f"TLS configuration error: {e}")
295
raise
296
297
except InvalidArgument as e:
298
logger.error(f"Invalid argument: {e}")
299
raise
300
301
except APIError as e:
302
logger.error(f"Docker API error ({e.response.status_code}): {e.explanation}")
303
raise
304
305
except DockerException as e:
306
logger.error(f"Docker SDK error: {e}")
307
raise
308
309
except Exception as e:
310
logger.error(f"Unexpected error: {e}")
311
raise
312
313
# Usage example
314
client = docker.from_env()
315
316
# Safe container operations
317
try:
318
container = safe_docker_operation(
319
client.containers.run,
320
'nginx:latest',
321
detach=True,
322
name='web-server',
323
ports={'80/tcp': 8080}
324
)
325
logger.info(f"Container created: {container.id}")
326
327
except DockerException:
328
logger.error("Failed to create container")
329
```
330
331
### Error Recovery Patterns
332
333
```python
334
import time
335
import docker
336
from docker.errors import APIError, NotFound
337
338
def retry_operation(func, max_retries=3, delay=1, *args, **kwargs):
339
"""
340
Retry Docker operations with exponential backoff.
341
"""
342
for attempt in range(max_retries):
343
try:
344
return func(*args, **kwargs)
345
except APIError as e:
346
if attempt == max_retries - 1:
347
raise
348
if e.response.status_code >= 500: # Server errors
349
print(f"Attempt {attempt + 1} failed, retrying in {delay}s...")
350
time.sleep(delay)
351
delay *= 2
352
else:
353
raise # Don't retry client errors
354
355
def ensure_container_running(client, container_name, image_name):
356
"""
357
Ensure a container is running, create if necessary.
358
"""
359
try:
360
container = client.containers.get(container_name)
361
if container.status != 'running':
362
container.start()
363
return container
364
except NotFound:
365
print(f"Container {container_name} not found, creating...")
366
return client.containers.run(
367
image_name,
368
detach=True,
369
name=container_name
370
)
371
372
# Usage
373
client = docker.from_env()
374
375
try:
376
# Retry image pull with backoff
377
image = retry_operation(
378
client.images.pull,
379
max_retries=3,
380
repository='nginx:latest'
381
)
382
383
# Ensure container is running
384
container = ensure_container_running(
385
client,
386
'my-nginx',
387
'nginx:latest'
388
)
389
390
except DockerException as e:
391
print(f"Operation failed after retries: {e}")
392
```