# docker service create

**Descripción:** Crea un nuevo servicio

**Uso:** `docker service create [OPTIONS] IMAGE [COMMAND] [ARG...]`








**Orquestador:** Swarm

## Descripción

Crea un servicio según lo descrito por los parámetros especificados.

> [!NOTE]
> Este es un comando de gestión de clústeres y debe ejecutarse en un nodo administrador de Swarm (manager node).
> Para obtener más información sobre administradores y trabajadores, consulta la
> [sección del modo Swarm](/engine/swarm/) en la
> documentación.


## Opciones

| Opción                                                        | Predeterminado                                        | Descripción                                                                                                                                    |
| ------------------------------------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|  | `--cap-add` |  | API 1.41+ Añade capacidades de Linux |

 | `--cap-drop` |  | API 1.41+ Elimina capacidades de Linux |

 | `--config` |  | API 1.30+ Especifica las configuraciones que se expondrán al servicio |

 | `--constraint` |  |  Restricciones de ubicación |

 | `--container-label` |  |  Etiquetas del contenedor |

 | `--credential-spec` |  | API 1.29+ Especificación de credenciales para cuenta de servicio administrada (solo Windows) |

 | `-d`, `--detach` |  | API 1.29+ Sale inmediatamente en lugar de esperar a que el servicio converja |

 | `--dns` |  | API 1.25+ Establece servidores DNS personalizados |

 | `--dns-option` |  | API 1.25+ Establece opciones de DNS |

 | `--dns-search` |  | API 1.25+ Establece dominios de búsqueda DNS personalizados |

 | `--endpoint-mode` | `vip` |  Modo de endpoint (vip o dnsrr) |

 | `--entrypoint` |  |  Sobrescribe el ENTRYPOINT por defecto de la imagen |

 | `-e`, `--env` |  |  Establece variables de entorno |

 | `--env-file` |  |  Lee un archivo de variables de entorno |

 | `--generic-resource` |  |  Recursos definidos por el usuario |

 | `--group` |  | API 1.25+ Establece uno o más grupos de usuarios suplementarios para el contenedor |

 | `--health-cmd` |  | API 1.25+ Comando a ejecutar para comprobar el estado de salud |

 | `--health-interval` |  | API 1.25+ Tiempo entre ejecuciones de la comprobación (ms|s|m|h) |

 | `--health-retries` |  | API 1.25+ Fallos consecutivos necesarios para reportar un estado insalubre |

 | `--health-start-interval` |  | API 1.44+ Tiempo entre ejecuciones de la comprobación durante el período de inicio (ms|s|m|h) |

 | `--health-start-period` |  | API 1.29+ Período de inicio para que el contenedor se inicialice antes de comenzar la cuenta regresiva de reintentos de salud (ms|s|m|h)<br> |

 | `--health-timeout` |  | API 1.25+ Tiempo máximo permitido para que se ejecute una comprobación (ms|s|m|h) |

 | `--host` |  | API 1.25+ Establece una o más asociaciones de host a IP personalizadas (host:ip) |

 | `--hostname` |  | API 1.25+ Nombre de host del contenedor |

 | `--init` |  | API 1.37+ Utiliza un proceso init dentro de cada contenedor del servicio para reenviar señales y adoptar procesos huérfanos<br> |

 | `--isolation` |  | API 1.35+ Modo de aislamiento del contenedor del servicio |

 | `-l`, `--label` |  |  Etiquetas del servicio |

 | `--limit-cpu` |  |  Limita las CPUs |

 | `--limit-memory` |  |  Limita la memoria |

 | `--limit-pids` |  | API 1.41+ Limita el número máximo de procesos (por defecto 0 = ilimitado) |

 | `--log-driver` |  |  Controlador de registro para el servicio |

 | `--log-opt` |  |  Opciones del controlador de registro |

 | `--max-concurrent` |  | API 1.41+ Número de tareas de trabajo a ejecutar simultáneamente (por defecto es igual a --replicas)<br> |

 | `--memory-swap` |  | API 1.52+ Bytes de intercambio (swap) (-1 para ilimitado) |

 | `--memory-swappiness` | `-1` | API 1.52+ Ajusta la tendencia al intercambio (swappiness) de memoria (0-100), -1 para restablecer al valor predeterminado |

 | `--mode` | `replicated` |  Modo de servicio (`replicated`, `global`, `replicated-job`, `global-job`)<br> |

 | `--mount` |  |  Acopla un montaje de sistema de archivos al servicio |

 | `--name` |  |  Nombre del servicio |

 | `--network` |  |  Conexiones de red |

 | `--no-healthcheck` |  | API 1.25+ Deshabilita cualquier HEALTHCHECK especificado por el contenedor |

 | `--no-resolve-image` |  | API 1.30+ No consulta el registro para resolver el digest de la imagen y las plataformas compatibles<br> |

 | `--oom-score-adj` |  | API 1.46+ Ajusta las preferencias OOM del host (-1000 a 1000) |

 | `--placement-pref` |  | API 1.28+ Añade una preferencia de ubicación |

 | `-p`, `--publish` |  |  Publica un puerto como puerto de nodo |

 | `-q`, `--quiet` |  |  Suprime la salida del progreso |

 | `--read-only` |  | API 1.28+ Monta el sistema de archivos raíz del contenedor como de solo lectura |

 | `--replicas` |  |  Número de tareas |

 | `--replicas-max-per-node` |  | API 1.40+ Número máximo de tareas por nodo (por defecto 0 = ilimitado) |

 | `--reserve-cpu` |  |  Reserva CPUs |

 | `--reserve-memory` |  |  Reserva memoria |

 | `--restart-condition` |  |  Reinicia cuando se cumple la condición (`none`, `on-failure`, `any`) (por defecto `any`)<br> |

 | `--restart-delay` |  |  Retraso entre intentos de reinicio (ns|us|ms|s|m|h) (por defecto 5s) |

 | `--restart-max-attempts` |  |  Número máximo de reinicios antes de darse por vencido |

 | `--restart-window` |  |  Ventana de tiempo utilizada para evaluar la política de reinicio (ns|us|ms|s|m|h) |

 | `--rollback-delay` |  | API 1.28+ Retraso entre reversiones (rollbacks) de tareas (ns|us|ms|s|m|h) (por defecto 0s) |

 | `--rollback-failure-action` |  | API 1.28+ Acción ante un fallo en la reversión (rollback) (`pause`, `continue`) (por defecto `pause`) |

 | `--rollback-max-failure-ratio` |  | API 1.28+ Tasa de fallos tolerada durante una reversión (rollback) (por defecto 0) |

 | `--rollback-monitor` |  | API 1.28+ Duración después de cada reversión (rollback) de tarea para monitorear fallos (ns|us|ms|s|m|h) (por defecto 5s)<br> |

 | `--rollback-order` |  | API 1.29+ Orden de reversión (rollback) (`start-first`, `stop-first`) (por defecto `stop-first`)<br> |

 | `--rollback-parallelism` | `1` | API 1.28+ Número máximo de tareas revertidas (rolled back) simultáneamente (0 para revertir todas a la vez)<br> |

 | `--secret` |  | API 1.25+ Especifica secretos que se expondrán al servicio |

 | `--stop-grace-period` |  |  Tiempo a esperar antes de forzar la finalización de un contenedor (ns|us|ms|s|m|h) (por defecto 10s)<br> |

 | `--stop-signal` |  | API 1.28+ Señal para detener el contenedor |

 | `--sysctl` |  | API 1.40+ Opciones de sysctl |

 | `-t`, `--tty` |  | API 1.25+ Asigna un pseudo-TTY |

 | `--ulimit` |  | API 1.41+ Opciones de ulimit |

 | `--update-delay` |  |  Retraso entre actualizaciones (ns|us|ms|s|m|h) (por defecto 0s) |

 | `--update-failure-action` |  |  Acción ante un fallo en la actualización (`pause`, `continue`, `rollback`) (por defecto `pause`)<br> |

 | `--update-max-failure-ratio` |  | API 1.25+ Tasa de fallos tolerada durante una actualización (por defecto 0) |

 | `--update-monitor` |  | API 1.25+ Duración después de cada actualización de tarea para monitorear fallos (ns|us|ms|s|m|h) (por defecto 5s)<br> |

 | `--update-order` |  | API 1.29+ Orden de actualización (`start-first`, `stop-first`) (por defecto `stop-first`) |

 | `--update-parallelism` | `1` |  Número máximo de tareas actualizadas simultáneamente (0 para actualizar todas a la vez)<br> |

 | `-u`, `--user` |  |  Nombre de usuario o UID (formato: <nombre|uid>[:<grupo|gid>]) |

 | `--with-registry-auth` |  |  Envía detalles de autenticación del registro a los agentes de swarm |

 | `-w`, `--workdir` |  |  Directorio de trabajo dentro del contenedor |




## Ejemplos

### Crear un servicio

```console
$ docker service create --name redis redis:7.4.1

dmu1ept4cxcfe8k8lhtux3ro3

$ docker service create --mode global --name redis2 redis:7.4.1

a8q9dasaafudfs8q8w32udass

$ docker service ls

ID            NAME    MODE        REPLICAS  IMAGE
dmu1ept4cxcf  redis   replicated  1/1       redis:7.4.1
a8q9dasaafud  redis2  global      1/1       redis:7.4.1
```

#### Crear un servicio utilizando una imagen de un registro privado (--with-registry-auth) {#with-registry-auth}

Si tu imagen está disponible en un registro privado que requiere iniciar sesión, utiliza el
flag `--with-registry-auth` con `docker service create`, después de haber iniciado sesión. Si
tu imagen está almacenada en `registry.example.com`, que es un registro privado, utiliza
un comando como el siguiente:

```console
$ docker login registry.example.com

$ docker service  create \
  --with-registry-auth \
  --name my_service \
  registry.example.com/acme/my_image:latest
```

Esto pasa el token de inicio de sesión desde tu cliente local a los nodos de swarm donde se
despliega el servicio, utilizando los registros WAL cifrados. Con esta información, los
nodos pueden iniciar sesión en el registro y descargar la imagen.

### Crear un servicio con 5 tareas réplica (--replicas) {#replicas}

Utiliza el flag `--replicas` para establecer el número de tareas réplica para un servicio
replicado. El siguiente comando crea un servicio `redis` con `5` tareas réplica:

```console
$ docker service create --name redis --replicas=5 redis:7.4.1

4cdgfyky7ozwh3htjfw0d12qv
```

El comando anterior establece el número *deseado* de tareas para el servicio. Aunque
el comando devuelve la salida inmediatamente, el escalado real del servicio puede tomar
algún tiempo. La columna `REPLICAS` muestra tanto el número real como el deseado
de tareas réplica para el servicio.

En el siguiente ejemplo, el estado deseado es de `5` réplicas, pero el número
actual de tareas `RUNNING` (en ejecución) es `3`:

```console
$ docker service ls

ID            NAME   MODE        REPLICAS  IMAGE
4cdgfyky7ozw  redis  replicated  3/5       redis:7.4.1
```

Una vez creadas todas las tareas y en estado `RUNNING`, el número real de tareas es
igual al deseado:

```console
$ docker service ls

ID            NAME   MODE        REPLICAS  IMAGE
4cdgfyky7ozw  redis  replicated  5/5       redis:7.4.1
```

### Crear un servicio con secretos (--secret) {#secret}

Utiliza el flag `--secret` para dar acceso a un contenedor a un
[secreto](/reference/cli/docker/secret/create/).

Crea un servicio especificando un secreto:

```console
$ docker service create --name redis --secret secret.json redis:7.4.1

4cdgfyky7ozwh3htjfw0d12qv
```

Crea un servicio especificando el secreto, el destino, el ID de usuario/grupo y el modo:

```console
$ docker service create --name redis \
    --secret source=ssh-key,target=ssh \
    --secret source=app-key,target=app,uid=1000,gid=1001,mode=0400 \
    redis:7.4.1

4cdgfyky7ozwh3htjfw0d12qv
```

Para conceder acceso a un servicio a múltiples secretos, utiliza múltiples flags `--secret`.

Los secretos se encuentran en `/run/secrets` en el contenedor si no se especifica ningún destino.
Si no se especifica ningún destino, el nombre del secreto se utiliza como el archivo en memoria
en el contenedor. Si se especifica un destino, este se utiliza como nombre de archivo. En el
ejemplo anterior, se crean dos archivos: `/run/secrets/ssh` y
`/run/secrets/app` para cada uno de los destinos de secreto especificados.

### Crear un servicio con configuraciones (--config) {#config}

Utiliza el flag `--config` para dar acceso a un contenedor a una
[configuración](/reference/cli/docker/config/create/).

Crea un servicio con una configuración. La configuración se montará en `redis-config`,
será propiedad del usuario que ejecuta el comando dentro del contenedor (a menudo `root`),
y tendrá el modo de archivo `0444` (legible para todos). Puedes especificar el `uid` y el `gid`
como IDs numéricos o nombres. Cuando utilices nombres, los nombres de grupo/usuario proporcionados
deben existir previamente en el contenedor. El `mode` se especifica como una secuencia de 4 números,
como `0755`.

```console
$ docker service create --name=redis --config redis-conf redis:7.4.1
```

Crea un servicio con una configuración y especifica la ubicación de destino y el modo de archivo:

```console
$ docker service create --name redis \
  --config source=redis-conf,target=/etc/redis/redis.conf,mode=0400 redis:7.4.1
```

Para conceder acceso a un servicio a múltiples configuraciones, utiliza múltiples flags `--config`.

Las configuraciones se encuentran en `/` en el contenedor si no se especifica ningún destino. Si no
se especifica ningún destino, el nombre de la configuración se utiliza como el nombre del archivo en
el contenedor. Si se especifica un destino, este se utiliza como nombre de archivo.

### Crear un servicio con una política de actualización continua (rolling update) {#update-delay}

```console
$ docker service create \
  --replicas 10 \
  --name redis \
  --update-delay 10s \
  --update-parallelism 2 \
  redis:7.4.1
```

Al ejecutar una [actualización del servicio](/reference/cli/docker/service/update/), el planificador actualiza un
máximo de 2 tareas a la vez, con un intervalo de `10s` entre actualizaciones. Para obtener más información,
consulta el [tutorial de actualizaciones continuas](/engine/swarm/swarm-tutorial/rolling-update/).

### Establecer variables de entorno (-e, --env) {#env}

Esto establece una variable de entorno para todas las tareas de un servicio. Por ejemplo:

```console
$ docker service create \
  --name redis_2 \
  --replicas 5 \
  --env MYVAR=foo \
  redis:7.4.1
```

Para especificar múltiples variables de entorno, especifica múltiples flags `--env`, cada uno
con un par clave-valor independiente.

```console
$ docker service create \
  --name redis_2 \
  --replicas 5 \
  --env MYVAR=foo \
  --env MYVAR2=bar \
  redis:7.4.1
```

### Crear un servicio con un nombre de host específico (--hostname) {#hostname}

Esta opción establece el nombre de host (hostname) de los contenedores del servicio Docker en una cadena específica.
Por ejemplo:

```console
$ docker service create --name redis --hostname myredis redis:7.4.1
```

### Establecer metadatos en un servicio (-l, --label) {#label}

Una etiqueta (label) es un par `clave=valor` que aplica metadatos a un servicio. Para etiquetar un
servicio con dos etiquetas:

```console
$ docker service create \
  --name redis_2 \
  --label com.example.foo="bar" \
  --label bar=baz \
  redis:7.4.1
```

Para obtener más información sobre las etiquetas, consulta [aplicar metadatos personalizados](/config/labels-custom-metadata/).

### Añadir montajes vinculados (bind mounts), volúmenes o sistemas de archivos en memoria (--mount) {#mount}

Docker admite tres tipos diferentes de montajes, que permiten a los contenedores leer
o escribir en archivos o directorios, ya sea en el sistema operativo del host o
en sistemas de archivos en memoria. Estos tipos son volúmenes de datos (a menudo llamados simplemente
volúmenes), montajes vinculados (bind mounts), tmpfs y tuberías con nombre (named pipes).

Un **montaje vinculado (bind mount)** hace que un archivo o directorio del host esté disponible para el
contenedor en el que está montado. Un montaje vinculado puede ser de solo lectura o
de lectura y escritura. Por ejemplo, un contenedor podría compartir la información DNS de su host mediante
un montaje vinculado del archivo `/etc/resolv.conf` del host, o un contenedor podría
escribir registros en el directorio `/var/log/myContainerLogs` de su host. Si utilizas
montajes vinculados y tu host y contenedores tienen diferentes nociones de permisos,
controles de acceso u otros detalles similares, te encontrarás con problemas de portabilidad.

Un **volumen con nombre (named volume)** es un mecanismo para desacoplar los datos persistentes que necesita tu
contenedor de la imagen utilizada para crearlo y de la máquina host.
Los volúmenes con nombre son creados y gestionados por Docker, y persisten
incluso cuando ningún contenedor los está utilizando actualmente. Los datos en los volúmenes con nombre se pueden
compartir entre un contenedor y la máquina host, así como entre múltiples
contenedores. Docker utiliza un _controlador de volumen (volume driver)_ para crear, gestionar y montar volúmenes.
Puedes hacer copias de seguridad o restaurar volúmenes utilizando comandos de Docker.

Un **tmpfs** monta un sistema de archivos tmpfs dentro de un contenedor para datos volátiles.

Un **npipe** monta una tubería con nombre (named pipe) desde el host en el contenedor.

Considera una situación en la que tu imagen inicia un servidor web ligero. Podrías
utilizar esa imagen como imagen base, copiar los archivos HTML de tu sitio web y empaquetar
eso en otra imagen. Cada vez que cambie tu sitio web, tendrías que actualizar
la nueva imagen y volver a desplegar todos los contenedores que sirven a tu sitio web. Una mejor
solución es almacenar el sitio web en un volumen con nombre que se conecte a cada uno de
tus contenedores de servidor web cuando se inicien. Para actualizar el sitio web, solo tienes que
actualizar el volumen con nombre.

Para obtener más información sobre los volúmenes con nombre, consulta
[Volúmenes de datos](/storage/volumes/).

La siguiente tabla describe las opciones que se aplican tanto a los montajes vinculados como a los
volúmenes con nombre en un servicio:

<table>
  <tr>
    <th>Opción</th>
    <th>Requerido</th>
    <th>Descripción</th>
  </tr>
  <tr>
    <td><b>type</b></td>
    <td></td>
    <td>
      <p>El tipo de montaje, puede ser el de <tt>volume</tt>, <tt>bind</tt>, <tt>tmpfs</tt> o <tt>npipe</tt>. Por defecto es <tt>volume</tt> si no se especifica el tipo.</p>
      <ul>
        <li><tt>volume</tt>: monta un <a href="/reference/cli/docker/volume/create/">volumen gestionado</a>
        en el contenedor.</li> <li><tt>bind</tt>:
        monta de forma vinculada (bind-mount) un directorio o archivo del host en el contenedor.</li>
        <li><tt>tmpfs</tt>: monta un tmpfs en el contenedor</li>
        <li><tt>npipe</tt>: monta una tubería con nombre (named pipe) desde el host en el contenedor (solo contenedores de Windows).</li>
      </ul>
    </td>
  </tr>
  <tr>
    <td><b>src</b> o <b>source</b></td>
    <td>para <tt>type=bind</tt> y <tt>type=npipe</tt></td>
    <td>
      <ul>
        <li>
         <tt>type=volume</tt>: <tt>src</tt> es una forma opcional de especificar el nombre del volumen (por ejemplo, <tt>src=my-volume</tt>).
          Si el volumen con nombre no existe, se crea automáticamente. Si no se especifica <tt>src</tt>, se le asigna al volumen
          un nombre aleatorio que garantiza ser único en el host, pero que podría no ser único en todo el clúster.
          Un volumen con nombre aleatorio tiene el mismo ciclo de vida que su contenedor y se destruye cuando el <i>contenedor</i>
          se destruye (lo cual ocurre al actualizar el servicio, o al escalar o reequilibrar el servicio)
        </li>
        <li>
          <tt>type=bind</tt>: <tt>src</tt> es requerido y especifica una ruta absoluta al archivo o directorio que se va a montar de forma vinculada
          (por ejemplo, <tt>src=/path/on/host/</tt>). Se produce un error si el archivo o directorio no existe.
        </li>
        <li>
          <tt>type=tmpfs</tt>: <tt>src</tt> no es compatible.
        </li>
      </ul>
    </td>
  </tr>
  <tr>
    <td><p><b>dst</b> o <b>destination</b> o <b>target</b></p></td>
    <td>sí</td>
    <td>
      <p>Ruta de montaje dentro del contenedor, por ejemplo <tt>/some/path/in/container/</tt>.
      Si la ruta no existe en el sistema de archivos del contenedor, Engine crea
      un directorio en la ubicación especificada antes de montar el volumen o el montaje vinculado.</p>
    </td>
  </tr>
  <tr>
    <td><p><b>readonly</b> o <b>ro</b></p></td>
    <td></td>
    <td>
      <p>Engine monta los enlaces y volúmenes como <tt>read-write</tt> a menos que se indique la opción <tt>readonly</tt>
      al montar el enlace o volumen. Ten en cuenta que establecer <tt>readonly</tt> para un
      montaje vinculado podría no hacer que sus submontajes sean de solo lectura según la versión del kernel. Consulta también <tt>bind-recursive</tt>.</p>
      <ul>
        <li><tt>true</tt> o <tt>1</tt> o sin valor: Monta el enlace o volumen como de solo lectura.</li>
        <li><tt>false</tt> o <tt>0</tt>: Monta el enlace o volumen como de lectura y escritura.</li>
      </ul>
    </td>
  </tr>
</table>

#### Opciones para montajes vinculados (bind mounts)

Las siguientes opciones solo se pueden utilizar para montajes vinculados (`type=bind`):


<table>
  <tr>
    <th>Opción</th>
    <th>Descripción</th>
  </tr>
  <tr>
    <td><b>bind-propagation</b></td>
    <td>
      <p>Consulta la <a href="#bind-propagation">sección de propagación de montaje</a>.</p>
    </td>
  </tr>
  <tr>
    <td><b>consistency</b></td>
    <td>
      <p>Los requisitos de consistencia para el montaje; uno de </p>
      <ul>
       <li><tt>default</tt>: Equivalente a <tt>consistent</tt>.</li>
       <li><tt>consistent</tt>: Consistencia total. El entorno de ejecución del contenedor y el host mantienen una vista idéntica del montaje en todo momento.</li>
       <li><tt>cached</tt>: La vista del host del montaje es autoritativa. Puede haber retrasos antes de que las actualizaciones realizadas en el host sean visibles dentro del contenedor.</li>
       <li><tt>delegated</tt>: La vista del entorno de ejecución del contenedor es autoritativa. Puede haber retrasos antes de que las actualizaciones realizadas en el contenedor sean visibles en el host.</li>
      </ul>
    </td>
  </tr>
  <tr>
    <td><b>bind-recursive</b></td>
    <td>
      Por defecto, los submontajes también se montan de forma vinculada recursivamente. Sin embargo, este comportamiento puede resultar confuso cuando un
      montaje vinculado se configura con la opción <tt>readonly</tt>, porque los submontajes podrían no montarse como de solo lectura,
      dependiendo de la versión del kernel.
      Establece <tt>bind-recursive</tt> para controlar el comportamiento del montaje vinculado recursivo.<br />
      <br />
      El valor es uno de:<br />
      <br />
      <ul>
        <li><tt>enabled</tt>: Habilita el montaje vinculado recursivo.
        Los montajes de solo lectura se hacen recursivamente de solo lectura si el kernel es v5.12 o posterior.
        De lo contrario, no se hacen recursivamente de solo lectura.</li>
        <li><tt>disabled</tt>: Deshabilita el montaje vinculado recursivo.</li>
        <li><tt>writable</tt>: Habilita el montaje vinculado recursivo.
        Los montajes de solo lectura no se hacen recursivamente de solo lectura.</li>
        <li><tt>readonly</tt>: Habilita el montaje vinculado recursivo.
        Los montajes de solo lectura se hacen recursivamente de solo lectura si el kernel es v5.12 o posterior.
        De lo contrario, Engine produce un error.</li>
      </ul>
      Cuando la opción no está especificada, el comportamiento predeterminado corresponde a establecer <tt>enabled</tt>.
    </td>
  </tr>
  <tr>
    <td><b>bind-create-src</b></td>
    <td>
      Por defecto, los montajes vinculados requieren que la ruta de origen exista en el host del demonio. Esta es una diferencia significativa
      con respecto al flag <tt>-v</tt>, que crea la ruta de origen si no existe.<br />
      <br />
      Establece <tt>bind-create-src</tt> para crear la ruta de origen en el host del demonio si no existe.<br />
      <br />
      El valor es opcional:<br />
      <br />
      <ul>
        <li><tt>true</tt> o <tt>1</tt>: Crea la ruta en el host del demonio si no existe.</li>
        <li><tt>false</tt> o <tt>0</tt>: Comportamiento predeterminado. Produce un error si la ruta de origen no existe en el host del demonio.</li>
      </ul>
    </td>
  </tr>
</table>

##### Propagación de montaje (bind propagation)

La propagación de montaje se refiere a si los montajes creados dentro de un montaje
vinculado o volumen con nombre dado se pueden propagar a las réplicas de ese montaje o no. Considera
un punto de montaje `/mnt`, que también está montado en `/tmp`. Los ajustes de propagación
controlan si un montaje en `/tmp/a` también estaría disponible en `/mnt/a`. Cada
ajuste de propagación tiene una contraparte recursiva. En el caso de recursividad,
considera que `/tmp/a` también está montado como `/foo`. Los ajustes de propagación
controlan si `/mnt/a` y/o `/tmp/a` existirían.

La opción `bind-propagation` se establece de forma predeterminada en `rprivate` tanto para montajes vinculados como para
montajes de volumen, y solo se puede configurar para montajes vinculados. En otras palabras, los volúmenes con nombre
no admiten la propagación de montaje.

- **`shared`**: Los submontajes del montaje original se exponen a los montajes réplica,
                y los submontajes de los montajes réplica también se propagan al
                montaje original.
- **`slave`**: similar a un montaje compartido, pero solo en una dirección. Si el
               montaje original expone un submontaje, el montaje réplica puede verlo.
               Sin embargo, si el montaje réplica expone un submontaje, el montaje original
               no puede verlo.
- **`private`**: El montaje es privado. Los submontajes dentro de él no se exponen a
                 los montajes réplica, y los submontajes de los montajes réplica no
                 se exponen al montaje original.
- **`rshared`**: Lo mismo que shared, pero la propagación también se extiende hacia y desde
                 los puntos de montaje anidados dentro de cualquiera de los puntos de montaje
                 originales o réplicas.
- **`rslave`**: Lo mismo que `slave`, pero la propagación también se extiende hacia y desde
                 los puntos de montaje anidados dentro de cualquiera de los puntos de montaje
                 originales o réplicas.
- **`rprivate`**: El predeterminado. Lo mismo que `private`, lo que significa que ningún punto de montaje
                  en ningún lugar dentro de los puntos de montaje originales o réplicas se propaga
                  en ninguna dirección.

Para obtener más información sobre la propagación de montaje, consulta la
[documentación del kernel de Linux para subárboles compartidos (shared subtree)](https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt).

#### Opciones para volúmenes con nombre

Las siguientes opciones solo se pueden utilizar para volúmenes con nombre (`type=volume`):


<table>
  <tr>
    <th>Opción</th>
    <th>Descripción</th>
  </tr>
  <tr>
    <td><b>volume-driver</b></td>
    <td>
      <p>Nombre del plugin del controlador de volumen (volume-driver) a utilizar para el volumen. Por defecto es
      <tt>"local"</tt>, para utilizar el controlador de volumen local para crear el volumen si este
      no existe.</p>
    </td>
  </tr>
  <tr>
    <td><b>volume-label</b></td>
    <td>
      Uno o más metadatos personalizados ("etiquetas") para aplicar al volumen en el momento de su
      creación. Por ejemplo,
      <tt>volume-label=mylabel=hello-world,my-other-label=hello-mars</tt>. Para obtener más
      información sobre las etiquetas, consulta
      <a href="/config/labels-custom-metadata/">aplicar metadatos personalizados</a>.
    </td>
  </tr>
  <tr>
    <td><b>volume-nocopy</b></td>
    <td>
      Por defecto, si conectas un volumen vacío a un contenedor y ya existían archivos o
      directorios en la ruta de montaje en el contenedor (<tt>dst</tt>),
      Engine copia esos archivos y directorios en el volumen, permitiendo
      que el host acceda a ellos. Establece <tt>volume-nocopy</tt> para deshabilitar la copia de archivos
      desde el sistema de archivos del contenedor al volumen y montar el volumen vacío.<br />
      <br />
      El valor es opcional:<br />
      <br />
      <ul>
        <li><tt>true</tt> o <tt>1</tt>: Predeterminado si no proporcionas un valor. Deshabilita la copia.</li>
        <li><tt>false</tt> o <tt>0</tt>: Habilita la copia.</li>
      </ul>
    </td>
  </tr>
  <tr>
    <td><b>volume-opt</b></td>
    <td>
      Opciones específicas para un controlador de volumen dado, que se pasarán al
      controlador al crear el volumen. Las opciones se proporcionan como una lista separada por comas
      de pares clave/valor, por ejemplo,
      <tt>volume-opt=some-option=some-value,volume-opt=some-other-option=some-other-value</tt>.
      Para conocer las opciones disponibles para un controlador dado, consulta la
      documentación de ese controlador.
    </td>
  </tr>
</table>


#### Opciones para tmpfs

Las siguientes opciones solo se pueden utilizar para montajes tmpfs (`type=tmpfs`):


<table>
  <tr>
    <th>Opción</th>
    <th>Descripción</th>
  </tr>
  <tr>
    <td><b>tmpfs-size</b></td>
    <td>Tamaño del montaje tmpfs en bytes. Sin límite por defecto en Linux.</td>
  </tr>
  <tr>
    <td><b>tmpfs-mode</b></td>
    <td>Modo de archivo del tmpfs en octal (por ejemplo, <tt>"700"</tt> o <tt>"0700"</tt>). Por defecto es <tt>"1777"</tt> en Linux.</td>
  </tr>
</table>


#### Diferencias entre "--mount" y "--volume"

El flag `--mount` admite la mayoría de las opciones que admite el flag `-v`
o `--volume` para `docker run`, con algunas excepciones importantes:

- El flag `--mount` te permite especificar un controlador de volumen y opciones del controlador de volumen
  *por volumen*, sin tener que crear los volúmenes con antelación. En cambio,
  `docker run` te permite especificar un único controlador de volumen que comparten todos los volúmenes,
  utilizando el flag `--volume-driver`.

- El flag `--mount` te permite especificar metadatos personalizados ("etiquetas") para un volumen,
  antes de que se cree el volumen.

- Cuando utilizas `--mount` con `type=bind`, la ruta del host debe hacer referencia a una ruta *existente*
  en el host. La ruta no se creará por ti y el servicio fallará con un error si la ruta no existe. Puedes utilizar
  `bind-create-src` para crear la ruta del host si no existe.

- El flag `--mount` no te permite volver a etiquetar un volumen con los flags `Z` o `z`,
  que se utilizan para el etiquetado de `selinux`.

#### Crear un servicio utilizando un volumen con nombre

El siguiente ejemplo crea un servicio que utiliza un volumen con nombre:

```console
$ docker service create \
  --name my-service \
  --replicas 3 \
  --mount type=volume,source=my-volume,destination=/path/in/container,volume-label="color=red",volume-label="shape=round" \
  nginx:alpine
```

Para cada réplica del servicio, Engine solicita un volumen llamado "my-volume"
al controlador de volumen predeterminado ("local") donde se despliega la tarea. Si el
volumen no existe, Engine crea un nuevo volumen y aplica las etiquetas "color"
y "shape".

Cuando se inicia la tarea, el volumen se monta en `/path/in/container/` dentro
del contenedor.

Ten en cuenta que el volumen predeterminado ("local") es un controlador de volumen de alcance local.
Esto significa que, dependiendo de dónde se despliegue una tarea, esta tarea obtendrá un
*nuevo* volumen llamado "my-volume", o compartirá el mismo "my-volume" con otras tareas
del mismo servicio. Varios contenedores escribiendo en un mismo volumen compartido puede
causar corrupción de datos si el software que se ejecuta dentro del contenedor no está
diseñado para manejar procesos simultáneos escribiendo en la misma ubicación. Ten también
en cuenta que los contenedores pueden ser reprogramados por el orquestador de Swarm y
desplegarse en un nodo diferente.

#### Crear un servicio que utiliza un volumen anónimo

El siguiente comando crea un servicio con tres réplicas con un volumen anónimo
en `/path/in/container`:

```console
$ docker service create \
  --name my-service \
  --replicas 3 \
  --mount type=volume,destination=/path/in/container \
  nginx:alpine
```

En este ejemplo, no se especifica ningún nombre (`source`) para el volumen, por lo que se crea
un nuevo volumen para cada tarea. Esto garantiza que cada tarea obtenga su propio volumen
y que los volúmenes no se compartan entre tareas. Los volúmenes anónimos se eliminan después
de que finalice la tarea que los utiliza.

#### Crear un servicio que utiliza un directorio del host montado de forma vinculada (bind-mounted)

El siguiente ejemplo monta de forma vinculada (bind-mounts) un directorio del host en `/path/in/container` en
los contenedores que respaldan el servicio:

```console
$ docker service create \
  --name my-service \
  --mount type=bind,source=/path/on/host,destination=/path/in/container \
  nginx:alpine
```

### Establecer el modo de servicio (--mode)

El modo de servicio determina si se trata de un servicio _replicado_ (replicated) o de un servicio _global_
(global). Un servicio replicado ejecuta tantas tareas como se especifiquen, mientras que un servicio global
se ejecuta en cada nodo activo en el swarm.

El siguiente comando crea un servicio global:

```console
$ docker service create \
 --name redis_2 \
 --mode global \
 redis:7.4.1
```

### Especificar restricciones de servicio (--constraint) {#constraint}

Puedes limitar el conjunto de nodos donde se puede planificar una tarea definiendo
expresiones de restricción. Las expresiones de restricción pueden utilizar una regla de
_coincidencia_ (`==`) o de _exclusión_ (`!=`). Múltiples restricciones buscan nodos que cumplan con cada
expresión (coincidencia AND). Las restricciones pueden coincidir con etiquetas del nodo o de Engine como
se detalla a continuación:

| atributo del nodo    | coincide con                   | ejemplo                                       |
|----------------------|--------------------------------|-----------------------------------------------|
| `node.id`            | ID del nodo                    | `node.id==2ivku8v2gvtg4`                      |
| `node.hostname`      | Nombre de host del nodo        | `node.hostname!=node-2`                       |
| `node.role`          | Rol del nodo (`manager`/`worker`) | `node.role==manager`                          |
| `node.platform.os`   | Sistema operativo del nodo     | `node.platform.os==windows`                   |
| `node.platform.arch` | Arquitectura del nodo          | `node.platform.arch==x86_64`                  |
| `node.labels`        | Etiquetas del nodo definidas por el usuario | `node.labels.security==high`                  |
| `engine.labels`      | Etiquetas del demonio de Docker (Docker Engine) | `engine.labels.operatingsystem==ubuntu-24.04` |

Las etiquetas `engine.labels` se aplican a las etiquetas de Docker Engine, como el sistema operativo, los controladores,
etc. Los administradores de Swarm añaden `node.labels` para fines operativos utilizando
el comando [`docker node update`](/reference/cli/docker/node/update/).

Por ejemplo, el siguiente comando limita las tareas del servicio redis a los nodos donde la
etiqueta de tipo de nodo es igual a queue:

```console
$ docker service create \
  --name redis_2 \
  --constraint node.platform.os==linux \
  --constraint node.labels.type==queue \
  redis:7.4.1
```

Si las restricciones del servicio excluyen a todos los nodos del clúster, se muestra un mensaje indicando
que no se ha encontrado ningún nodo adecuado, pero el planificador iniciará un bucle de conciliación
y desplegará el servicio una vez que haya disponible un nodo adecuado.

En el ejemplo de abajo, no se encontró ningún nodo que cumpliera con la restricción, lo que provocó que el
servicio no conciliara con el estado deseado:

```console
$ docker service create \
  --name web \
  --constraint node.labels.region==east \
  nginx:alpine

lx1wrhhpmbbu0wuk0ybws30bc
overall progress: 0 out of 1 tasks
1/1: no suitable node (scheduling constraints not satisfied on 5 nodes)

$ docker service ls
ID                  NAME     MODE         REPLICAS   IMAGE               PORTS
b6lww17hrr4e        web      replicated   0/1        nginx:alpine
```

Después de añadir la etiqueta `region=east` a un nodo del clúster, el servicio
se concilia y se despliega el número deseado de réplicas:

```console
$ docker node update --label-add region=east yswe2dm4c5fdgtsrli1e8ya5l
yswe2dm4c5fdgtsrli1e8ya5l

$ docker service ls
ID                  NAME     MODE         REPLICAS   IMAGE               PORTS
b6lww17hrr4e        web      replicated   1/1        nginx:alpine
```

### Especificar preferencias de ubicación del servicio (--placement-pref) {#placement-pref}

Puedes configurar el servicio para dividir las tareas de manera uniforme entre diferentes categorías de
nodos. Un ejemplo en el que esto puede ser útil es equilibrar las tareas en un conjunto
de centros de datos o zonas de disponibilidad. El siguiente ejemplo ilustra esto:

```console
$ docker service create \
  --replicas 9 \
  --name redis_2 \
  --placement-pref spread=node.labels.datacenter \
  redis:7.4.1
```

Esto utiliza `--placement-pref` con una estrategia de distribución `spread` (actualmente la única
estrategia admitida) para distribuir las tareas de manera uniforme según los valores de la etiqueta
de nodo `datacenter`. En este ejemplo, asumimos que cada nodo tiene una etiqueta de nodo
`datacenter` asignada. Si hay tres valores diferentes para esta etiqueta entre los
nodos del swarm, un tercio de las tareas se ubicará en los nodos
asociados con cada valor. Esto es así incluso si hay más nodos con un
valor que con otro. Por ejemplo, considera el siguiente conjunto de nodos:

- Tres nodos con `node.labels.datacenter=east`
- Dos nodos con `node.labels.datacenter=south`
- Un nodo con `node.labels.datacenter=west`

Dado que estamos distribuyendo sobre los valores de la etiqueta `datacenter` y el
servicio tiene 9 réplicas, terminarán 3 réplicas en cada centro de datos. Hay
tres nodos asociados con el valor `east`, por lo que cada uno recibirá una de las
tres réplicas reservadas para este valor. Hay dos nodos con el valor
`south`, y las tres réplicas para este valor se dividirán entre ellos,
recibiendo uno dos réplicas y el otro solo una. Por último, `west`
tiene un único nodo que recibirá las tres réplicas reservadas para `west`.

Si los nodos de una categoría (por ejemplo, aquellos con
`node.labels.datacenter=south`) no pueden manejar su parte equitativa de tareas debido a
restricciones o limitaciones de recursos, las tareas adicionales se asignarán a otros
nodos en su lugar, si es posible.

Las preferencias de ubicación admiten tanto etiquetas de Engine como etiquetas de nodo. El
ejemplo anterior utiliza una etiqueta de nodo, porque se hace referencia a la etiqueta con
`node.labels.datacenter`. Para distribuir sobre los valores de una etiqueta de Engine, utiliza
`--placement-pref spread=engine.labels.<nombre_etiqueta>`.

Es posible añadir múltiples preferencias de ubicación a un servicio. Esto
establece una jerarquía de preferencias, de modo que las tareas se dividen primero sobre
una categoría y luego se dividen aún más sobre categorías adicionales. Un ejemplo
de dónde puede ser útil esto es dividir las tareas equitativamente entre centros de datos y
luego dividir las tareas dentro de cada centro de datos entre una selección de racks. Para añadir
múltiples preferencias de ubicación, especifica el flag `--placement-pref` varias
veces. El orden es importante, y las preferencias de ubicación se aplicarán
en el orden indicado al tomar las decisiones de planificación.

El siguiente ejemplo configura un servicio con múltiples preferencias de ubicación.
Las tareas se distribuyen primero entre los distintos centros de datos y luego entre los racks
(según lo indican las etiquetas respectivas):

```console
$ docker service create \
  --replicas 9 \
  --name redis_2 \
  --placement-pref 'spread=node.labels.datacenter' \
  --placement-pref 'spread=node.labels.rack' \
  redis:7.4.1
```

Al actualizar un servicio con `docker service update`, `--placement-pref-add`
añade una nueva preferencia de ubicación después de todas las preferencias de ubicación existentes.
`--placement-pref-rm` elimina una preferencia de ubicación existente que coincida con el
argumento.

### Especificar requisitos y restricciones de memoria para un servicio (--reserve-memory y --limit-memory) {#reserve-memory}

Si tu servicio necesita una cantidad mínima de memoria para funcionar correctamente,
puedes utilizar `--reserve-memory` para especificar que el servicio solo se
planifique en un nodo que tenga esta cantidad de memoria disponible para reservar. Si no hay ningún nodo
disponible que cumpla con los criterios, la tarea no se planifica, sino que permanece en estado
pendiente.

El siguiente ejemplo requiere que haya 4 GB de memoria disponibles y reservables
en un nodo determinado antes de planificar la ejecución del servicio en ese nodo.

```console
$ docker service create --reserve-memory=4GB --name=too-big nginx:alpine
```

Los administradores no planificarán un conjunto de contenedores en un solo nodo cuyas reservas combinadas
superen la memoria disponible en ese nodo.

Una vez que una tarea está planificada y ejecutándose, `--reserve-memory` no impone un
límite de memoria. Utiliza `--limit-memory` para asegurar que una tarea no use más de una
cantidad determinada de memoria en un nodo. Este ejemplo limita la cantidad de memoria utilizada
por la tarea a 4 GB. La tarea se planificará incluso si cada uno de tus nodos tiene
solo 2 GB de memoria, porque `--limit-memory` es un límite superior.

```console
$ docker service create --limit-memory=4GB --name=too-big nginx:alpine
```

El uso de `--reserve-memory` y `--limit-memory` no garantiza que Docker
no vaya a utilizar más memoria en tu host de la que deseas. Por ejemplo, podrías
crear muchos servicios, cuya suma de uso de memoria podría agotar la memoria disponible.

Puedes evitar que este escenario agote la memoria disponible teniendo en cuenta también
otro software (no contenedorizado) que se ejecuta en el host. Si
`--reserve-memory` es mayor o igual que `--limit-memory`, Docker no
planificará un servicio en un host que no tenga suficiente memoria. `--limit-memory`
limitará la memoria del servicio para mantenerse dentro de ese límite, por lo que si cada servicio
tiene una reserva y un límite de memoria configurados, los servicios de Docker tendrán menos probabilidades de
saturar el host. Otros contenedores que no son servicios o las aplicaciones que se ejecutan directamente
en el host de Docker aún podrían agotar la memoria.

Esta estrategia tiene un inconveniente. Reservar memoria también significa que podrías
no estar haciendo un uso óptimo de la memoria disponible en el nodo. Considera un servicio
que en circunstancias normales utiliza 100 MB de memoria, pero que dependiendo de la carga puede
tener picos de hasta 500 MB. Reservar 500 MB para ese servicio (para garantizar que pueda disponer de 500 MB
en esos picos) hace que se desperdicien 400 MB de memoria la mayor parte del tiempo.

En resumen, puedes adoptar un enfoque más conservador o más flexible:

- **Conservador**: reservar 500 MB y limitar a 500 MB. Básicamente, ahora estás
  tratando los contenedores de servicio como máquinas virtuales, y podrías estar perdiendo una gran ventaja de los
  contenedores, que es una mayor densidad de servicios por host.

- **Flexible**: limitar a 500 MB en la asunción de que si el servicio requiere
  más de 500 MB, está funcionando mal. Reserva una cantidad intermedia entre el requisito "normal"
  de 100 MB y el requisito de "pico" de 500 MB. Esto asume que cuando
  este servicio esté en su punto máximo, otros servicios o cargas de trabajo no contenedorizadas probablemente
  no lo estarán.

El enfoque que adoptes depende en gran medida de los patrones de uso de memoria de tus
cargas de trabajo. Debes realizar pruebas en condiciones normales y de pico antes de decidirte
por un enfoque.

On Linux, también puedes limitar la huella de memoria general de un servicio en un host determinado
a nivel del sistema operativo del host, utilizando `cgroups` u otras herramientas relevantes
del sistema operativo.

### Especificar el número máximo de réplicas por nodo (--replicas-max-per-node) {#replicas-max-per-node}

Utiliza el flag `--replicas-max-per-node` para establecer el número máximo de tareas réplica que se pueden ejecutar en un nodo.
El siguiente comando crea un servicio nginx con 2 tareas réplica pero solo una tarea réplica por nodo.

Un ejemplo en el que esto puede ser útil es equilibrar las tareas en un conjunto de centros de datos junto con `--placement-pref`
y dejar que el ajuste `--replicas-max-per-node` se asegure de que las réplicas no se migren a otro centro de datos durante
las tareas de mantenimiento o ante un fallo en un centro de datos.

El siguiente ejemplo ilustra esto:

```console
$ docker service create \
  --name nginx \
  --replicas 2 \
  --replicas-max-per-node 1 \
  --placement-pref 'spread=node.labels.datacenter' \
  nginx
```

### Conectar un servicio a una red existente (--network) {#network}

Puedes utilizar redes superpuestas (overlay networks) para conectar uno o más servicios dentro del swarm.

Primero, crea una red superpuesta en un nodo administrador utilizando el comando docker network create:

```console
$ docker network create --driver overlay my-network

etjpu59cykrptrgw0z0hk5snf
```

Después de crear una red superpuesta en el modo swarm, todos los nodos administradores tienen
acceso a la red.

Cuando creas un servicio y pasas el flag `--network` para conectar el servicio a
la red superpuesta:

```console
$ docker service create \
  --replicas 3 \
  --network my-network \
  --name my-web \
  nginx

716thylsndqma81j6kkkb5aus
```

El swarm extiende my-network a cada nodo que ejecuta el servicio.

Los contenedores en la misma red pueden acceder entre sí mediante el
[descubrimiento de servicios](/engine/network/drivers/overlay/#container-discovery).

La sintaxis en formato largo de `--network` permite especificar una lista de alias y opciones del controlador:
`--network name=my-network,alias=web1,driver-opt=field1=value1`

### Publicar puertos de servicio externamente al swarm (-p, --publish) {#publish}

Puedes publicar puertos de servicio para que estén disponibles externamente al swarm
utilizando el flag `--publish`. El flag `--publish` puede tomar dos estilos diferentes
de argumentos. La versión corta es posicional y te permite especificar el
puerto publicado y el puerto de destino separados por dos puntos (`:`).

```console
$ docker service create --name my_web --replicas 3 --publish 8080:80 nginx
```

También existe un formato largo, que es más fácil de leer y te permite especificar
más opciones. Se prefiere el formato largo. No puedes especificar el modo del servicio
cuando utilizas el formato corto. A continuación se muestra un ejemplo del uso del formato largo
para el mismo servicio que el anterior:

```console
$ docker service create --name my_web --replicas 3 --publish published=8080,target=80 nginx
```

Las opciones que puedes especificar son:

<table>
<thead>
<tr>
  <th>Opción</th>
  <th>Sintaxis corta</th>
  <th>Sintaxis larga</th>
  <th>Descripción</th>
</tr>
</thead>
<tr>
  <td>puerto publicado y puerto de destino</td>
  <td><tt>--publish 8080:80</tt></td>
  <td><tt>--publish published=8080,target=80</tt></td>
  <td><p>
    El puerto de destino dentro del contenedor y el puerto al que se asigna en los
    nodos, utilizando la malla de enrutamiento (<tt>ingress</tt>) o redes a nivel de host.
    Hay más opciones disponibles, más adelante en esta tabla. Se prefiere la sintaxis de clave-valor,
    porque se autodocumenta en cierta medida.
  </p></td>
</tr>
<tr>
  <td>modo</td>
  <td>No es posible establecer usando la sintaxis corta.</td>
  <td><tt>--publish published=8080,target=80,mode=host</tt></td>
  <td><p>
    El modo a utilizar para vincular el puerto, ya sea <tt>ingress</tt> o <tt>host</tt>.
    Por defecto es <tt>ingress</tt> para utilizar la malla de enrutamiento.
  </p></td>
</tr>
<tr>
  <td>protocolo</td>
  <td><tt>--publish 8080:80/tcp</tt></td>
  <td><tt>--publish published=8080,target=80,protocol=tcp</tt></td>
  <td><p>
    El protocolo a utilizar, <tt>tcp</tt> , <tt>udp</tt> o <tt>sctp</tt>. Por defecto es
    <tt>tcp</tt>. Para vincular un puerto para ambos protocolos, especifica el flag <tt>-p</tt> o
    <tt>--publish</tt> dos veces.
  </p></td>
</tr>
</table>

Cuando publicas un puerto de servicio usando el modo `ingress`, la malla de enrutamiento de Swarm
hace que el servicio sea accesible en el puerto publicado en cada nodo, independientemente de si
hay una tarea para el servicio ejecutándose en ese nodo. Si utilizas el modo `host`,
el puerto solo se vincula en los nodos donde se ejecuta el servicio, y un puerto determinado
en un nodo solo se puede vincular una vez. Solo puedes establecer el modo de publicación utilizando
la sintaxis larga. Para obtener más información, consulta
[Utilizar la malla de enrutamiento del modo swarm](/engine/swarm/ingress/).

### Proporcionar especificaciones de credenciales para cuentas de servicio administradas (--credentials-spec) {#credentials-spec}

Esta opción solo se utiliza para servicios que emplean contenedores de Windows. La opción
`--credential-spec` debe tener el formato `file://<nombre_archivo>` o
`registry://<nombre_valor>`.

Cuando se utiliza el formato `file://<nombre_archivo>`, el archivo al que se hace referencia debe estar
presente en el subdirectorio `CredentialSpecs` del directorio de datos de docker,
que por defecto es `C:\ProgramData\Docker\` en Windows. Por ejemplo,
especificar `file://spec.json` carga `C:\ProgramData\Docker\CredentialSpecs\spec.json`.

Cuando se utiliza el formato `registry://<nombre_valor>`, la especificación de credenciales se
lee desde el registro de Windows en el host del demonio. El valor de registro especificado
debe estar ubicado en:

    HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\Containers\CredentialSpecs


### Crear servicios utilizando plantillas

Puedes utilizar plantillas para algunos flags de `service create`, utilizando la sintaxis
proporcionada por el paquete [text/template](https://pkg.go.dev/text/template) de Go.

Los flags compatibles son los siguientes:

- `--hostname`
- `--mount`
- `--env`

Los marcadores de posición válidos para la plantilla Go son los siguientes:

<table>
  <tr>
    <th>Marcador de posición</th>
    <th>Descripción</th>
  </tr>
  <tr>
    <td><tt>.Service.ID</tt></td>
    <td>ID del servicio</td>
  </tr>
  <tr>
    <td><tt>.Service.Name</tt></td>
    <td>Nombre del servicio</td>
  </tr>
  <tr>
    <td><tt>.Service.Labels</tt></td>
    <td>Etiquetas del servicio</td>
  </tr>
  <tr>
    <td><tt>.Node.ID</tt></td>
    <td>ID del nodo</td>
  </tr>
  <tr>
    <td><tt>.Node.Hostname</tt></td>
    <td>Nombre de host del nodo</td>
  </tr>
  <tr>
    <td><tt>.Task.ID</tt></td>
    <td>ID de la tarea</td>
  </tr>
  <tr>
    <td><tt>.Task.Name</tt></td>
    <td>Nombre de la tarea</td>
  </tr>
  <tr>
    <td><tt>.Task.Slot</tt></td>
    <td>Ranura (slot) de la tarea</td>
  </tr>
</table>


#### Ejemplo de plantilla

En este ejemplo, vamos a configurar la plantilla de los contenedores creados basándonos en el
nombre del servicio, el ID del nodo y el nombre de host donde se encuentra.

```console
$ docker service create \
    --name hosttempl \
    --hostname="{{.Node.Hostname}}-{{.Node.ID}}-{{.Service.Name}}"\
    busybox top

va8ew30grofhjoychbr6iot8c

$ docker service ps va8ew30grofhjoychbr6iot8c

ID            NAME         IMAGE                                                                                   NODE          DESIRED STATE  CURRENT STATE               ERROR  PORTS
wo41w8hg8qan  hosttempl.1  busybox:latest@sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912  2e7a8a9c4da2  Running        Running about a minute ago

$ docker inspect --format="{{.Config.Hostname}}" 2e7a8a9c4da2-wo41w8hg8qanxwjwsg4kxpprj-hosttempl

x3ti0erg11rjpg64m75kej2mz-hosttempl
```

### Especificar el modo de aislamiento en Windows (--isolation) {#isolation}

Por defecto, las tareas planificadas en nodos de Windows se ejecutan utilizando el modo de aislamiento predeterminado
configurado para ese nodo en particular. Para forzar un modo de aislamiento específico, puedes utilizar
el flag `--isolation`:

```console
$ docker service create --name myservice --isolation=process microsoft/nanoserver
```

Los modos de aislamiento compatibles en Windows son:
- `default`: utiliza los ajustes predeterminados especificados en el nodo que ejecuta la tarea
- `process`: utiliza aislamiento de proceso (solo Windows Server)
- `hyperv`: utiliza aislamiento de Hyper-V

### Crear servicios solicitando recursos genéricos (--generic-resources) {#generic-resources}

Puedes limitar el tipo de nodos en los que puede terminar tu tarea utilizando el
flag `--generic-resource` (si los nodos anuncian estos recursos):

```console
$ docker service create \
    --name cuda \
    --generic-resource "NVIDIA-GPU=2" \
    --generic-resource "SSD=1" \
    nvidia/cuda
```

### Ejecutar como un trabajo (job)

Los trabajos (jobs) son un tipo especial de servicio diseñado para ejecutar una operación hasta su finalización
y luego detenerse, a diferencia de los demonios de ejecución prolongada. Cuando una tarea (Task)
que pertenece a un trabajo finaliza correctamente (valor de retorno 0), la tarea se marca como
"Completada" (Completed) y no se vuelve a ejecutar.

Los trabajos se inician utilizando uno de los dos modos siguientes: `replicated-job` o `global-job`

```console
$ docker service create --name myjob \
                        --mode replicated-job \
                        bash "true"
```

Este comando ejecutará una tarea que, utilizando la imagen `bash`, ejecutará el
comando `true`, el cual devolverá 0 y luego finalizará.

Aunque los trabajos son en última instancia un tipo de servicio diferente, presentan un par de
advertencias en comparación con otros servicios:

- Ninguna de las opciones de configuración de actualización (update) o reversión (rollback) es válida. Los trabajos se pueden
  actualizar, pero no se pueden implementar ni revertir progresivamente, lo que hace que estas opciones de configuración
  sean irrelevantes.
- Los trabajos nunca se reinician al alcanzar el estado `Complete`. Esto significa que,
  para los trabajos, establecer `--restart-condition` en `any` es lo mismo que establecerlo en
  `on-failure`.

Los trabajos están disponibles tanto en modo replicado como global.

#### Trabajos replicados (Replicated Jobs)

Un trabajo replicado es como un servicio replicado. Establecer el flag `--replicas`
especificará el número total de iteraciones de un trabajo a ejecutar.

Por defecto, todas las réplicas de un trabajo replicado se iniciarán a la vez. Para controlar
el número total de réplicas que se ejecutan simultáneamente en cualquier momento dado,
se puede utilizar el flag `--max-concurrent`:

```console
$ docker service create \
    --name mythrottledjob \
    --mode replicated-job \
    --replicas 10 \
    --max-concurrent 2 \
    bash "true"
```

El comando anterior ejecutará 10 tareas en total, pero solo 2 de ellas se
ejecutarán en un momento dado.

#### Global Jobs

Los trabajos globales son como los servicios globales, en el sentido de que se ejecuta una tarea una vez en cada nodo
que cumpla con las restricciones de ubicación. Los trabajos globales están representados por el modo `global-job`.

Ten en cuenta que después de crear un trabajo global, cualquier nodo nuevo que se añada al clúster
tendrá una tarea de ese trabajo iniciada en él. El trabajo global en su conjunto no
tiene un estado de "finalizado", excepto en la medida en que cada nodo que cumple con las
restricciones del trabajo tiene una tarea completada (Completed).



