Lab 4.1: Usando Docker y Docker Compose
Este laboratorio contiene una serie de varias secciones, cada una de las cuales explica un aspecto particular de Docker y su uso en modo ad-hoc.
⚠️ Este tutorial usa la versión
20.10.17-ce
de Docker. Si encuentra alguna parte del laboratorio incompatible con una versión futura, por favor cree un “issue” en el repositorio original.
Requerimientos
- Capacidad de lectura del idioma inglés.
- Comodidad básica con la línea de comandos y el uso de un editor de texto.
- Uso de
git
, asumimos que luego de haber tomado el Laboratorio 2.1 - Cómo usar git ya se está preparado para tomar este laboratio.
Configurando el ambiente de trabajo
La guía de introducción a Docker tiene instrucciones detalladas para configurar Docker en Mac, Linux y Windows.
Una vez que haya terminado de instalar Docker, pruebe su instalación de Docker ejecutando lo siguiente:
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
Hello world! 👋
Jugando con Busybox
Ahora que tenemos todo configurado, es hora de ensuciarse las manos. En esta sección, ejecutaremos un contenedor Busybox en nuestro sistema y probaremos el comando docker run
.
Para comenzar, ejecutemos lo siguiente en nuestra terminal:
docker pull busybox
🚨 Dependiendo de cómo haya instalado Docker en su sistema, es posible que vea un error de permiso denegado después de ejecutar el comando anterior. Si está en una Mac, asegúrese de que el motor Docker esté funcionando. Si está en Linux, prefije los comandos de
docker
consudo
. Alternativamente, puede crear un grupo de docker para deshacerse de este problema.
El comando pull
obtiene la imagen busybox
del registro de docker y la guarda en nuestro sistema. Puede usar el comando docker images
para ver una lista de todas las imágenes en su sistema.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest 3c19bafed223 5 weeks ago 1.41MB
docker run
¡Excelente! Ahora ejecutemos un contenedor Docker basado en esta imagen. Para hacer eso, vamos a usar el comando todopoderoso docker run
.
docker run busybox
¡Espera, no pasó nada! ¿Es eso un error? Bueno, no. Detrás de escena, sucedieron muchas cosas. Cuando llama run
, el cliente de Docker encuentra la imagen (busybox
en este caso), carga el contenedor y luego ejecuta un comando en ese contenedor. Cuando ejecutamos docker run busybox
, no proporcionamos un comando, por lo que el contenedor se inició, ejecutó un comando vacío y luego salió. Probemos algo más emocionante.
$ docker run busybox echo "hello from busybox"
hello from busybox
Bien, finalmente vemos algo de salida. En este caso, el cliente Docker ejecutó diligentemente el comando echo
en nuestro contenedor busybox y luego lo cerró. Si te has dado cuenta, todo eso sucedió bastante rápido. Imagine iniciar una máquina virtual, ejecutar un comando y luego eliminarlo. Ahora es el momento de ver el comando docker ps
. El comando docker ps
muestra todos los contenedores que se están ejecutando actualmente.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Como no hay contenedores en ejecución, vemos una línea en blanco. Probemos una variante más útil: docker ps -a
.
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7bd1e6ed9754 busybox "echo 'hello from bu…" 14 minutes ago Exited (0) 14 minutes ago dazzling_poincare
1227171134d4 busybox "sh" 16 minutes ago Exited (0) 16 minutes ago frosty_jang
Entonces, lo que vemos arriba es una lista de todos los contenedores que ejecutamos. Observe que la columna STATUS
muestra que estos contenedores salieron hace unos minutos.
Probablemente se esté preguntando si hay una forma de ejecutar más de un comando en un contenedor. Probemos eso ahora:
$ docker run -it busybox sh
/ # ls
bin dev etc home proc root sys tmp usr var
/ # uptime
19:47:33 up 36 min, 0 users, load average: 0.00, 0.01, 0.00
/ # date
Sun Jul 17 19:47:33 UTC 2022
/ # exit
Ejecutar el comando run
con las bandera -it
nos adjunta a un tty interactivo en el contenedor. Ahora podemos ejecutar tantos comandos en el contenedor como queramos.
Eso concluye un recorrido relámpago por el poderoso comando docker run
, que probablemente sea el comando que usará con más frecuencia. Tiene sentido pasar algún tiempo sintiéndose cómodo con él. Para obtener más información sobre run
, utilice docker run --help
para ver una lista de todos los indicadores que admite. A medida que avanzamos, veremos algunas variantes más de docker run
.
Sin embargo, antes de seguir adelante, podremos rápidamente sobre la eliminación de contenedores. Vimos arriba que todavía podemos ver restos del contenedor incluso después de haber salido de docker ps -a
. A lo largo de este tutorial, ejecutará docker run
varias veces y dejará contenedores perdidos consumiendo espacio en disco. Por lo tanto, como regla general, limpie los contenedores una vez que termino con ellos. Para hacerlo, puede ejecutar el comando docker rm. Simplemente copie los ID
de contenedor de arriba y péguelos junto con el comando.
$ docker rm 5d30f71b3f4e 3eb5f97e9851
5d30f71b3f4e
3eb5f97e9851
En la eliminación, debería ver los ID
repetidos. Si tiene un montón de contenedores para eliminar de una sola vez, copiar y pegar ID
puede ser tedioso. En ese caso, simplemente puede ejecutar:
$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
320cfb506f0ed3d6e8aa64bc700d1fee9613d6f883727b8d54bdf9b8636369fb
d79102a642d705ba7a832617e0d520d66173a665d2f9db377a64f4f5affeba41
Total reclaimed space: 26B
Por último, también puede eliminar imágenes que ya no necesita ejecutando docker rmi
.
Este comando elimina todos los contenedores que tienen un estado de exited
.
Aplicaciones web con Docker
Así que ahora hemos visto la ejecución de Docker, jugado con un contenedor de Docker. Armados con todo este conocimiento, ahora estamos listos para desplegar aplicaciones web con Docker.
Sitios estáticos
Lo primero que vamos a ver es cómo podemos ejecutar un sitio web estático. Vamos a extraer una imagen de Docker de Docker Hub, ejecutar el contenedor y ver lo fácil que es ejecutar un servidor web.
La imagen que usaremos primero es la de nginx
, un servidor web bastante popular, y cuya imagen ya se encuentra disponible en Docker Hub.
Podemos descargar y ejecutar la imagen directamente de una sola vez usando docker run
.
docker run -d --rm -it --name 'web-server' -p '80:80' nginx:alpine
Al acceder a la URL localhost:80, veremos el mensaje de bienvenida de nginx
:
¡Genial! Pero… oh, vaya. Ahora hemos utilizado un comando más complejo que los anteriores. Pero sin preocuparse, que cada uno tiene una explicación bastante simple. Como ya conocemos --rm
y -it
, solo nos enfocaremos en explicar --name
, -d
y -p
:
-d
separará nuestro terminal del contenedor que se ejecutará y lo enviará al “background”,-p
publicará un puerto expuesto del contenedor a un puerto de la máquina local,- finalmente
--name
corresponde al nombre que queremos dar.
Para detener un contenedor desconectado, ejecute docker stop proporcionando la ID del contenedor. En este caso, podemos usar el nombre static-site que usamos para iniciar el contenedor.
Para detener un contenedor desconectado (tras usar -d
), ejecute docker stop
proporcionando el ID
del contenedor. En este caso, podemos usar el nombre web-server
que usamos para iniciar el contenedor.
$ docker stop web-server
web-server
Ahora que ha visto cómo ejecutar un servidor web dentro de una imagen de Docker, debe preguntarse: ¿cómo puedo crear mi propia imagen de Docker? Esta es la pregunta que exploraremos en la siguiente sección.
Imágenes de Docker
Hemos visto imágenes antes, pero en esta sección profundizaremos en lo que son las imágenes de Docker y construiremos nuestra propia imagen. Empecemos.
Las imágenes de Docker son la base de los contenedores. En el ejemplo anterior, extrajimos la imagen de Busybox del registro y le pedimos al cliente de Docker que ejecutara un contenedor basado en esa imagen. Para ver la lista de imágenes que están disponibles localmente, use el comando docker images
.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx alpine 6721bbfe2e85 3 weeks ago 22.1MB
busybox latest 3c19bafed223 5 weeks ago 1.41MB
hello-world latest 46331d942d63 4 months ago 9.14kB
Lo anterior proporciona una lista de imágenes que henmos usado descargadas desde Docker Hub. TAG
se refiere a una etiqueta particular de la imagen y IMAGE ID
es el identificador único correspondiente para esa imagen.
Para simplificar, puede pensar en una imagen similar a un repositorio git: las imágenes se pueden “commit” con cambios y tener múltiples versiones. Si no proporciona un número de versión específico, el cliente de Docker se establece de manera predeterminada en el tag latest
(la imagen más reciente). Por ejemplo, puede extraer una versión específica de la imagen de ubuntu
:
docker pull ubuntu:22.04
Para obtener una nueva imagen de Docker, puede obtenerla de un registro (como Docker Hub) o crear la suya propia. Hay decenas de miles de imágenes disponibles en Docker Hub. También puede buscar imágenes directamente desde la línea de comandos mediante docker search
.
Una distinción importante a tener en cuenta cuando se trata de imágenes es la diferencia entre imágenes base e imágenes secundarias.
- Las imágenes base son imágenes que no tienen una imagen principal, generalmente imágenes con un sistema operativo como ubuntu, busybox o debian.
- Las imágenes secundarias son imágenes que se basan en imágenes base y agregan funcionalidad adicional.
Luego están las imágenes oficiales y de usuario, que pueden ser tanto imágenes básicas como secundarias.
- Las imágenes oficiales son imágenes mantenidas y respaldadas oficialmente por la gente de Docker. Suelen tener una palabra de longitud. En la lista de imágenes anterior, las imágenes de
python
,ubuntu
,busybox
yhello-world
son imágenes oficiales. - Las imágenes de usuario son imágenes creadas y compartidas por usuarios como tú y yo. Se basan en imágenes base y agregan funcionalidad adicional. Por lo general, estos tienen el formato de
usuario/nombre-de-imagen
.
¡Bien hecho! 🥳 Has completado existosamente el laboratorio introductorio de containers con Docker y su modo ad-hoc.