├── README.md ├── 2-construyendo-imagenes └── README.md ├── 0-bases-de-docker └── README.md ├── 1-corriendo-contenedores └── README.md ├── 3-docker-compose └── README.md ├── 4-docker-swarm └── README.md └── LICENSE /README.md: -------------------------------------------------------------------------------- 1 | # Taller de Docker 2 | 3 | Un taller simple de `docker` para cualquiera que quiera aprender a usar docker efectivamente en sus desarrollos cotidianos. 4 | 5 | Este repo pretende guiarte por las bases, y algunos temas más avanzados como `docker-compose` o el modo swarm. 6 | 7 | Este es, obviamente, un eterno trabajo en construcción; sentite libre de proponer cambios y de compartirlo. 8 | 9 | Arrancá por la sección [`0-bases-de-docker`](https://github.com/mgarciaisaia/docker-workshop/tree/master/0-bases-de-docker). 10 | 11 | 🐳 12 | 13 | # Requisitos 14 | 15 | Necesitás tener `docker 1.12` o superior instalado. Podés [conseguir la última versión estable acá](https://docs.docker.com/engine/installation/). 16 | 17 | Podés seguir este repo casi por completo de manera online con [`play-with-docker`](http://play-with-docker.com). Si necesitás acceder a tus servicios desde afuera, usá el patrón de URLs `http://ip-.play-with-docker.com` (por ejemplo, http://ip10_2_135_3-80.play-with-docker.com/). Tené en cuenta que esas sesiones no son permanentes, y que tu trabajo se borrará después de unas horas. 18 | 19 | # Licencia 20 | 21 | Creative Commons Licence
Este trabajo está licenciado bajo una licencia Creative Commons Atribución/Reconocimiento-CompartirIgual 4.0 Licencia Pública Internacional — CC BY-SA 4.0. 22 | 23 | Usted es libre de: 24 | 25 | * Compartir — copiar y redistribuir el material en cualquier medio o formato 26 | * Adaptar — remezclar, transformar y construir a partir del material 27 | 28 | para cualquier propósito, incluso comercialmente. 29 | 30 | La licenciante no puede revocar estas libertades en tanto usted siga los términos de la licencia. 31 | 32 | # Traducción en español 33 | 34 | Esta traducción en español fue originalmente realizada por [Matías García Isaía](https://github.com/mgarciaisaia/) basada en [la versión `031dfaa2c5e3724334b583a47bda147ec01a7a79` de `docker-workshop`](https://github.com/gvilarino/docker-workshop/tree/031dfaa2c5e3724334b583a47bda147ec01a7a79) de [Guido Vilariño](https://github.com/gvilarino). 35 | -------------------------------------------------------------------------------- /2-construyendo-imagenes/README.md: -------------------------------------------------------------------------------- 1 | # Imágenes _(images)_ 2 | 3 | ## Construyendo _(build)_ imágenes 4 | 5 | Una imagen _(image)_ docker está formada por una o más capas _(layers)_. Cada capa se construye arriba de la anterior, y son todas inmutables. Esto significa que no podés modificar una capa existente; en cambio, creás una nueva con los cambios respecto a la anterior. Esto es similar a como funcionan los diff's de `git`. 6 | 7 | Para construir una imagen, vas a necesitar un `Dockerfile`. Probá el de la aplicación web que estuvimos usando haciendo `git clone` del [repositorio público `gvilarino/docker-testing`](https://github.com/gvilarino/docker-testing). 8 | 9 | En el directorio raíz de ese proyecto, hacé: 10 | 11 | ``` 12 | docker build -t test-image . 13 | ``` 14 | 15 | Yyyy.... ¡Eso es todo! 🐳 16 | 17 | Si la ejecutás e inspeccionás su contenido, vas a ver que es lo mismo que el de `gvilarino/docker-testing`, que incluye los mismos archivos del proyecto git. 18 | 19 | Cada instrucción (`FROM`, `RUN`, etc) en el `Dockerfile` genera una nueva capa inmutable. 20 | 21 | ## Entendiendo las capas y aprovechando la cache 22 | 23 | Notá que si volvés a correr ese mismo comando, no va a tardar nada. Esto es porque docker cachea cada capa y evita reconstruirla si el contexto de construcción y el comando de creación de la capa no cambiaron desde el último build. 24 | 25 | Ahora cambiemos la línea `FROM node:argon` a `FROM node:6` así vemos cómo funciona con la última versión de `node.js`*, y volvamos a buildear. 26 | 27 | Vas a ver que ¡todas las capas vuelven a construirse! Esto es porque cambiaste la capa _base_. Como todas las capas son simplemente un diff sobre la anterior, al cambiar la capa base invalidás el cache para todas las capas siguientes. 28 | 29 | Ahora cambiemos el mensaje de texto en `index.js` y volvamos a buildear. 30 | 31 | Acá podemos ver que la capa base se reusa, pero todo lo demás se vuelve a hacer, incluída la instalación de dependencias. En tu flujo de trabajo cotidiano, no querés reinstalar las dependencias simplemente porque cambiaste un archivo fuente - sólo querrías hacer eso si cambiaste tu `package.json`. Así que cambiemos el `Dockerfile` para aprovechar la cache de capas. 32 | 33 | Cambiá la línea `COPY [".", "/usr/src/"]` a `COPY ["package.json", "/usr/src/"]` 34 | 35 | Agregá un nuevo `COPY [".", "/usr/src/"]` luego de la instrucción `RUN npm install`. 36 | 37 | Ahora volvé a buildear (va a reconstruir todo la primera vez), después volvé a cambiar el texto en `index.js` y volvé a reconstruir la imagen. 38 | 39 | Más rápido, ¿eh? 😎 40 | 41 | Podés publicar esta imagen usando el comando `docker push`, pero para eso vas a necesitar una cuenta en [`hub.docker.com`](https://hub.docker.com); te dejo eso como tarea para después. Por ahora, [apreandamos a usar `docker-compose`](https://github.com/mgarciaisaia/docker-workshop/tree/master/3-docker-compose). 42 | 43 | ------ 44 | 45 | * Sí, la guía original tiene sus años 46 | -------------------------------------------------------------------------------- /0-bases-de-docker/README.md: -------------------------------------------------------------------------------- 1 | # Bases de Docker 2 | 3 | ## Contenedores _(containers)_ 4 | 5 | La parte más fundamental de `Docker` son los *contenedores* ("containers"). Hay mucho para decir sobre ellos, pero por ahora corramos uno: 6 | 7 | ``` 8 | docker run hello-world 9 | ``` 10 | 11 | Fácil, ¿eh? Peguémosle otra mirada a ese contenedor 12 | 13 | ``` 14 | docker ps 15 | ``` 16 | 17 | 🤔 No está... Agreguemos el flag `-a`: 18 | 19 | ``` 20 | docker ps -a 21 | ``` 22 | 23 | 😀 ¡Ahí está! También podemos mirarlo más de cerca con: 24 | 25 | ``` 26 | docker inspect 27 | ``` 28 | 29 | Ahora pongámnos serios. Corramos una versión completa de Ubuntu Linux: 30 | 31 | ``` 32 | docker run ubuntu:18.04 33 | ``` 34 | 35 | (fijate que le especificamos una versión; ya hablaremos de eso) 36 | 37 | 🤔 parece que descargó algo, pero no sé qué... 38 | 39 | ``` 40 | docker ps -a 41 | ``` 42 | 43 | ¿Así que se frena después de ejecutar? Probemos otra cosa: 44 | 45 | ``` 46 | docker run -it ubuntu:18.04 47 | ``` 48 | 49 | Bien, ¡estamos dentro del contenedor! `-it` especifica que querés entrar en modo interactivo (en realidad, `i` es interactivo, y `t` es para que docker reserve una interfaz pseudo TTY para la interacción). 50 | 51 | Después de jugar un rato, ejecutá `exit`. Miremoslo de nuevo: 52 | 53 | ``` 54 | docker ps -a 55 | ``` 56 | 57 | Así que los contenedores trabajan teniendo un único proceso principal que tiene asignado el PID 1, que ejecuta al iniciar el contenedores, y que tan pronto como ese proceso finaliza, el contenedor se frena, incluso si había otros procesos corriendo dentro. 58 | 59 | También podrás haber notado que la primera vez que corriste `docker run ubuntu:18.04` tardó un rato, pero la segunda vez fue inmediata. Lo que ocurre es que docker intentó ejecutar un contenedor basado en la imagen `ubuntu:18.04`, y, como no la tenía localmente, la descargó desde el repositorio público. Lo que nos lleva a hablar de... 60 | 61 | ## Imágenes _(images)_ 62 | 63 | Las _imágenes_ ("images") son las plantillas que docker usa para crear los contenedores. Si te resulta familiar la [programación orientada a objetos](https://es.wikipedia.org/wiki/Programaci%C3%B3n_orientada_a_objetos), podés más o menos pensar a las imágenes como _clases_, y a los contenedores como _instancias_. 64 | 65 | Fijate qué imágenes tenés en tu repositorio local ejecutando esto: 66 | 67 | ``` 68 | docker images 69 | ``` 70 | 71 | Consigamos otra imagen: 72 | 73 | ``` 74 | docker pull mongo 75 | ``` 76 | 77 | Este último comando _bajó_ ("pull") una imagen llamada `mongo` del [repositorio público de docker](https://hub.docker.com) a tu repositorio local. Esto es muy similar a lo que conseguís cuando hacés `git pull` desde un repositorio `git` público. 78 | 79 | ¡Bien! Así que ahora tenemos una imagen de la que no creamos ningún contenedor. 80 | 81 | Esto es un buen resumen de las bases. Vayamos a [la próxima sección](https://github.com/mgarciaisaia/docker-workshop/tree/master/1-corriendo-contenedores). 82 | -------------------------------------------------------------------------------- /1-corriendo-contenedores/README.md: -------------------------------------------------------------------------------- 1 | # Contenedores 2 | 3 | ## Corriendo, soltando _(detaching)_ y conectándose _(attaching)_ a contenedores 4 | 5 | ¡Corramos una base de datos Mongo! Y con un nombre bonito. 6 | 7 | ``` 8 | docker run --name db mongo 9 | ``` 10 | 11 | 🤔 Pero no me quiero quedar conectado a su salida estándar... Démosle CTRL+C para salir, y después borremos ese contenedor. 12 | 13 | ``` 14 | docker rm db 15 | ``` 16 | 17 | Ahora corramos un nuevo contenedor de Mongo, pero en segundo plano (en _background_), con el modificador `-d` (`d` de `detach`, despegarse, soltar). 18 | 19 | ``` 20 | docker run --name db -d mongo 21 | ``` 22 | 23 | ¡Bien! Ahora revisemos la base de datos. Primero necesitamos hacer algo así como un `ssh` a dentro del contenedor. Pero no usamos _realmente_ `ssh`, si no que podemos usar `execute` para ejecutar un comando en el contenedor en modo interactivo. Algo así: 24 | 25 | ``` 26 | docker exec -it db mongo 27 | ``` 28 | 29 | Podés interpretar este comando como "Hey, `docker`, ejecutame (`exec`) el comando `mongo` dentro del contenedor llamado `db`, y hacelo de modo interactivo (`-it`) para poder conectarle mi entrada y salida estándar (`STDIN` y `STDOUT`)". 30 | 31 | Ahora simplemente estás corriendo el comando `mongo` en el contenedor `db`. Jugá un rato, y después dale CTRL+C para salir. 32 | 33 | Si ahora hacés `docker ps`, vas a notar que el contenedor `db` sigue ejecutando. No frenó, porque el proceso principal (el proceso `mongo` de la base de datos, con `pid 1`) sigue ejecutando. El proceso que mataste al salir de la sesión fue simplemente la consola de Mongo que ejecutaste al hacer `docker exec`. 34 | 35 | Ahora conectémonos a él desde _otro_ contenedor. 36 | 37 | ``` 38 | docker pull gvilarino/docker-testing 39 | ``` 40 | 41 | Esto te va a descargar una aplicación `node.js` muy simple que intenta conectarse a una base de datos Mongo e informa si lo logra (podés mirar el código [acá](https://github.com/gvilarino/docker-testing)). Cuando termine de descargar, simplemente hacé: 42 | 43 | ``` 44 | docker run -d --name app gvilarino/docker-testing 45 | ``` 46 | 47 | Ahora fijate si hizo algo: 48 | 49 | ``` 50 | docker logs app 51 | ``` 52 | 53 | Parece que la aplicación está escuchando en el puerto 3000. Naveguemos a `localhost:3000` 54 | 55 | 🤔 No logra conectarse a la aplicación... Miremos más de cerca: 56 | 57 | ``` 58 | docker ps -a 59 | ``` 60 | 61 | Como podés ver bajo `PORTS` (puertos), parece que la app _está_ escuchando en el puerto 3000, pero... 😮 ¡Claro! ¡Ese es el puerto _interno_ del contenedor! Lo que necesitás es _vincular_ ("bind") el puerto del contenedor a un puerto en nuestra máquina. Así que, eliminá este contenedor de la app con `docker rm -f app` y creemos uno nuevo como corresponde. 62 | 63 | ``` 64 | docker run -d --name app -p 3000:3000 gvilarino/docker-testing 65 | ``` 66 | 67 | Ahora revisá `localhost:3000` otra vez. 68 | 69 | Bien, parece que pudimos llegar hasta ahí, pero también parece que la app no está llegando a conectarse a la DB. Si te conectás al contenedor de la app (con `docker exec`) y revisás el archivo `index.js`, vas a notar que está intentando conectarse a un equipo llamado `db`. Nuestro contenedor de la base de datos tiene exactamente ese mismo nombre. ¿Por qué no está llegando, entonces? 70 | 71 | ## Redes docker _(networks)_ 72 | 73 | Para que un contenedor sea visible a otro, ambos deben pertenecer a la misma red _(network)_. Las redes Docker son redes privadas virtuales que Docker usa para conectar a los contenedores de manera segura y privada, como si fueran equipos reales en una red física y real. 74 | 75 | Creemos una red simple: 76 | 77 | ``` 78 | docker network create app-network 79 | ``` 80 | 81 | Ahora revisémosla: 82 | 83 | ``` 84 | docker network ls 85 | ``` 86 | 87 | Parece que todo está en orden. Conectemos nuestros contenedores a esa red. 88 | 89 | ``` 90 | docker network connect app-network db 91 | docker network connect app-network app 92 | ``` 93 | 94 | Ahora revisá `localhost:3000` una vez más. 95 | 96 | 😎🐳 97 | 98 | Bien, ya estamos en condiciones de [aprender a trabajar con imágenes]() 99 | Ok, now you're ready to [learn how to work with images](https://github.com/mgarciaisaia/docker-workshop/tree/master/2-construyendo-imagenes). 100 | -------------------------------------------------------------------------------- /3-docker-compose/README.md: -------------------------------------------------------------------------------- 1 | # Docker compose 2 | 3 | Si bien docker te permite construir y conectar fácilmente distintas aplicaciones con entornos y _runtimes_ diferentes, hacerlo con más de dos o tres contenedores se vuelve tedioso. `docker-compose` te permite trabajar con un sistema de contenedores complejo de manera sencilla. 4 | 5 | Primero fijate que tengas `docker-compose` instalado (es probable) haciendo: 6 | 7 | ``` 8 | docker-compose --version 9 | ``` 10 | 11 | Si eso falla, [instalate el `docker-compose` para tu plataforma](https://docs.docker.com/compose/install/) 12 | 13 | Para trabajar con `docker-compose` vas a necesitar un archivo `docker-compose.yml`. Fijate que el que está en el [repo `gvilarino/docker-testing`](https://github.com/gvilarino/docker-testing). 14 | 15 | Asegurate de no estar corriendo ningún contenedor. Luego, desde el directorio ráiz del proyecto, ejecutá: 16 | 17 | ``` 18 | docker-compose up -d 19 | ``` 20 | 21 | ¡Magia! ✨🐳 22 | 23 | Lo que acaba de ocurrir es que docker creó todos los contenedores necesarios para el sistema, los conectó correctamente en una red y les vinculó todos los puertos necesarios. 24 | 25 | ``` 26 | docker-compose ps 27 | ``` 28 | 29 | Acá podés ver una variante más simple de `docker ps`, basada en los elementos que describiste en el `docker-compose.yml`. Cada uno de esos elementos se llama _servicios_ _(services)_. 30 | 31 | Comparalo con `docker ps`. Se parecen, ¿no? La diferencia es que los nombres de los contenedores se generan como instancias del servicio, pero el servicio en sí mismo es un concepto propio de `docker-compose`. 32 | 33 | Navegá a `localhost:3000` y vas a ver una página familiar. 34 | 35 | ## Servicios _(services)_ 36 | 37 | Un servicio es el componente fundamental de docker-compose. Es una especificación sobre cómo queres que corran los contenedores de ese servicio a través de `docker-compose`. 38 | 39 | La propiedad `depends_on` _("depende de")_ indica qué servicios deberían iniciarse antes de iniciar el que tiene esa propiedad. Esto ayuda a indicar la precedencia de servicios. 40 | 41 | También podés especificar valores de las variables de entorno con la propiedad `environment` _("entorno")_. 42 | 43 | Cambiá el valor de `MONGO_URL` a `mongodb://foo/test`. 44 | 45 | Navegá a `localhost:3000`. Vas a ver que nada cambió... ¡Porque tenés que recrear el contenedor! 46 | 47 | ``` 48 | docker-compose up -d 49 | ``` 50 | 51 | Vas a ver que el servicio `app` se re-crea y, si volvés a navegar a `localhost:3000`, vas a ver el mensaje de error. 52 | 53 | ## `docker-compose` como una herramienta de desarrollo 54 | 55 | Digamos que querés usar esta configuración para trabajar, así que necesitás una forma de probar los cambios de tu código usando compose. Empecemos construyendo tu propia imagen *con* compose: 56 | 57 | Borrá la propiedad `image` del servicio `app` y agregá esta otra: 58 | 59 | ``` 60 | build: . 61 | ``` 62 | 63 | Esto le dice a docker-compose dónde buscar un contexto de construcción de imágen para ese servicio. Ahora: 64 | 65 | ``` 66 | docker-compose build 67 | ``` 68 | 69 | Vas a ver unos mensajes familiares. Cuando termine, hacé: 70 | 71 | ``` 72 | docker images 73 | ``` 74 | 75 | Fijate cómo se creó una imagen nueva con un nombre generado. Podés usar esta imagen como cualquier otra y correr un contenedor haciendo `docker run`, pero por ahora hagamos: 76 | 77 | ``` 78 | docker-compose up -d 79 | ``` 80 | 81 | Los servicios se re-crearon usando la nueva imagen. 82 | 83 | Esto nos permite aprovechar la cache de capas en cada re-construcción, y podés hacer `docker-compose build` para cada cambio que hacés en el código... un espanto 😩 84 | 85 | Para que tu flujo de trabajo sea rápido, necesitás poder re-crear los contenedores de los servicios con contenido nuevo sin re-construir toda la imagen. Así que en lugar de re-construir la imagen, vas a re-crear el contenedor del servicio si hay cambios en los archivos fuente. Para eso, tenés que _montar_ _(mount)_ el sistema de archivos local sobre los contenedor, así: 86 | 87 | En la sección `app:` del archivo `docker-compose.yml` agregá: 88 | 89 | ``` 90 | volumes: 91 | - .:/usr/src 92 | - /usr/src/node_modules 93 | ``` 94 | 95 | Así es como se montan los archivos fuente en el contenedor. Excluímos _específicamente_ el directorio `node_modules` porque no queremos sobreescribirlo si llegara a haber un directorio `node_modules` en la máquina host. 96 | 97 | Ahora hacé un cambio en el `index.js` y hacé `docker-compose up -d`. Vas a ver cómo el contenedor del servicio se re-crea con los nuevos archivos fuente sin tener que re-construir toda la imagen. 98 | 99 | Ahora pongámonos seri@s, y [liberemos al enjambre](https://github.com/mgarciaisaia/docker-workshop/tree/master/4-docker-swarm)*. 100 | 101 | ------------ 102 | 103 | * La frase original era _unleash the swarm_, donde "unleash" es algo así como _liberar todo el potencial de_, y `Docker Swarm` es la tecnología que permite manejar grupos de servidores (un "enjambre"), pero no encontré forma de traducir esta expresión sin que pierda el 80% de su significado. 104 | -------------------------------------------------------------------------------- /4-docker-swarm/README.md: -------------------------------------------------------------------------------- 1 | # Docker swarm 2 | 3 | El modo enjambre _(Swarm)_ de Docker te permite trabajar en serio con ambientes docker de gran escala y alta disponibilidad. Básicamente te permite manejar un clúster de máquinas como si fuera un único daemon de docker, con reemplazo de fallos _(failover)_ automático, planificación de contenedores, ruteo y otro montón de bondades. 4 | 5 | Esta última sección te guiará en la creación de un clúster simple de Swarm y en los conceptos básicos. Sí notá que entender Docker Swarm en su totalidad está _muy_ fuera del alcance de esta guía. En cualquier caso, vayamos al grano. 6 | 7 | ## Conseguir algunos nodos 8 | 9 | Para tener un enjambre de docker, primero necesitás un clúster de máquinas, para lo que necesitás máquinas. La forma más rápida y piola de conseguirlo es usando [`play-with-docker`](http://play-with-docker.com/) para probarlo en línea. Si preferís probarlo localmente, vas a necesitar [`docker-machine`](https://docs.docker.com/machine/) y [`Virtualbox`](https://www.virtualbox.org/). Si estás corriendo `Docker for Mac` o `Docker for Windows`, probablemente ya lo tengas instalado; en Linux vas a tener que instalar `docker-machine` por separado. 10 | 11 | La principal diferncia es cuánto te va a llevar tener el enjambre listo. Si sólo querés hacer alguna prueba rápida, probablemente quieras usar la versión online. Si querés tener un enjambre persistente o probar alguna cosa extra, andá por el camino de ejecutar localmente (ojo que puede requerir bastantes recursos). 12 | 13 | Elegí tu propio veneno y andá por alguno de estos dos: 14 | 15 | #### Arenero _(sandbox)_ en línea 16 | 17 | Navegá a [`play-with-docker`](http://play-with-docker.com/) y creá tres nodos usando el botón "+ ADD NEW INSTANCE" _(Agregar nueva instancia)_. 18 | 19 | Saltá a [la próxima sección](https://github.com/mgarciaisaia/docker-workshop/tree/master/4-docker-swarm#enjambrate). 20 | 21 | #### Enjambre local 22 | 23 | Asegurate de tener `docker-machine` instalado, ejecutando: 24 | 25 | ``` 26 | docker-machine --version 27 | ``` 28 | 29 | Empezá creando el nodo maestro del clúster: 30 | 31 | ``` 32 | docker-machine create -d virtualbox manager 33 | ``` 34 | 35 | Eso creó un nodo administrador. Podés entrar por `ssh` si querés: 36 | 37 | ``` 38 | docker-machine ssh manager 39 | ``` 40 | 41 | Piola, ¿eh? Ahora dale `exit` y creemos algunos nodos trabajadores _(workers)_. 42 | 43 | ``` 44 | docker-machine create -d virtualbox worker1 45 | docker-machine create -d virtualbox worker2 46 | ``` 47 | 48 | Ahora necesitás hablarle al daemon de docker en el nodo administrador. Podrías hacerlo entrando por `ssh`, pero hagámoslo desde afuera, que se parece más a cómo querrías hacerlo en el mundo real. 49 | 50 | La forma rápida de hacerlo es ejecutando: 51 | 52 | ``` 53 | eval $(docker-machine env manager) 54 | ``` 55 | 56 | Este comando escribe unas variables de entorno que le indican a tu cliente docker dónde y cómo encontrar al daemon docker con el que querés que se comunique. Fijate cuáles son esas variables haciendo: 57 | 58 | ``` 59 | env | grep DOCKER 60 | ``` 61 | 62 | Notá que cada comando que le pidas a docker que corra va a ejecutarse en el dameon docker del nodo administrador, por lo que si hacés `docker images` o `docker ps` no vas a ver las cosas con las que estuvimos trabajando hasta ahora, porque ya no estás hablando con tu dameon docker local. 63 | 64 | Para volver a trabajar con tu daemon local podés abrir una nueva terminal o hacerle `unset` a esas variables de entorno. 65 | 66 | ### Enjambrate* 67 | 68 | Arranquemos con este enjambre. Conseguite la IP del nodo administrador. En `play-with-docker` la vas a ver en el prompt de la terminal del nodo; si estás ejecutando de manera local con `docker-machine`, suele ser `192.168.99.100`. 69 | 70 | ``` 71 | docker swarm init --advertise-addr 72 | ``` 73 | 74 | Esto configura al daemon docker del nodo en modo swarm, e imprime el comando `swarm join` _(unirse al enjambre)_ que vas a necesitar para que otros nodos se unan a este enjambre. Copialo al portapapeles, que lo vas a necesitar pronto. 75 | 76 | Verificá el estado del enjambre haciendo: 77 | 78 | ``` 79 | docker info 80 | ``` 81 | 82 | Podés ver el estado del enjambre debajo de `Swarm`. 83 | 84 | Mirá los nodos del enjambre con: 85 | 86 | ``` 87 | docker node ls 88 | ``` 89 | 90 | Ahora hagamos que ambos nodos trabajadores se unan al clúster del enjambre: corré el comando que acabás de copiar al portapapeles dentro de cada uno de los nodos trabajadores (si estás ejecutando localmente, metete a los workers con `docker-machine ssh` y después hacé `exit` para volver a tu terminal). 91 | 92 | Fijate que ahora tu enjambre tiene 3 nodos: 93 | 94 | ``` 95 | docker node ls 96 | ``` 97 | 98 | Ya tenés un clúster de 3 nodos actuando como enjambre 😎 99 | 100 | ## Servicios 101 | 102 | Docker swarm trabaja con el concepto de servicios, como `docker-compose`. Creemos un servicio simple que haga ping a `docker.com`. 103 | 104 | ``` 105 | docker service create --name pinger --replicas 1 alpine ping docker.com 106 | ``` 107 | 108 | Veamos algo de información del servicio haciendo: 109 | 110 | ``` 111 | docker service inspect --pretty pinger 112 | ``` 113 | 114 | Verifiquemos su estado haciendo: 115 | 116 | ``` 117 | docker service ps pinger 118 | ``` 119 | 120 | Podés ver en qué nodo está ejecutando. Ahora, escalemos el servicio poniéndole más réplicas (cada réplica es un contendor): 121 | 122 | ``` 123 | docker service scale pinger=5 124 | ``` 125 | 126 | Si ahora hacés `docker service ps pinger` vas a ver en qué nodos están ejecutando las nuevas réplicas. 127 | 128 | ¡Ya tenés un enjambre docker local completo! 129 | 130 | Ahora matemos uno de los nodos trabajadores y veamos cómo docker re-planifica sus contenedores: en `play-with-docker` simplemente tocá el botón "Delete" _(eliminar)_ de cualquiera de los nodos trabajadores. Si estás ejecutando localmente, hacé `docker-machine rm worker2`. 131 | 132 | Ahora hacé `docker service ps pinger` repetidamente para ver cómo van apareciendo en los otros nodos automáticamente. ¿Copado, eh? 133 | 134 | Ya tenés una aplicación resiliente y distribuída corriendo en un clúster de docker swarm ✨ 135 | 136 | ## Palabras finales 137 | 138 | Estos son sólamente los conceptos básicos de docker: vas a aprender mucho más tratando con casos reales, así que _a hackearla se ha dicho_. 139 | 140 | Con algo de suerte este repo te ayude a [investigar más por tu cuenta](https://docs.docker.com) y tener a docker como parte de tu caja de herramientas de desarrollo y procesos de producción. 141 | 142 | Sentite libre de actualizar/corregir cualquier cosa que veas mejorable en este repo, y si te gustó, difundilo. 143 | 144 | ¡Gracias por leer! 🙇 145 | 146 | --------- 147 | 148 | * El título original de la sección era `Get swarmin'`, que es un tipo de expresión en inglés para indicar _"metete en la cosa"_, para distintos valores de "la cosa". Qué se yo 🤷‍ 149 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Atribución/Reconocimiento-CompartirIgual 4.0 Licencia Pública Internacional — CC BY-SA 4.0 2 | 3 | Al ejercer los Derechos Licenciados (definidos a continuación), Usted acepta y acuerda estar obligado por los términos y condiciones de esta Licencia Internacional Pública de Atribución/Reconocimiento-CompartirIgual 4.0 de Creative Commons ("Licencia Pública"). En la medida en que esta Licencia Pública pueda ser interpretada como un contrato, a Usted se le otorgan los Derechos Licenciados en consideración a su aceptación de estos términos y condiciones, y el Licenciante le concede a Usted tales derechos en consideración a los beneficios que el Licenciante recibe por poner a disposición el Material Licenciado bajo estos términos y condiciones. 4 | 5 | Sección 1 – Definiciones. 6 | 7 | Material Adaptado es aquel material protegido por Derechos de Autor y Derechos Similares que se deriva o se crea en base al Material Licenciado y en el cual el Material Licenciado se traduce, altera, arregla, transforma o modifica de manera tal que dicho resultado sea de aquellos que requieran autorización de acuerdo con los Derechos de Autor y Derechos Similares que ostenta el Licenciante. A los efectos de esta Licencia Pública, cuando el Material Licenciado se trate de una obra musical, una interpretación o una grabación sonora, la sincronización temporal de este material con una imagen en movimiento siempre producirá Material Adaptado. 8 | Licencia de adaptador es aquella licencia que Usted aplica a Sus Derechos de Autor y Derechos Similares en Sus contribuciones consideradas como Material Adaptado de acuerdo con los términos y condiciones de esta Licencia Pública. 9 | Una Licencia Compatible con BY-SA es aquella que aparece en la lista disponible en creativecommons.org/compatiblelicenses, aprobada por Creative Commons, como una licencia esencialmente equivalente a esta Licencia Pública. 10 | Derechos de Autor y Derechos Similares son todos aquellos derechos estrechamente vinculados a los derechos de autor, incluidos, de manera enunciativa y no taxativa, los derechos sobre las interpretaciones, las emisiones, las grabaciones sonoras y los Derechos "Sui Generis" sobre Bases de Datos, sin importar cómo estos derechos se encuentren enunciados o categorizados. A los efectos de esta Licencia Pública, los derechos especificados en las secciones 2(b)(1)-(2) no se consideran Derechos de Autor y Derechos Similares. 11 | Medidas Tecnológicas Efectivas son aquellas medidas que, en ausencia de la debida autorización, no pueden ser eludidas en virtud de las leyes que cumplen las obligaciones del artículo 11 del Tratado de la OMPI sobre Derecho de Autor adoptado el 20 de diciembre de 1996, y/o acuerdos internacionales similares. 12 | Excepciones y Limitaciones son el uso justo (fair use), el trato justo (fair dealing) y/o cualquier otra excepción o limitación a los Derechos de Autor y Derechos Similares que se apliquen al uso el Material Licenciado. 13 | Elementos de la Licencia son los atributos que figuran en el nombre de la Licencia Pública de Creative Commons. Los Elementos de la Licencia de esta Licencia Pública son Atribución/Reconocimiento y CompartirIgual. 14 | Material Licenciado es obra artística o literaria, base de datos o cualquier otro material al cual el Licenciante aplicó esta Licencia Pública. 15 | Derechos Licenciados son derechos otorgados a Usted bajo los términos y condiciones de esta Licencia Pública, los cuales se limitan a todos los Derechos de Autor y Derechos Similares que apliquen al uso del Material Licenciado y que el Licenciante tiene potestad legal para licenciar. 16 | Licenciante es el individuo(s) o la entidad(es) que concede derechos bajo esta Licencia Pública. 17 | Compartir significa proporcionar material al público por cualquier medio o procedimiento que requiera permiso conforme a los Derechos Licenciados, tales como la reproducción, exhibición pública, presentación pública, distribución, difusión, comunicación o importación, así como también su puesta a disposición, incluyendo formas en que el público pueda acceder al material desde un lugar y momento elegido individualmente por ellos. 18 | Derechos "Sui Generis" sobre Bases de Datos son aquellos derechos diferentes a los derechos de autor, resultantes de la Directiva 96/9/EC del Parlamento Europeo y del Consejo, de 11 de marzo de 1996 sobre la protección jurídica de las bases de datos, en sus versiones modificadas y/o posteriores, así como otros derechos esencialmente equivalentes en cualquier otra parte del mundo. 19 | Usted es el individuo o la entidad que ejerce los Derechos Licenciados en esta Licencia Pública. La palabra Su tiene un significado equivalente. 20 | 21 | Sección 2 – Ámbito de Aplicación. 22 | 23 | Otorgamiento de la licencia. 24 | Sujeto a los términos y condiciones de esta Licencia Pública, el Licenciante le otorga a Usted una licencia de carácter global, gratuita, no transferible a terceros, no exclusiva e irrevocable para ejercer los Derechos Licenciados sobre el Material Licenciado para: 25 | reproducir y Compartir el Material Licenciado, en su totalidad o en parte; y 26 | producir, reproducir y Compartir Material Adaptado. 27 | Excepciones y Limitaciones. Para evitar cualquier duda, donde se apliquen Excepciones y Limitaciones al uso del Material Licenciado, esta Licencia Pública no será aplicable, y Usted no tendrá necesidad de cumplir con sus términos y condiciones. 28 | Vigencia. La vigencia de esta Licencia Pública está especificada en la sección 6(a). 29 | Medios y formatos; modificaciones técnicas permitidas. El Licenciante le autoriza a Usted a ejercer los Derechos Licenciados en todos los medios y formatos, actualmente conocidos o por crearse en el futuro, y a realizar las modificaciones técnicas necesarias para ello. El Licenciante renuncia y/o se compromete a no hacer valer cualquier derecho o potestad para prohibirle a Usted realizar las modificaciones técnicas necesarias para ejercer los Derechos Licenciados, incluyendo las modificaciones técnicas necesarias para eludir las Medidas Tecnológicas Efectivas. A los efectos de esta Licencia Pública, la mera realización de modificaciones autorizadas por esta sección 2(a)(4) nunca produce Material Adaptado. 30 | Receptores posteriores. 31 | Oferta del Licenciante – Material Licenciado. Cada receptor de Material Licenciado recibe automáticamente una oferta del Licenciante para ejercer los Derechos Licenciados bajo los términos y condiciones de esta Licencia Pública. 32 | Oferta adicional por parte del Licenciante – Material Adaptado. Cada receptor del Material Adaptado por Usted recibe automáticamente una oferta del Licenciante para ejercer los Derechos Licenciados en el Material Adaptado bajo las condiciones de la Licencia del Adaptador que Usted aplique. 33 | Sin restricciones a receptores posteriores. Usted no puede ofrecer o imponer ningún término ni condición diferente o adicional, ni puede aplicar ninguna Medida Tecnológica Efectiva al Material Licenciado si haciéndolo restringe el ejercicio de los Derechos Licenciados a cualquier receptor del Material Licenciado. 34 | Sin endoso. Nada de lo contenido en esta Licencia Pública constituye o puede interpretarse como un permiso para afirmar o implicar que Usted, o que Su uso del Material Licenciado, está conectado, patrocinado, respaldado o reconocido con estatus oficial por el Licenciante u otros designados para recibir la Atribución/Reconocimiento según lo dispuesto en la sección 3(a)(1)(A)(i). 35 | 36 | Otros derechos. 37 | Los derechos morales, tales como el derecho a la integridad, no están comprendidos bajo esta Licencia Pública ni tampoco los derechos de publicidad y privacidad ni otros derechos personales similares. Sin embargo, en la medida de lo posible, el Licenciante renuncia y/o se compromete a no hacer valer ninguno de estos derechos que ostenta como Licenciante, limitándose a lo necesario para que Usted pueda ejercer los Derechos Licenciados, pero no de otra manera. 38 | Los derechos de patentes y marcas no son objeto de esta Licencia Pública. 39 | En la medida de lo posible, el Licenciante renuncia al derecho de cobrarle regalías a Usted por el ejercicio de los Derechos Licenciados, ya sea directamente o a través de una entidad de gestión colectiva bajo cualquier esquema de licenciamiento voluntario, renunciable o no renunciable. En todos los demás casos, el Licenciante se reserva expresamente cualquier derecho de cobrar esas regalías. 40 | 41 | Sección 3 – Condiciones de la Licencia. 42 | 43 | Su ejercicio de los Derechos Licenciados está expresamente sujeto a las condiciones siguientes. 44 | 45 | Atribución/Reconocimiento. 46 | 47 | Si Usted comparte el Material Licenciado (incluyendo en forma modificada), Usted debe: 48 | Conservar lo siguiente si es facilitado por el Licenciante con el Material Licenciado: 49 | identificación del creador o los creadores del Material Licenciado y de cualquier otra persona designada para recibir Atribución/Reconocimiento, de cualquier manera razonable solicitada por el Licenciante (incluyendo por seudónimo si este ha sido designado); 50 | un aviso sobre derecho de autor; 51 | un aviso que se refiera a esta Licencia Pública; 52 | un aviso que se refiera a la limitación de garantías; 53 | un URI o un hipervínculo al Material Licenciado en la medida razonablemente posible; 54 | Indicar si Usted modificó el Material Licenciado y conservar una indicación de las modificaciones anteriores; e 55 | Indicar que el Material Licenciado está bajo esta Licencia Pública, e incluir el texto, el URI o el hipervínculo a esta Licencia Pública. 56 | Usted puede satisfacer las condiciones de la sección 3(a)(1) de cualquier forma razonable según el medio, las maneras y el contexto en los cuales Usted Comparta el Material Licenciado. Por ejemplo, puede ser razonable satisfacer las condiciones facilitando un URI o un hipervínculo a un recurso que incluya la información requerida. 57 | Bajo requerimiento del Licenciante, Usted debe eliminar cualquier información requerida por la sección 3(a)(1)(A) en la medida razonablemente posible. 58 | CompartirIgual. 59 | 60 | Además de las condiciones de la sección 3(a), si Usted Comparte Material Adaptado producido por Usted, también aplican las condiciones siguientes. 61 | La Licencia del Adaptador que Usted aplique debe ser una licencia de Creative Commons con los mismos Elementos de la Licencia, ya sea de esta versión o una posterior, o una Licencia Compatible con la BY-SA. 62 | Usted debe incluir el texto, el URI o el hipervínculo a la Licencia del Adaptador que aplique. Usted puede satisfacer esta condición de cualquier forma razonable según el medio, las maneras y el contexto en los cuales Usted Comparta el Material Adaptado. 63 | Usted no puede ofrecer o imponer ningún término o condición adicional o diferente, o aplicar ninguna Medida Tecnológica Efectiva al Material Adaptado que restrinja el ejercicio de los derechos concedidos en virtud de la Licencia de Adaptador que Usted aplique. 64 | 65 | Sección 4 – Derechos "Sui Generis" sobre Bases de Datos. 66 | 67 | Cuando los Derechos Licenciados incluyan Derechos "Sui Generis" sobre Bases de Datos que apliquen a Su uso del Material Licenciado: 68 | 69 | para evitar cualquier duda, la sección 2(a)(1) le concede a Usted el derecho a extraer, reutilizar, reproducir y Compartir todo o una parte sustancial de los contenidos de la base de datos; 70 | si Usted incluye la totalidad o una parte sustancial del contenido de una base de datos en otra sobre la cual Usted ostenta Derecho "Sui Generis" sobre Bases de Datos, entonces ella (pero no sus contenidos individuales) se entenderá como Material Adaptado para efectos de la sección 3(b); y 71 | Usted debe cumplir con las condiciones de la sección 3(a) si Usted Comparte la totalidad o una parte sustancial de los contenidos de la base de datos. 72 | 73 | Para evitar dudas, esta sección 4 complementa y no sustituye Sus obligaciones bajo esta Licencia Pública cuando los Derechos Licenciados incluyen otros Derechos de Autor y Derechos Similares. 74 | 75 | Sección 5 – Exención de Garantías y Limitación de Responsabilidad. 76 | 77 | Salvo que el Licenciante se haya comprometido mediante un acuerdo por separado, en la medida de lo posible el Licenciante ofrece el Material Licenciado tal como es y tal como está disponible y no se hace responsable ni ofrece garantías de ningún tipo respecto al Material Licenciado, ya sea de manera expresa, implícita, legal u otra. Esto incluye, de manera no taxativa, las garantías de título, comerciabilidad, idoneidad para un propósito en particular, no infracción, ausencia de vicios ocultos u otros defectos, la exactitud, la presencia o la ausencia de errores, sean o no conocidos o detectables. Cuando no se permita, totalmente o en parte, la declaración de ausencia de garantías, a Usted puede no aplicársele esta exclusión. 78 | En la medida de lo posible, en ningún caso el Licenciante será responsable ante Usted por ninguna teoría legal (incluyendo, de manera no taxativa, la negligencia) o de otra manera por cualquier pérdida, coste, gasto o daño directo, especial, indirecto, incidental, consecuente, punitivo, ejemplar u otro que surja de esta Licencia Pública o del uso del Material Licenciado, incluso cuando el Licenciante haya sido advertido de la posibilidad de tales pérdidas, costes, gastos o daños. Cuando no se permita la limitación de responsabilidad, ya sea totalmente o en parte, a Usted puede no aplicársele esta limitación. 79 | 80 | La renuncia de garantías y la limitación de responsabilidad descritas anteriormente deberán ser interpretadas, en la medida de lo posible, como lo más próximo a una exención y renuncia absoluta a todo tipo de responsabilidad. 81 | 82 | Sección 6 – Vigencia y Terminación. 83 | 84 | Esta Licencia Pública tiene una vigencia de aplicación igual al plazo de protección de los Derechos de Autor y Derechos Similares licenciados aquí. Sin embargo, si Usted incumple las condiciones de esta Licencia Pública, los derechos que se le conceden mediante esta Licencia Pública terminan automáticamente. 85 | 86 | En aquellos casos en que Su derecho a utilizar el Material Licenciado se haya terminado conforme a la sección 6(a), este será restablecido: 87 | automáticamente a partir de la fecha en que la violación sea subsanada, siempre y cuando esta se subsane dentro de los 30 días siguientes a partir de Su descubrimiento de la violación; o 88 | tras el restablecimiento expreso por parte del Licenciante. 89 | Para evitar dudas, esta sección 6(b) no afecta ningún derecho que pueda tener el Licenciante a buscar resarcimiento por Sus violaciones de esta Licencia Pública. 90 | Para evitar dudas, el Licenciante también puede ofrecer el Material Licenciado bajo términos o condiciones diferentes, o dejar de distribuir el Material Licenciado en cualquier momento; sin embargo, hacer esto no pondrá fin a esta Licencia Pública. 91 | Las secciones 1, 5, 6, 7, y 8 permanecerán vigentes a la terminación de esta Licencia Pública. 92 | 93 | Sección 7 – Otros Términos y Condiciones. 94 | 95 | El Licenciante no estará obligado por ningún término o condición adicional o diferente que Usted le comunique a menos que se acuerde expresamente. 96 | Cualquier arreglo, convenio o acuerdo en relación con el Material Licenciado que no se indique en este documento se considera separado e independiente de los términos y condiciones de esta Licencia Pública. 97 | 98 | Sección 8 – Interpretación. 99 | 100 | Para evitar dudas, esta Licencia Pública no es ni deberá interpretarse como una reducción, limitación, restricción, o una imposición de condiciones al uso de Material Licenciado que legalmente pueda realizarse sin permiso del titular, más allá de lo contemplado en esta Licencia Pública. 101 | En la medida de lo posible, si alguna disposición de esta Licencia Pública se considera inaplicable, esta será automáticamente modificada en la medida mínima necesaria para hacerla aplicable. Si la disposición no puede ser reformada, deberá ser eliminada de esta Licencia Pública sin afectar la exigibilidad de los términos y condiciones restantes. 102 | No se podrá renunciar a ningún término o condición de esta Licencia Pública, ni se consentirá ningún incumplimiento, a menos que se acuerde expresamente con el Licenciante. 103 | Nada en esta Licencia Pública constituye ni puede ser interpretado como una limitación o una renuncia a los privilegios e inmunidades que aplican al Licenciante o a Usted, incluyendo aquellos surgidos a partir de procesos legales de cualquier jurisdicción o autoridad. 104 | --------------------------------------------------------------------------------