pywhales 0.2.1__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.
- pywhales-0.2.1/LICENSE +21 -0
- pywhales-0.2.1/MANIFEST.in +3 -0
- pywhales-0.2.1/PKG-INFO +206 -0
- pywhales-0.2.1/README.md +189 -0
- pywhales-0.2.1/docs/requirements.txt +11 -0
- pywhales-0.2.1/docs/template/docker_client.md +116 -0
- pywhales-0.2.1/docs/template/index.md +1 -0
- pywhales-0.2.1/docs/template/objects/builders.md +41 -0
- pywhales-0.2.1/docs/template/objects/configs.md +51 -0
- pywhales-0.2.1/docs/template/objects/containers.md +48 -0
- pywhales-0.2.1/docs/template/objects/images.md +56 -0
- pywhales-0.2.1/docs/template/objects/networks.md +50 -0
- pywhales-0.2.1/docs/template/objects/nodes.md +51 -0
- pywhales-0.2.1/docs/template/objects/plugins.md +50 -0
- pywhales-0.2.1/docs/template/objects/services.md +51 -0
- pywhales-0.2.1/docs/template/objects/tasks.md +31 -0
- pywhales-0.2.1/docs/template/objects/volumes.md +56 -0
- pywhales-0.2.1/docs/template/sub-commands/buildx.md +47 -0
- pywhales-0.2.1/docs/template/sub-commands/compose.md +84 -0
- pywhales-0.2.1/docs/template/sub-commands/context.md +40 -0
- pywhales-0.2.1/docs/template/user_guide/build_performance.md +374 -0
- pywhales-0.2.1/docs/template/user_guide/docker_run.md +105 -0
- pywhales-0.2.1/docs/template/user_guide/exceptions.md +35 -0
- pywhales-0.2.1/docs/template/user_guide/generic_resources.md +176 -0
- pywhales-0.2.1/docs/template/user_guide/running_pydocker_inside_a_container.md +107 -0
- pywhales-0.2.1/pyproject.toml +99 -0
- pywhales-0.2.1/pywhales/__init__.py +48 -0
- pywhales-0.2.1/pywhales/client_config.py +325 -0
- pywhales-0.2.1/pywhales/command_line_entrypoint.py +8 -0
- pywhales-0.2.1/pywhales/components/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/_swarm_inspect.py +78 -0
- pywhales-0.2.1/pywhales/components/buildx/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/buildx/cli_wrapper.py +1123 -0
- pywhales-0.2.1/pywhales/components/buildx/imagetools/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/buildx/imagetools/cli_wrapper.py +117 -0
- pywhales-0.2.1/pywhales/components/buildx/imagetools/models.py +40 -0
- pywhales-0.2.1/pywhales/components/buildx/models.py +27 -0
- pywhales-0.2.1/pywhales/components/compose/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/compose/cli_wrapper.py +1534 -0
- pywhales-0.2.1/pywhales/components/compose/models.py +147 -0
- pywhales-0.2.1/pywhales/components/config/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/config/cli_wrapper.py +186 -0
- pywhales-0.2.1/pywhales/components/config/models.py +30 -0
- pywhales-0.2.1/pywhales/components/container/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/container/cli_wrapper.py +2533 -0
- pywhales-0.2.1/pywhales/components/container/models.py +312 -0
- pywhales-0.2.1/pywhales/components/container/top.py +85 -0
- pywhales-0.2.1/pywhales/components/context/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/context/cli_wrapper.py +249 -0
- pywhales-0.2.1/pywhales/components/context/models.py +27 -0
- pywhales-0.2.1/pywhales/components/image/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/image/cli_wrapper.py +1058 -0
- pywhales-0.2.1/pywhales/components/image/models.py +47 -0
- pywhales-0.2.1/pywhales/components/image/streams.py +149 -0
- pywhales-0.2.1/pywhales/components/manifest/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/manifest/cli_wrapper.py +180 -0
- pywhales-0.2.1/pywhales/components/manifest/models.py +9 -0
- pywhales-0.2.1/pywhales/components/network/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/network/cli_wrapper.py +365 -0
- pywhales-0.2.1/pywhales/components/network/models.py +36 -0
- pywhales-0.2.1/pywhales/components/node/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/node/cli_wrapper.py +274 -0
- pywhales-0.2.1/pywhales/components/node/models.py +91 -0
- pywhales-0.2.1/pywhales/components/plugin/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/plugin/cli_wrapper.py +308 -0
- pywhales-0.2.1/pywhales/components/plugin/models.py +39 -0
- pywhales-0.2.1/pywhales/components/secret/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/secret/cli_wrapper.py +176 -0
- pywhales-0.2.1/pywhales/components/secret/models.py +19 -0
- pywhales-0.2.1/pywhales/components/service/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/service/cli_wrapper.py +617 -0
- pywhales-0.2.1/pywhales/components/service/models.py +93 -0
- pywhales-0.2.1/pywhales/components/stack/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/stack/cli_wrapper.py +170 -0
- pywhales-0.2.1/pywhales/components/swarm/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/swarm/cli_wrapper.py +229 -0
- pywhales-0.2.1/pywhales/components/system/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/system/cli_wrapper.py +192 -0
- pywhales-0.2.1/pywhales/components/system/models.py +214 -0
- pywhales-0.2.1/pywhales/components/task/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/task/cli_wrapper.py +117 -0
- pywhales-0.2.1/pywhales/components/task/models.py +158 -0
- pywhales-0.2.1/pywhales/components/top.py +172 -0
- pywhales-0.2.1/pywhales/components/trust/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/trust/cli_wrapper.py +22 -0
- pywhales-0.2.1/pywhales/components/volume/__init__.py +0 -0
- pywhales-0.2.1/pywhales/components/volume/cli_wrapper.py +393 -0
- pywhales-0.2.1/pywhales/components/volume/models.py +16 -0
- pywhales-0.2.1/pywhales/docker_client.py +391 -0
- pywhales-0.2.1/pywhales/exceptions.py +62 -0
- pywhales-0.2.1/pywhales/py.typed +1 -0
- pywhales-0.2.1/pywhales/test_utils.py +25 -0
- pywhales-0.2.1/pywhales/utils.py +541 -0
- pywhales-0.2.1/pywhales.egg-info/PKG-INFO +206 -0
- pywhales-0.2.1/pywhales.egg-info/SOURCES.txt +105 -0
- pywhales-0.2.1/pywhales.egg-info/dependency_links.txt +1 -0
- pywhales-0.2.1/pywhales.egg-info/entry_points.txt +2 -0
- pywhales-0.2.1/pywhales.egg-info/requires.txt +4 -0
- pywhales-0.2.1/pywhales.egg-info/top_level.txt +1 -0
- pywhales-0.2.1/scripts/docker-plugin-checksums.txt +3 -0
- pywhales-0.2.1/setup.cfg +4 -0
- pywhales-0.2.1/skills/pywhales/SKILL.md +61 -0
- pywhales-0.2.1/skills/pywhales/references/buildx.md +86 -0
- pywhales-0.2.1/skills/pywhales/references/client-and-errors.md +82 -0
- pywhales-0.2.1/skills/pywhales/references/compose.md +100 -0
- pywhales-0.2.1/skills/pywhales/references/containers-and-output.md +85 -0
- pywhales-0.2.1/skills/pywhales/references/validation.md +50 -0
pywhales-0.2.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 Gabriel de Marmiesse de Lussan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pywhales-0.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pywhales
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: A Docker client for Python, designed to be fun and intuitive!
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Source, https://github.com/MaraClaw/PyWhales
|
|
7
|
+
Project-URL: Documentation, https://github.com/MaraClaw/PyWhales
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/MaraClaw/PyWhales/issues
|
|
9
|
+
Requires-Python: >=3.14.8
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: pydantic>=2.14.1
|
|
13
|
+
Requires-Dist: typing_extensions>=4.16.0
|
|
14
|
+
Requires-Dist: boto3>=1.43.118
|
|
15
|
+
Requires-Dist: s3transfer>=0.19.3
|
|
16
|
+
Dynamic: license-file
|
|
17
|
+
|
|
18
|
+
# PyWhales
|
|
19
|
+
|
|
20
|
+
------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
[](https://github.com/MaraClaw/PyWhales/actions/workflows/python-package.yml)
|
|
23
|
+
[](https://docs.astral.sh/ruff/)
|
|
24
|
+
[](https://docs.astral.sh/ty/)
|
|
25
|
+
[](https://github.com/MaraClaw/PyWhales/blob/HEAD/LICENSE)
|
|
26
|
+
|
|
27
|
+
------------------------------------------------------------------------
|
|
28
|
+
The Docker and its composer client for Python, designed to be fun and intuitive!
|
|
29
|
+
|
|
30
|
+
Works on Linux, macOS and Windows, for Python 3.14.8 and above.
|
|
31
|
+
|
|
32
|
+
* [Documentation](https://github.com/MaraClaw/PyWhales/tree/HEAD/docs)
|
|
33
|
+
* [GitHub repository](https://github.com/MaraClaw/PyWhales)
|
|
34
|
+
|
|
35
|
+
------------------------------------------------------------------------
|
|
36
|
+
|
|
37
|
+
## How to install?
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
uv pip install pywhales
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
See [the Docker CLI guide](https://github.com/MaraClaw/PyWhales/blob/HEAD/docs/template/docker_client.md#the-docker-cli)
|
|
44
|
+
for instructions on installing Docker.
|
|
45
|
+
|
|
46
|
+
## Some cool examples
|
|
47
|
+
|
|
48
|
+
Start by doing
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from pywhales import docker
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
and then:
|
|
55
|
+
|
|
56
|
+
* `docker run hello-world` -> `docker.run("hello-world")`
|
|
57
|
+
* `docker pull ubuntu` -> `docker.pull("ubuntu")`
|
|
58
|
+
* `docker build ./` -> `docker.build("./")`
|
|
59
|
+
* `docker compose up my_service` -> `docker.compose.up(["my_service"])`
|
|
60
|
+
* `docker image ls` -> `docker.image.list()`
|
|
61
|
+
* `docker ps` -> `docker.ps()`
|
|
62
|
+
* `docker cp` -> `docker.copy()`
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
>>> from pywhales import docker
|
|
66
|
+
|
|
67
|
+
>>> output = docker.run("hello-world")
|
|
68
|
+
>>> print(output)
|
|
69
|
+
|
|
70
|
+
Hello from Docker!
|
|
71
|
+
This message shows that your installation appears to be working correctly.
|
|
72
|
+
|
|
73
|
+
...
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
>>> from pywhales import docker
|
|
78
|
+
>>> my_image = docker.build(".", tags="some_name") # uses Buildx/buildkit by default
|
|
79
|
+
[+] Building 1.6s (17/17) FINISHED
|
|
80
|
+
...
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Some more `docker.run()` advanced examples with postgres
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
docker run --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword -d postgres
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
becomes
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from pywhales import docker
|
|
93
|
+
|
|
94
|
+
docker.run(
|
|
95
|
+
"postgres:9.6",
|
|
96
|
+
name="some-postgres",
|
|
97
|
+
envs={"POSTGRES_PASSWORD": "mysecretpassword"},
|
|
98
|
+
detach=True,
|
|
99
|
+
)
|
|
100
|
+
print(docker.ps())
|
|
101
|
+
# [pywhales.Container(id='f5fb939c409d', name='some-postgres')]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
-----
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
docker run -it --rm --network some-network postgres psql -h some-postgres -U postgres
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
becomes
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from pywhales import docker
|
|
114
|
+
|
|
115
|
+
# since it's interactive, you'll be dropped into the psql shell. The python code
|
|
116
|
+
# will continue only after you exit the shell.
|
|
117
|
+
docker.run(
|
|
118
|
+
"postgres:9.6",
|
|
119
|
+
["psql", "-h", "some-postgres", "-U", "postgres"],
|
|
120
|
+
networks=["some-network"],
|
|
121
|
+
interactive=True,
|
|
122
|
+
tty=True,
|
|
123
|
+
remove=True,
|
|
124
|
+
)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
----------
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
docker run -d --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword -e PGDATA=/var/lib/postgresql/data/pgdata -v /custom/mount:/var/lib/postgresql/data -v myvolume:/tmp/myvolume postgres -c shared_buffers=256MB -c max_connections=200
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
becomes
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
from pywhales import docker
|
|
137
|
+
|
|
138
|
+
docker.run(
|
|
139
|
+
"postgres:9.6",
|
|
140
|
+
["-c", "shared_buffers=256MB", "-c", "max_connections=200"],
|
|
141
|
+
name="some-postgres",
|
|
142
|
+
envs={
|
|
143
|
+
"POSTGRES_PASSWORD": "mysecretpassword",
|
|
144
|
+
"PGDATA": "/var/lib/postgresql/data/pgdata",
|
|
145
|
+
},
|
|
146
|
+
volumes=[
|
|
147
|
+
("/custom/mount", "/var/lib/postgresql/data"),
|
|
148
|
+
("myvolume", "/tmp/myvolume"),
|
|
149
|
+
],
|
|
150
|
+
detach=True,
|
|
151
|
+
)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
Any Docker object can be used as a context manager to ensure it's removed even if an exception occurs:
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
from pywhales import docker
|
|
159
|
+
|
|
160
|
+
with docker.volume.create("random_name") as some_volume:
|
|
161
|
+
docker.run(
|
|
162
|
+
"postgres:9.6",
|
|
163
|
+
["-c", "shared_buffers=256MB", "-c", "max_connections=200"],
|
|
164
|
+
name="some-postgres",
|
|
165
|
+
envs={
|
|
166
|
+
"POSTGRES_PASSWORD": "mysecretpassword",
|
|
167
|
+
"PGDATA": "/var/lib/postgresql/data/pgdata",
|
|
168
|
+
},
|
|
169
|
+
volumes=[
|
|
170
|
+
(some_volume, "/var/lib/postgresql/data"),
|
|
171
|
+
("myvolume", "/tmp/myvolume"),
|
|
172
|
+
],
|
|
173
|
+
detach=True,
|
|
174
|
+
)
|
|
175
|
+
# so some stuff here
|
|
176
|
+
|
|
177
|
+
# here we are out of the context manager, so the volume has been removed, even if there was an exception.
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Main features
|
|
181
|
+
|
|
182
|
+
* 1 to 1 mapping between the CLI interface and the Python API. No need to look in the docs
|
|
183
|
+
what is the name of the function/argument you need.
|
|
184
|
+
* Support for the latest Docker features:
|
|
185
|
+
[Docker buildx/buildkit](https://github.com/docker/buildx),
|
|
186
|
+
`docker run --gpu=all ...`
|
|
187
|
+
* Support for Docker stack, services and Swarm (same API as the command line).
|
|
188
|
+
* Progress bars and progressive outputs when pulling, pushing, loading, building...
|
|
189
|
+
* Support for some other CLI commands that are not in [Docker-py](https://docker-py.readthedocs.io/en/stable/):
|
|
190
|
+
`docker cp`, `docker run --cpus ...` and more.
|
|
191
|
+
* Nice SSH support for remote daemons.
|
|
192
|
+
* Docker object as Python objects: Container, Images, Volumes, Services... and their
|
|
193
|
+
attributes are updated in real-time!
|
|
194
|
+
* Each Docker object can be used as a context manager. When getting out of the
|
|
195
|
+
context, the Docker object is removed automatically, even if an exception occurs.
|
|
196
|
+
* A fully typed API (ty and IDE-friendly) compatible with `pathlib` and `os.path`
|
|
197
|
+
* All Docker objects and the Docker client are safe to use with multithreading and multiprocessing.
|
|
198
|
+
* Display the commands called and the environment variables used by setting `PYDOCKER_DEBUG=1`.
|
|
199
|
+
The legacy `PYTHON_ON_WHALES_DEBUG` variable is a fallback only when `PYDOCKER_DEBUG` is unset.
|
|
200
|
+
Setting `PYDOCKER_DEBUG=0` or leaving its value explicitly empty disables debug output even if the legacy variable is set.
|
|
201
|
+
|
|
202
|
+
## What about the license?
|
|
203
|
+
|
|
204
|
+
It's a MIT license, so quite permissive.
|
|
205
|
+
|
|
206
|
+
The license can be found [in the git repository](https://github.com/MaraClaw/PyWhales/blob/HEAD/LICENSE).
|
pywhales-0.2.1/README.md
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# PyWhales
|
|
2
|
+
|
|
3
|
+
------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
[](https://github.com/MaraClaw/PyWhales/actions/workflows/python-package.yml)
|
|
6
|
+
[](https://docs.astral.sh/ruff/)
|
|
7
|
+
[](https://docs.astral.sh/ty/)
|
|
8
|
+
[](https://github.com/MaraClaw/PyWhales/blob/HEAD/LICENSE)
|
|
9
|
+
|
|
10
|
+
------------------------------------------------------------------------
|
|
11
|
+
The Docker and its composer client for Python, designed to be fun and intuitive!
|
|
12
|
+
|
|
13
|
+
Works on Linux, macOS and Windows, for Python 3.14.8 and above.
|
|
14
|
+
|
|
15
|
+
* [Documentation](https://github.com/MaraClaw/PyWhales/tree/HEAD/docs)
|
|
16
|
+
* [GitHub repository](https://github.com/MaraClaw/PyWhales)
|
|
17
|
+
|
|
18
|
+
------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
## How to install?
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
uv pip install pywhales
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
See [the Docker CLI guide](https://github.com/MaraClaw/PyWhales/blob/HEAD/docs/template/docker_client.md#the-docker-cli)
|
|
27
|
+
for instructions on installing Docker.
|
|
28
|
+
|
|
29
|
+
## Some cool examples
|
|
30
|
+
|
|
31
|
+
Start by doing
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from pywhales import docker
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
and then:
|
|
38
|
+
|
|
39
|
+
* `docker run hello-world` -> `docker.run("hello-world")`
|
|
40
|
+
* `docker pull ubuntu` -> `docker.pull("ubuntu")`
|
|
41
|
+
* `docker build ./` -> `docker.build("./")`
|
|
42
|
+
* `docker compose up my_service` -> `docker.compose.up(["my_service"])`
|
|
43
|
+
* `docker image ls` -> `docker.image.list()`
|
|
44
|
+
* `docker ps` -> `docker.ps()`
|
|
45
|
+
* `docker cp` -> `docker.copy()`
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
>>> from pywhales import docker
|
|
49
|
+
|
|
50
|
+
>>> output = docker.run("hello-world")
|
|
51
|
+
>>> print(output)
|
|
52
|
+
|
|
53
|
+
Hello from Docker!
|
|
54
|
+
This message shows that your installation appears to be working correctly.
|
|
55
|
+
|
|
56
|
+
...
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
>>> from pywhales import docker
|
|
61
|
+
>>> my_image = docker.build(".", tags="some_name") # uses Buildx/buildkit by default
|
|
62
|
+
[+] Building 1.6s (17/17) FINISHED
|
|
63
|
+
...
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Some more `docker.run()` advanced examples with postgres
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
docker run --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword -d postgres
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
becomes
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from pywhales import docker
|
|
76
|
+
|
|
77
|
+
docker.run(
|
|
78
|
+
"postgres:9.6",
|
|
79
|
+
name="some-postgres",
|
|
80
|
+
envs={"POSTGRES_PASSWORD": "mysecretpassword"},
|
|
81
|
+
detach=True,
|
|
82
|
+
)
|
|
83
|
+
print(docker.ps())
|
|
84
|
+
# [pywhales.Container(id='f5fb939c409d', name='some-postgres')]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
-----
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
docker run -it --rm --network some-network postgres psql -h some-postgres -U postgres
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
becomes
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from pywhales import docker
|
|
97
|
+
|
|
98
|
+
# since it's interactive, you'll be dropped into the psql shell. The python code
|
|
99
|
+
# will continue only after you exit the shell.
|
|
100
|
+
docker.run(
|
|
101
|
+
"postgres:9.6",
|
|
102
|
+
["psql", "-h", "some-postgres", "-U", "postgres"],
|
|
103
|
+
networks=["some-network"],
|
|
104
|
+
interactive=True,
|
|
105
|
+
tty=True,
|
|
106
|
+
remove=True,
|
|
107
|
+
)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
----------
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
docker run -d --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword -e PGDATA=/var/lib/postgresql/data/pgdata -v /custom/mount:/var/lib/postgresql/data -v myvolume:/tmp/myvolume postgres -c shared_buffers=256MB -c max_connections=200
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
becomes
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from pywhales import docker
|
|
120
|
+
|
|
121
|
+
docker.run(
|
|
122
|
+
"postgres:9.6",
|
|
123
|
+
["-c", "shared_buffers=256MB", "-c", "max_connections=200"],
|
|
124
|
+
name="some-postgres",
|
|
125
|
+
envs={
|
|
126
|
+
"POSTGRES_PASSWORD": "mysecretpassword",
|
|
127
|
+
"PGDATA": "/var/lib/postgresql/data/pgdata",
|
|
128
|
+
},
|
|
129
|
+
volumes=[
|
|
130
|
+
("/custom/mount", "/var/lib/postgresql/data"),
|
|
131
|
+
("myvolume", "/tmp/myvolume"),
|
|
132
|
+
],
|
|
133
|
+
detach=True,
|
|
134
|
+
)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
Any Docker object can be used as a context manager to ensure it's removed even if an exception occurs:
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
from pywhales import docker
|
|
142
|
+
|
|
143
|
+
with docker.volume.create("random_name") as some_volume:
|
|
144
|
+
docker.run(
|
|
145
|
+
"postgres:9.6",
|
|
146
|
+
["-c", "shared_buffers=256MB", "-c", "max_connections=200"],
|
|
147
|
+
name="some-postgres",
|
|
148
|
+
envs={
|
|
149
|
+
"POSTGRES_PASSWORD": "mysecretpassword",
|
|
150
|
+
"PGDATA": "/var/lib/postgresql/data/pgdata",
|
|
151
|
+
},
|
|
152
|
+
volumes=[
|
|
153
|
+
(some_volume, "/var/lib/postgresql/data"),
|
|
154
|
+
("myvolume", "/tmp/myvolume"),
|
|
155
|
+
],
|
|
156
|
+
detach=True,
|
|
157
|
+
)
|
|
158
|
+
# so some stuff here
|
|
159
|
+
|
|
160
|
+
# here we are out of the context manager, so the volume has been removed, even if there was an exception.
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Main features
|
|
164
|
+
|
|
165
|
+
* 1 to 1 mapping between the CLI interface and the Python API. No need to look in the docs
|
|
166
|
+
what is the name of the function/argument you need.
|
|
167
|
+
* Support for the latest Docker features:
|
|
168
|
+
[Docker buildx/buildkit](https://github.com/docker/buildx),
|
|
169
|
+
`docker run --gpu=all ...`
|
|
170
|
+
* Support for Docker stack, services and Swarm (same API as the command line).
|
|
171
|
+
* Progress bars and progressive outputs when pulling, pushing, loading, building...
|
|
172
|
+
* Support for some other CLI commands that are not in [Docker-py](https://docker-py.readthedocs.io/en/stable/):
|
|
173
|
+
`docker cp`, `docker run --cpus ...` and more.
|
|
174
|
+
* Nice SSH support for remote daemons.
|
|
175
|
+
* Docker object as Python objects: Container, Images, Volumes, Services... and their
|
|
176
|
+
attributes are updated in real-time!
|
|
177
|
+
* Each Docker object can be used as a context manager. When getting out of the
|
|
178
|
+
context, the Docker object is removed automatically, even if an exception occurs.
|
|
179
|
+
* A fully typed API (ty and IDE-friendly) compatible with `pathlib` and `os.path`
|
|
180
|
+
* All Docker objects and the Docker client are safe to use with multithreading and multiprocessing.
|
|
181
|
+
* Display the commands called and the environment variables used by setting `PYDOCKER_DEBUG=1`.
|
|
182
|
+
The legacy `PYTHON_ON_WHALES_DEBUG` variable is a fallback only when `PYDOCKER_DEBUG` is unset.
|
|
183
|
+
Setting `PYDOCKER_DEBUG=0` or leaving its value explicitly empty disables debug output even if the legacy variable is set.
|
|
184
|
+
|
|
185
|
+
## What about the license?
|
|
186
|
+
|
|
187
|
+
It's a MIT license, so quite permissive.
|
|
188
|
+
|
|
189
|
+
The license can be found [in the git repository](https://github.com/MaraClaw/PyWhales/blob/HEAD/LICENSE).
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# The Docker client object
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
{{autogenerated}}
|
|
5
|
+
|
|
6
|
+
## Sub-commands
|
|
7
|
+
|
|
8
|
+
* [`docker.buildx`](sub-commands/buildx.md)
|
|
9
|
+
* [`docker.compose`](sub-commands/compose.md)
|
|
10
|
+
* [`docker.config`](sub-commands/config.md)
|
|
11
|
+
* [`docker.container`](sub-commands/container.md)
|
|
12
|
+
* [`docker.context`](sub-commands/context.md)
|
|
13
|
+
* [`docker.image`](sub-commands/image.md)
|
|
14
|
+
* [`docker.manifest`](sub-commands/manifest.md)
|
|
15
|
+
* [`docker.network`](sub-commands/network.md)
|
|
16
|
+
* [`docker.node`](sub-commands/node.md)
|
|
17
|
+
* [`docker.secret`](sub-commands/secret.md)
|
|
18
|
+
* [`docker.service`](sub-commands/service.md)
|
|
19
|
+
* [`docker.stack`](sub-commands/stack.md)
|
|
20
|
+
* [`docker.swarm`](sub-commands/swarm.md)
|
|
21
|
+
* [`docker.system`](sub-commands/system.md)
|
|
22
|
+
* [`docker.trust`](sub-commands/trust.md)
|
|
23
|
+
* [`docker.volume`](sub-commands/volume.md)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## Other commands
|
|
27
|
+
|
|
28
|
+
They're actually aliases
|
|
29
|
+
|
|
30
|
+
* [`docker.attach`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.attach)
|
|
31
|
+
* [`docker.build`](sub-commands/buildx.md#pywhales.components.buildx.cli_wrapper.BuildxCLI.build)
|
|
32
|
+
* [`docker.commit`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.commit)
|
|
33
|
+
* [`docker.copy`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.copy)
|
|
34
|
+
* [`docker.create`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.create)
|
|
35
|
+
* [`docker.diff`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.diff)
|
|
36
|
+
* [`docker.execute`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.execute)
|
|
37
|
+
* [`docker.export`](sub-commands/container.md#pywhales.components.image.cli_wrapper.ImageCLI.export)
|
|
38
|
+
* [`docker.images`](sub-commands/image.md#pywhales.components.image.cli_wrapper.ImageCLI.list)
|
|
39
|
+
* [`docker.import_`](sub-commands/image.md#pywhales.components.image.cli_wrapper.ImageCLI.import_)
|
|
40
|
+
* [`docker.info`](sub-commands/system.md#pywhales.components.system.cli_wrapper.SystemCLI.info)
|
|
41
|
+
* [`docker.kill`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.kill)
|
|
42
|
+
* [`docker.load`](sub-commands/image.md#pywhales.components.image.cli_wrapper.ImageCLI.load)
|
|
43
|
+
* [`docker.logs`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.logs)
|
|
44
|
+
* [`docker.pause`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.pause)
|
|
45
|
+
* [`docker.ps`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.list)
|
|
46
|
+
* [`docker.pull`](sub-commands/image.md#pywhales.components.image.cli_wrapper.ImageCLI.pull)
|
|
47
|
+
* [`docker.push`](sub-commands/image.md#pywhales.components.image.cli_wrapper.ImageCLI.push)
|
|
48
|
+
* [`docker.rename`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.rename)
|
|
49
|
+
* [`docker.restart`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.rename)
|
|
50
|
+
* [`docker.remove`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.rename)
|
|
51
|
+
* [`docker.run`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.rename)
|
|
52
|
+
* [`docker.save`](sub-commands/image.md#pywhales.components.image.cli_wrapper.ImageCLI.save)
|
|
53
|
+
* [`docker.start`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.start)
|
|
54
|
+
* [`docker.stats`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.stats)
|
|
55
|
+
* [`docker.stop`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.stop)
|
|
56
|
+
* [`docker.tag`](sub-commands/image.md#pywhales.components.image.cli_wrapper.ImageCLI.tag)
|
|
57
|
+
* [`docker.top`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.top)
|
|
58
|
+
* [`docker.unpause`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.unpause)
|
|
59
|
+
* [`docker.update`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.update)
|
|
60
|
+
* [`docker.wait`](sub-commands/container.md#pywhales.components.container.cli_wrapper.ContainerCLI.wait)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
## About multithreading and multiprocessing
|
|
64
|
+
|
|
65
|
+
Behind the scenes, pywhales calls the Docker command line interface with
|
|
66
|
+
subprocess. The pywhales client does not store any intermediate state so it's safe
|
|
67
|
+
to use with multithreading.
|
|
68
|
+
|
|
69
|
+
The Docker objects store some intermediate states (the attributes
|
|
70
|
+
that you would normally get with `docker ... inspect`but no logic in
|
|
71
|
+
the codebase depends on those attributes. They're just here so that users can look at them.
|
|
72
|
+
So you can share them between process/threads and pickle containers, images, networks...
|
|
73
|
+
|
|
74
|
+
The Docker daemon works with its own objects internally and handles concurrent and conflicting requests.
|
|
75
|
+
For example, if you create two containers with the same name from different threads, only one will
|
|
76
|
+
succeed. If you pull the same docker image from multiple processes/threads, the Docker daemon will
|
|
77
|
+
only pull the image and layers once.
|
|
78
|
+
|
|
79
|
+
Just be careful with some scenario similar to this one
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
Thread 1: my_container = docker.run(..., detach=True)
|
|
83
|
+
...
|
|
84
|
+
# my_container finishes
|
|
85
|
+
...
|
|
86
|
+
Thread 2: docker.container.prune()
|
|
87
|
+
...
|
|
88
|
+
Thread 1: docker.logs(my_container) # will fail because the container was removed by thread 2
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
In the end, unless you use this type of logic in your code,
|
|
92
|
+
pywhales is safe to use with multithreading and multiprocessing.
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
## The Docker CLI
|
|
96
|
+
|
|
97
|
+
pywhales needs the Docker CLI to work (unlike docker-py).
|
|
98
|
+
Most of the time, users already have the CLI installed on their machines. It's possible to
|
|
99
|
+
verify that the CLI is there by doing `docker --help` in the command line.
|
|
100
|
+
|
|
101
|
+
Sometimes, the CLI might not be available on the system, it can happen if you want to control
|
|
102
|
+
Docker from within a container with `-v /var/run/docker.sock:/var/run/docker.sock`, or if you
|
|
103
|
+
want to connect to a remote daemon with the `host` argument.
|
|
104
|
+
|
|
105
|
+
Instructions for installing Docker can be found at <https://docs.docker.com/engine/install/>.
|
|
106
|
+
Note that if connecting to Docker remotely then a local Docker daemon (`dockerd`) is not needed.
|
|
107
|
+
|
|
108
|
+
Previously, when using python-on-whales, the Docker CLI was downloaded automatically, but
|
|
109
|
+
this functionality was removed under <https://github.com/gabrieldemarmiesse/python-on-whales/pull/633>.
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
### Handling an unavailable client
|
|
113
|
+
|
|
114
|
+
Trying to use pywhales when it cannot find a Docker client binary
|
|
115
|
+
will trigger a `pywhales.ClientNotFoundError`. You can use a try-except around
|
|
116
|
+
a first `docker.ps()` call to handle the case when pywhales won't work.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--8<-- "README.md"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Docker builders
|
|
2
|
+
|
|
3
|
+
The Buildx builders objects.
|
|
4
|
+
|
|
5
|
+
Don't use the constructor directly. Instead use
|
|
6
|
+
```python
|
|
7
|
+
from pywhales import docker
|
|
8
|
+
|
|
9
|
+
my_builder = docker.buildx.inspect("my-builder")
|
|
10
|
+
|
|
11
|
+
# or
|
|
12
|
+
|
|
13
|
+
my_builder = docker.buildx.create()
|
|
14
|
+
```
|
|
15
|
+
For type hints, use this
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from pywhales import Builder
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Attributes
|
|
22
|
+
|
|
23
|
+
The attributes are the same as with the command line:
|
|
24
|
+
`docker buildx inspect ...`
|
|
25
|
+
|
|
26
|
+
Only a few are available at the moment
|
|
27
|
+
```
|
|
28
|
+
In [1]: from pywhales import docker
|
|
29
|
+
|
|
30
|
+
In [2]: my_builder = docker.buildx.create()
|
|
31
|
+
|
|
32
|
+
In [4]: def super_print(obj):
|
|
33
|
+
...: print(f"type={type(obj)}, value={obj}")
|
|
34
|
+
...:
|
|
35
|
+
|
|
36
|
+
@INSERT_GENERATED_CODE@
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Methods
|
|
40
|
+
|
|
41
|
+
{{autogenerated}}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Docker configs
|
|
2
|
+
|
|
3
|
+
Configs objects present in Swarm mode
|
|
4
|
+
|
|
5
|
+
Don't use the constructor directly. Instead use
|
|
6
|
+
```python
|
|
7
|
+
from pywhales import docker
|
|
8
|
+
|
|
9
|
+
my_config = docker.config.inspect("my-config-name")
|
|
10
|
+
|
|
11
|
+
# or
|
|
12
|
+
|
|
13
|
+
my_config = docker.config.create("my_config_name", "my_config_file")
|
|
14
|
+
```
|
|
15
|
+
For type hints, use this
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from pywhales import Config
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def print_config_labels(config: Config):
|
|
22
|
+
print(config.spec.labels)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## Attributes
|
|
27
|
+
|
|
28
|
+
The attributes are the same as with the command line:
|
|
29
|
+
`docker config inspect ...`
|
|
30
|
+
|
|
31
|
+
To get a complete description of those attributes, you
|
|
32
|
+
can take a look at the [daemon api reference page](https://docs.docker.com/engine/api/v1.40/#operation/ConfigInspect)
|
|
33
|
+
and click on "200 No error".
|
|
34
|
+
|
|
35
|
+
An example is worth many lines of descriptions.
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
In [1]: from pywhales import docker
|
|
39
|
+
|
|
40
|
+
In [2]: config = docker.config.create("my_config", "./config_file.cfg", labels=dict(hello="world"))
|
|
41
|
+
|
|
42
|
+
In [3]: def super_print(obj):
|
|
43
|
+
...: print(f"type={type(obj)}, value={obj}")
|
|
44
|
+
...:
|
|
45
|
+
|
|
46
|
+
@INSERT_GENERATED_CODE@
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Methods
|
|
50
|
+
|
|
51
|
+
{{autogenerated}}
|