def list(self, filters: Dict[str, str] = {}) -> List[Image]: """Returns the list of Docker images present on the machine. Alias: `docker.images()` Note that each image may have multiple tags. # Returns A `List[python_on_whales.Image]` object. """ full_cmd = self.docker_cmd + [ "image", "list", "--quiet", "--no-trunc", ] full_cmd.add_args_list("--filter", format_dict_for_cli(filters)) ids = run(full_cmd).splitlines() # the list of tags is bigger than the number of images. We uniquify ids = set(ids) return [ Image(self.client_config, x, is_immutable_id=True) for x in ids ]
def create( self, name: str, file: Union[str, Path], labels: Dict[str, str] = {}, template_driver: Optional[str] = None, ) -> Config: """Create a config from a file See [the docker docs](https://docs.docker.com/engine/swarm/configs/) for more information about swarm configs. # Arguments name: The config name. file: Tbe file to be used as config. labels: The labels to add to the config template_driver: The template driver # Returns A `python_on_whales.Config` object. """ full_cmd = self.docker_cmd + ["config", "create"] full_cmd.add_args_list("--label", format_dict_for_cli(labels)) full_cmd.add_simple_arg("--template-driver", template_driver) full_cmd += [name, file] return Config(self.client_config, run(full_cmd), is_immutable_id=True)
def create( self, name: str, attachable: bool = False, driver: Optional[str] = None, gateway: Optional[str] = None, subnet: Optional[str] = None, labels: Dict[str, str] = {}, options: List[str] = [], ) -> Network: """Creates a Docker network. # Arguments name: The name of the network # Returns A `python_on_whales.Network`. """ full_cmd = self.docker_cmd + ["network", "create"] full_cmd.add_flag("--attachable", attachable) full_cmd.add_simple_arg("--driver", driver) full_cmd.add_simple_arg("--gateway", gateway) full_cmd.add_simple_arg("--subnet", subnet) full_cmd.add_args_list("--label", format_dict_for_cli(labels)) full_cmd.add_args_list("--opt", options) full_cmd.append(name) return Network(self.client_config, run(full_cmd), is_immutable_id=True)
def list(self, filters: Dict[str, str] = {}) -> List[Secret]: """Returns all secrets as a `List[python_on_whales.Secret]`.""" full_cmd = self.docker_cmd + ["secret", "list", "--quiet"] full_cmd.add_args_list("--filter", format_dict_for_cli(filters)) ids = run(full_cmd).splitlines() return [ Secret(self.client_config, id_, is_immutable_id=True) for id_ in ids ]
def prune(self, all: bool = False, filter: Dict[str, str] = {}) -> None: """Remove unused images # Arguments all: Remove all unused images, not just dangling ones filter: Provide filter values (e.g. `{"until": "<timestamp>"}`) """ full_cmd = self.docker_cmd + ["image", "prune", "--force"] full_cmd.add_flag("--all", all) full_cmd.add_args_list("--filter", format_dict_for_cli(filter)) run(full_cmd)
def prune(self, all: bool = False, filters: Dict[str, str] = {}) -> None: """Remove build cache on the current builder. # Arguments all: Remove all cache, not just dangling layers filters: Filters to use, for example `filters=dict(until="24h")` """ full_cmd = self.docker_cmd + ["buildx", "prune", "--force"] full_cmd.add_flag("--all", all) full_cmd.add_args_list("--filter", format_dict_for_cli(filters)) run(full_cmd)
def list(self, filters: Dict[str, str] = {}) -> List[Network]: full_cmd = self.docker_cmd + [ "network", "list", "--no-trunc", "--quiet" ] full_cmd.add_args_list("--filter", format_dict_for_cli(filters)) ids = run(full_cmd).splitlines() return [ Network(self.client_config, id_, is_immutable_id=True) for id_ in ids ]
def list(self, filters: Dict[str, str] = {}) -> List[Config]: """List all config available in the swarm. # Arguments filters: If you want to filter the results based on a given condition. For example, `docker.config.list(filters=dict(label="my_label=hello"))`. # Returns A `List[python_on_whales.Config]`. """ full_cmd = self.docker_cmd + ["config", "list", "--quiet"] full_cmd.add_args_list("--filter", format_dict_for_cli(filters)) output = run(full_cmd) ids = output.splitlines() return [ Config(self.client_config, id_, is_immutable_id=True) for id_ in ids ]
def prune(self, all: bool = False, volumes: bool = False, filters: Dict[str, str] = {}) -> None: """Remove unused docker data # Arguments all: Remove all unused images not just dangling ones volumes: Prune volumes filters: See the [Docker documentation page about filtering ](https://docs.docker.com/engine/reference/commandline/system_prune/#filtering). For example, `filters=dict(until="24h")`. """ full_cmd = self.docker_cmd + ["system", "prune", "--force"] full_cmd.add_flag("--all", all) full_cmd.add_flag("--volumes", volumes) full_cmd.add_args_list("--filter", format_dict_for_cli(filters)) run(full_cmd)
def create( self, name: str, file: ValidPath, driver: Optional[str] = None, labels: Dict[str, str] = {}, template_driver: Optional[str] = None, ) -> Secret: """Creates a `python_on_whales.Secret`. # Returns A `python_on_whales.Secret` object. """ full_cmd = self.docker_cmd + ["secret", "create"] full_cmd.add_simple_arg("--driver", driver) full_cmd.add_args_list("--label", format_dict_for_cli(labels)) full_cmd.add_simple_arg("--template-driver", template_driver) full_cmd += [name, file] return Secret(self.client_config, run(full_cmd), is_immutable_id=True)
def prune(self, filters: Dict[str, str] = {}): full_cmd = self.docker_cmd + ["network", "prune", "--force"] full_cmd.add_args_list("--filter", format_dict_for_cli(filters)) run(full_cmd)
def bake( self, targets: Union[str, List[str]] = [], builder: Optional[ValidBuilder] = None, files: Union[ValidPath, List[ValidPath]] = [], load: bool = False, cache: bool = True, print: bool = False, progress: Union[str, bool] = "auto", pull: bool = False, push: bool = False, set: Dict[str, str] = {}, variables: Dict[str, str] = {}, ) -> Dict[str, Dict[str, Dict[str, Any]]]: """Bake is similar to make, it allows you to build things declared in a file. For example it allows you to build multiple docker image in parallel. The CLI docs is [here](https://github.com/docker/buildx#buildx-bake-options-target) and it contains a lot more information. # Arguments targets: Targets or groups of targets to build. builder: The builder to use. files: Build definition file(s) load: Shorthand for `set=["*.output=type=docker"]` cache: Whether to use the cache or not. print: Do nothing, just returns the config. progress: Set type of progress output (`"auto"`, `"plain"`, `"tty"`, or `False`). Use plain to keep the container output on screen pull: Always try to pull the newer version of the image push: Shorthand for `set=["*.output=type=registry"]` set: A list of overrides in the form `"targetpattern.key=value"`. variables: A dict containing the values of the variables defined in the hcl file. See <https://github.com/docker/buildx#hcl-variables-and-functions> # Returns The configuration used for the bake (files merged + override with the arguments used in the function). It's the loaded json you would obtain by running `docker buildx bake --print --load my_target` if your command was `docker buildx bake --load my_target`. Some example here. ```python from python_on_whales import docker # returns the config used and runs the builds config = docker.buildx.bake(["my_target1", "my_target2"], load=True) assert config == { "target": { "my_target1": { "context": "./", "dockerfile": "Dockerfile", "tags": ["pretty_image1:1.0.0"], "target": "out1", "output": ["type=docker"] }, "my_target2": { "context": "./", "dockerfile": "Dockerfile", "tags": ["pretty_image2:1.0.0"], "target": "out2", "output": ["type=docker"] } } } # returns the config only, doesn't run the builds config = docker.buildx.bake(["my_target1", "my_target2"], load=True, print=True) ``` """ full_cmd = self.docker_cmd + ["buildx", "bake"] full_cmd.add_flag("--no-cache", not cache) full_cmd.add_simple_arg("--builder", builder) full_cmd.add_flag("--load", load) full_cmd.add_flag("--pull", pull) full_cmd.add_flag("--push", push) full_cmd.add_flag("--print", print) if progress != "auto" and isinstance(progress, str): full_cmd += ["--progress", progress] for file in to_list(files): full_cmd.add_simple_arg("--file", file) full_cmd.add_args_list("--set", format_dict_for_cli(set)) targets = to_list(targets) env = dict(os.environ) env.update(variables) if print: return json.loads(run(full_cmd + targets, env=env)) else: run(full_cmd + targets, capture_stderr=progress is False, env=env) return json.loads(run(full_cmd + ["--print"] + targets, env=env))
def format_dict_for_buildx(options: Dict[str, str]) -> str: return ",".join(format_dict_for_cli(options, separator="="))
def build( self, context_path: ValidPath, add_hosts: Dict[str, str] = {}, allow: List[str] = [], build_args: Dict[str, str] = {}, builder: Optional[ValidBuilder] = None, cache: bool = True, cache_from: Union[str, Dict[str, str], None] = None, cache_to: Union[str, Dict[str, str], None] = None, file: Optional[ValidPath] = None, labels: Dict[str, str] = {}, load: bool = False, network: Optional[str] = None, output: Dict[str, str] = {}, platforms: Optional[List[str]] = None, progress: Union[str, bool] = "auto", pull: bool = False, push: bool = False, secrets: Union[str, List[str]] = [], ssh: Optional[str] = None, tags: Union[str, List[str]] = [], target: Optional[str] = None, ) -> Optional[python_on_whales.components.image.Image]: """Build a Docker image with builkit as backend. Alias: `docker.build(...)` A `python_on_whales.Image` is returned, even when using multiple tags. That is because it will produce a single image with multiple tags. If no image is loaded into the Docker daemon (if `push=True` for ex), then `None` is returned. # Arguments context_path: The path of the build context. add_hosts: Hosts to add. `add_hosts={"my_host1": "192.168.32.35"}` allow: List of extra privileges. Eg `allow=["network.host", "security.insecure"]` build_args: The build arguments. ex `build_args={"PY_VERSION": "3.7.8", "UBUNTU_VERSION": "20.04"}`. builder: Specify which builder to use. cache: Whether or not to use the cache cache_from: Works only with the container driver. Loads the cache (if needed) from a registry `cache_from="user/app:cache"` or a directory on the client `cache_from="type=local,src=path/to/dir"`. It's also possible to use a dict form for this argument. e.g. `cache_from=dict(type="local", src="path/to/dir")` cache_to: Works only with the container driver. Sends the resulting docker cache either to a registry `cache_to="user/app:cache"`, or to a local directory `cache_to="type=local,dest=path/to/dir"`. It's also possible to use a dict form for this argument. e.g. `cache_to=dict(type="local", dest="path/to/dir", mode="max")` file: The path of the Dockerfile labels: Dict of labels to add to the image. `labels={"very-secure": "1", "needs-gpu": "0"}` for example. load: Shortcut for `output=dict(type="docker")` If `True`, `docker.buildx.build` will return a `python_on_whales.Image`. network: which network to use when building the Docker image output: Output destination (format: `output={"type": "local", "dest": "path"}` Possible output types are `["local", "tar", "oci", "docker", "image", "registry"]`. See [this link](https://github.com/docker/buildx#-o---outputpath-typetypekeyvalue) for more details about each exporter. platforms: List of target platforms when building the image. Ex: `platforms=["linux/amd64", "linux/arm64"]` progress: Set type of progress output (auto, plain, tty, or False). Use plain to keep the container output on screen pull: Always attempt to pull a newer version of the image push: Shorthand for `output=dict(type="registry")`. secrets: One or more secrets passed as string(s). For example `secrets="id=aws,src=/home/my_user/.aws/credentials"` ssh: SSH agent socket or keys to expose to the build (format is `default|<id>[=<socket>|<key>[,<key>]]` as a string) tags: Tag or tags to put on the resulting image. target: Set the target build stage to build. # Returns A `python_on_whales.Image` if a Docker image is loaded in the daemon after the build (the default behavior when calling `docker.build(...)`). Otherwise, `None`. """ tags = to_list(tags) full_cmd = self.docker_cmd + ["buildx", "build"] if progress != "auto" and isinstance(progress, str): full_cmd += ["--progress", progress] full_cmd.add_args_list("--add-host", format_dict_for_cli(add_hosts, separator=":")) full_cmd.add_args_list("--allow", allow) full_cmd.add_args_list("--build-arg", format_dict_for_cli(build_args)) full_cmd.add_simple_arg("--builder", builder) full_cmd.add_args_list("--label", format_dict_for_cli(labels)) full_cmd.add_simple_arg("--ssh", ssh) full_cmd.add_flag("--pull", pull) full_cmd.add_flag("--push", push) full_cmd.add_flag("--load", load) full_cmd.add_simple_arg("--file", file) full_cmd.add_simple_arg("--target", target) if isinstance(cache_from, dict): full_cmd.add_simple_arg("--cache-from", format_dict_for_buildx(cache_from)) else: full_cmd.add_simple_arg("--cache-from", cache_from) if isinstance(cache_to, dict): full_cmd.add_simple_arg("--cache-to", format_dict_for_buildx(cache_to)) else: full_cmd.add_simple_arg("--cache-to", cache_to) full_cmd.add_args_list("--secret", to_list(secrets)) if output != {}: full_cmd += ["--output", format_dict_for_buildx(output)] if platforms is not None: full_cmd += ["--platform", ",".join(platforms)] full_cmd.add_simple_arg("--network", network) full_cmd.add_flag("--no-cache", not cache) full_cmd.add_args_list("--tag", tags) will_load_image = self._build_will_load_image(builder, push, load, output) # very special_case, must be fixed https://github.com/docker/buildx/issues/420 if (will_load_image and not tags and self.inspect(builder).driver == "docker-container"): # we have no way of fetching the image because iidfile is wrong in this case. will_load_image = False if not will_load_image: full_cmd.append(context_path) run(full_cmd, capture_stderr=progress is False) return docker_image = python_on_whales.components.image.ImageCLI( self.client_config) if self._method_to_get_image(builder) == GetImageMethod.TAG: full_cmd.append(context_path) run(full_cmd, capture_stderr=progress is False) return docker_image.inspect(tags[0]) else: with tempfile.TemporaryDirectory() as tmp_dir: tmp_dir = Path(tmp_dir) iidfile = tmp_dir / "id_file.txt" full_cmd.add_simple_arg("--iidfile", iidfile) full_cmd.append(context_path) run(full_cmd, capture_stderr=progress is False) image_id = iidfile.read_text() return docker_image.inspect(image_id)
def create( self, image: str, command: Union[str, List[str], None], cap_add: List[str] = [], cap_drop: List[str] = [], constraints: List[str] = [], detach: bool = False, dns: List[str] = [], dns_options: List[str] = [], dns_search: List[str] = [], endpoint_mode: Optional[str] = None, entrypoint: Optional[str] = None, envs: Dict[str, str] = {}, env_files: Union[ValidPath, List[ValidPath]] = [], generic_resources: List[str] = [], groups: List[str] = [], healthcheck: bool = True, health_cmd: Optional[str] = None, health_interval: Union[None, int, timedelta] = None, health_retries: Optional[int] = None, health_start_period: Union[None, int, timedelta] = None, health_timeout: Union[None, int, timedelta] = None, hosts: Dict[str, str] = {}, hostname: Optional[str] = None, init: bool = False, isolation: Optional[str] = None, labels: Dict[str, str] = {}, limit_cpu: Optional[float] = None, limit_memory: Optional[str] = None, limit_pids: Optional[int] = None, log_driver: Optional[str] = None, ): """Creates a Docker swarm service. Consider using 'docker stack deploy' instead as it's idempotent and easier to read for complex applications. docker stack deploy is basically docker compose for swarm clusters. # Arguments: image: The image to use as the base for the service. command: The command to execute in the container(s). """ full_cmd = self.docker_cmd + ["service", "create", "--quiet"] full_cmd.add_args_list("--cap-add", cap_add) full_cmd.add_args_list("--cap-drop", cap_drop) full_cmd.add_args_list("--constraint", constraints) full_cmd.add_flag("--detach", detach) full_cmd.add_args_list("--dns", dns) full_cmd.add_args_list("--dns-option", dns_options) full_cmd.add_args_list("--dns-search", dns_search) full_cmd.add_simple_arg("--endpoint-mode", endpoint_mode) full_cmd.add_simple_arg("--entrypoint", entrypoint) full_cmd.add_args_list("--env", format_dict_for_cli(envs)) full_cmd.add_args_list("--env-file", env_files) full_cmd.add_args_list("--generic-resource", generic_resources) full_cmd.add_args_list("--group", groups) full_cmd.add_flag("--no-healthcheck", not healthcheck) full_cmd.add_simple_arg("--health-cmd", health_cmd) full_cmd.add_simple_arg("--health-interval", to_seconds(health_interval)) full_cmd.add_simple_arg("--health-retries", health_retries) full_cmd.add_simple_arg("--health-start-period", to_seconds(health_start_period)) full_cmd.add_simple_arg("--health-timeout", to_seconds(health_timeout)) for key, value in hosts: full_cmd += ["--host", f"{key}:{value}"] full_cmd.add_simple_arg("--hostname", hostname) full_cmd.add_flag("--init", init) full_cmd.add_simple_arg("--isolation", isolation) full_cmd.add_args_list("--label", format_dict_for_cli(labels)) full_cmd.add_simple_arg("--limit-cpu", limit_cpu) full_cmd.add_simple_arg("--limit-memory", limit_memory) full_cmd.add_simple_arg("--limit-pids", limit_pids) full_cmd.add_simple_arg("--log-driver", log_driver) full_cmd.append(image) if command is not None: for string in to_list(command): full_cmd.append(string) service_id = run(full_cmd) return Service(self.client_config, service_id, is_immutable_id=True)