I had this after reading #12537 and #9047. Currently `DockerOperator`’s `volumes` argument is passed directly to docker-py’s `bind` (aka `docker -v`). But `-v`’s behaviour has long been problematic, and [Docker has been pushing users to the new `--mount` syntax instead](https://docs.docker.com/storage/bind-mounts/#choose-the--v-or---mount-flag). With #12537, it seems like `-v`’s behaviour is also confusing to some Airflow users, so I want to migrate Airflow’s internals to `--mount`.

However, `--mount` has a different syntax to `-v`, and the behaviour is also slightly different, so for compatibility reasons we can’t just do it under the hood. I can think of two possible solutions to this:

A. Deprecate `volumes` altogether and introduce `DockerOperator(mounts=...)`

This will emit a deprecation warning when the user passes `DockerOperator(volumes=...)` to tell them to convert to `DockerOperator(mounts=...)` instead. `volumes` will stay unchanged otherwise, and continue to be passed to bind mounts.

`mounts` will take a list of [`docker.types.Mount`](https://docker-py.readthedocs.io/en/stable/api.html#docker.types.Mount) to describe the mounts. They will be passed directly to the mounts API. Some shorthands could be useful as well, for example:

```python
DockerOperator(
    ...
    mounts=[
        ('/root/data1', './data1'),  # Source and target, default to volume mount.
        ('/root/data2', './data2', 'bind'),  # Bind mount.
    ],
)
```

B. Reuse `volumes` and do introspection to choose between binds and mounts

The `volumes` argument can be augmented to also accept `docker.types.Mount` instances, and internally we’ll do something like

```python
binds = []
mounts = []
for vol in volumes:
    if isinstance(vol, str):
        binds.append(vol)
    elif isintance(vol, docker.types.Mount):
        mounts.append(vol)
    else:
        raise ValueError('...')
if binds:
    warnings.warn('...', DeprecationWarning)
```

and pass the collected lists to binds and mounts respectively.

I’m very interested in hearing thoughts on this.


**Are you willing to submit a PR?**
Yes

**Related Issues**

* #12537: Confusing on the bind syntax.
* #9047: Implement mounting in `DockerSwarmOperator` (it’s a subclass of `DockerOperator`, but the `volumes` option is currently unused).

docs/conf.py
) in AirflowConfigParser.deprecated_options.items():
        deprecated_options[deprecated_section][deprecated_key] = section, key, since_version
    jinja_contexts = {
        'config_ctx': {"configs": default_config_yaml(), "deprecated_options": deprecated_options},
        'quick_start_ctx': {
            'doc_root_url': f'https://airflow.apache.org/docs/apache-airflow/{PACKAGE_VERSION}/'
            if FOR_PRODUCTION
            else (
                'http://apache-airflow-docs.s3-website.eu-central-1.amazonaws.com/docs/apache-airflow/latest/'
            )
        },
    }
elif PACKAGE_NAME.startswith('apache-airflow-providers-'):
    def _load_config():
        templates_dir = os.path.join(PACKAGE_DIR, 'config_templates')
        file_path = os.path.join(templates_dir, "config.yml")
        if not os.path.exists(file_path):
            return {}
        with open(file_path) as f:
            return yaml.load(f, SafeLoader)
    config = _load_config()
    if config:
        jinja_contexts = {'config_ctx': {"configs": config}}
        extensions.append('sphinxcontrib.jinja')
elif PACKAGE_NAME == 'helm-chart':
    def _str_representer(dumper, data):
        style = "|" if "\n" in data else None  # 
        return dumper.represent_scalar("tag:yaml.org,2002:str", data, style)
    yaml.add_representer(str, _str_representer)
    def _format_default(value: Any) -> str: