Ejecutando su primer contenedor

DockerDockerBeginner
Practicar Ahora

This tutorial is from open-source community. Access the source code

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En este laboratorio, ejecutará su primer contenedor Docker.

Los contenedores son simplemente un proceso (o un grupo de procesos) que se ejecuta en aislamiento. El aislamiento se logra a través de los espacios de nombres de Linux, los grupos de control (cgroups), seccomp y SELinux. Tenga en cuenta que los espacios de nombres de Linux y los grupos de control se integran en el núcleo de Linux. Además del propio núcleo de Linux, no hay nada especial en los contenedores.

Lo que hace útil a los contenedores es la herramienta que los rodea. Para estos laboratorios, usaremos Docker, que ha sido una herramienta ampliamente adoptada para usar contenedores para construir aplicaciones. Docker proporciona a los desarrolladores y operadores una interfaz amigable para construir, enviar y ejecutar contenedores en cualquier entorno con un motor de Docker. Debido a que el cliente de Docker requiere un motor de Docker, una alternativa es usar Podman, que es un motor de contenedores sin demonio para desarrollar, administrar y ejecutar contenedores OCI y es capaz de ejecutar contenedores como root o en modo sin privilegios de root. Por esas razones, recomendamos Podman, pero debido a la adopción, este laboratorio todavía usa Docker.

En la primera parte de este laboratorio, ejecutaremos nuestro primer contenedor y aprenderemos cómo inspeccionarlo. Podremos presenciar el aislamiento de espacios de nombres que adquirimos del núcleo de Linux.

Después de ejecutar nuestro primer contenedor, profundizaremos en otros usos de los contenedores. Puede encontrar muchos ejemplos de estos en la Tienda de Docker, y ejecutaremos varios tipos diferentes de contenedores en el mismo host. Esto nos permitirá ver el beneficio del aislamiento, donde podemos ejecutar múltiples contenedores en el mismo host sin conflictos.

Usaremos algunos comandos de Docker en este laboratorio. Para obtener la documentación completa de los comandos disponibles, consulte la documentación oficial.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/SystemManagementGroup(["System Management"]) linux(("Linux")) -.-> linux/PackagesandSoftwaresGroup(["Packages and Softwares"]) docker/ContainerOperationsGroup -.-> docker/run("Run a Container") docker/ContainerOperationsGroup -.-> docker/ls("List Containers") docker/ContainerOperationsGroup -.-> docker/exec("Execute Command in Container") docker/ContainerOperationsGroup -.-> docker/top("Display Running Processes in Container") docker/SystemManagementGroup -.-> docker/version("Show Docker Version") docker/SystemManagementGroup -.-> docker/prune("Remove Unused Docker Objects") linux/PackagesandSoftwaresGroup -.-> linux/apt("Package Handling") subgraph Lab Skills docker/run -.-> lab-148982{{"Ejecutando su primer contenedor"}} docker/ls -.-> lab-148982{{"Ejecutando su primer contenedor"}} docker/exec -.-> lab-148982{{"Ejecutando su primer contenedor"}} docker/top -.-> lab-148982{{"Ejecutando su primer contenedor"}} docker/version -.-> lab-148982{{"Ejecutando su primer contenedor"}} docker/prune -.-> lab-148982{{"Ejecutando su primer contenedor"}} linux/apt -.-> lab-148982{{"Ejecutando su primer contenedor"}} end

Empezar

Abra una terminal en la VM de LabEx y ejecute docker -h, que le mostrará la página de ayuda de la CLI de Docker.

$ docker -h
La abreviatura de la bandera -h ha sido desaprobada, utilice --help en su lugar

Uso: docker [OPCIONES] COMANDO

Un entorno de ejecución autónomo para contenedores

...

Comandos de gestión:
builder Gestionar compilaciones
config Gestionar configuraciones de Docker
container Gestionar contenedores
engine Gestionar el motor de Docker
image Gestionar imágenes
network Gestionar redes
node Gestionar nodos de Swarm
plugin Gestionar plugins
secret Gestionar secretos de Docker
service Gestionar servicios
stack Gestionar stacks de Docker
swarm Gestionar Swarm
system Gestionar Docker
trust Gestionar la confianza en las imágenes de Docker
volume Gestionar volúmenes

La línea de comandos de Docker se puede utilizar para administrar varias características del motor de Docker. En este laboratorio, nos centraremos principalmente en el comando container.

Instale podman en su VM de LabEx.

sudo apt-get update
sudo apt-get install podman -y

Si se ha instalado podman, puede ejecutar el comando alternativo para comparar.

sudo podman -h

Además, puede revisar la versión de su instalación de Docker con docker version

docker version

Cliente:
Versión: 20.10.21
...

Servidor:
Motor:
Versión: 20.10.21
...

Nota que Docker instala tanto un Cliente como un Servidor: Motor de Docker. Por ejemplo, si ejecuta el mismo comando para podman, verá solo una versión de la CLI, porque podman se ejecuta sin demonio y depende de un entorno de ejecución de contenedores compatible con OCI (runc, crun, runv, etc.) para interactuar con el sistema operativo y crear los contenedores en ejecución.

sudo podman version --events-backend=none
Versión: 3.4.4
Versión de la API: 3.4.4
Versión de Go: go1.17.3
Compilado: Thu Jan 1 08:00:00 1970
Sistema operativo/Arquitectura: linux/amd64

Ejecute su primer contenedor

Vamos a usar la CLI de Docker para ejecutar nuestro primer contenedor.

Abra una terminal en la VM de LabEx.

Ejecute el comando.

docker container run -t ubuntu top

Utilice el comando docker container run para ejecutar un contenedor con la imagen ubuntu usando el comando top. La bandera -t asigna un pseudo-TTY que necesitamos para que funcione correctamente top.

$ docker container run -it ubuntu top
No se encuentra la imagen 'ubuntu:latest' localmente
latest: Buscando en el repositorio de Docker Hub
aafe6b5e13de: Descarga completada
0a2b43a72660: Descarga completada
18bdd1e546d2: Descarga completada
8198342c3e05: Descarga completada
f56970a44fd4: Descarga completada
Digest: sha256:f3a61450ae43896c4332bda5e78b453f4a93179045f20c8181043b26b5e79028
Estado: Imagen actualizada: ubuntu:latest

El comando docker run primero resultará en un docker pull para descargar la imagen de ubuntu en su host. Una vez que se ha descargado, iniciará el contenedor. La salida del contenedor en ejecución debería verse así:

top - 20:32:46 up 3 days, 17:40,  0 users,  load average: 0.00, 0.01, 0.00
Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.1 sy,  0.0 ni, 99.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  2046768 total,   173308 free,   117248 used,  1756212 buff/cache
KiB Swap:  1048572 total,  1048572 free,        0 used.  1548356 avail Mem

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
      1 root      20   0   36636   3072   2640 R   0.3  0.2   0:00.04 top

top es una utilidad de Linux que imprime los procesos en un sistema y los ordena por consumo de recursos. Observe que solo hay un solo proceso en esta salida: es el propio proceso top. No vemos otros procesos de nuestro host en esta lista debido al aislamiento del espacio de nombres PID.

Los contenedores utilizan los espacios de nombres de Linux para proporcionar aislamiento de los recursos del sistema de otros contenedores o del host. El espacio de nombres PID proporciona aislamiento para los identificadores de proceso. Si ejecuta top mientras está dentro del contenedor, notará que muestra los procesos dentro del espacio de nombres PID del contenedor, que es muy diferente de lo que puede ver si ejecuta top en el host.

Aunque estamos usando la imagen ubuntu, es importante destacar que nuestro contenedor no tiene su propio kernel. Utiliza el kernel del host y la imagen ubuntu solo se utiliza para proporcionar el sistema de archivos y las herramientas disponibles en un sistema ubuntu.

Inspeccione el contenedor con docker container exec

El comando docker container exec es una forma de "entrar" en los espacios de nombres de un contenedor en ejecución con un nuevo proceso.

Abra una nueva terminal. Seleccione Terminal > Nueva terminal.

En la nueva terminal, use el comando docker container ls para obtener el ID del contenedor en ejecución que acaba de crear.

$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b3ad2a23fab3 ubuntu "top" 29 minutes ago Up 29 minutes goofy_nobel

Luego, use ese id para ejecutar bash dentro de ese contenedor usando el comando docker container exec. Dado que estamos usando bash y queremos interactuar con este contenedor desde nuestra terminal, use las banderas -it para ejecutar en modo interactivo mientras asigna un pseudo-terminal.

$ docker container exec -it ID < CONTAINER > bash
root@b3ad2a23fab3:/#

¡Y voilà! Acabamos de usar el comando docker container exec para "entrar" en los espacios de nombres de nuestro contenedor con nuestro proceso bash. Usar docker container exec con bash es un patrón común para inspeccionar un contenedor de Docker.

Observe el cambio en el prefijo de su terminal. Por ejemplo, root@b3ad2a23fab3:/. Esto es una indicación de que estamos ejecutando bash "dentro" de nuestro contenedor.

Nota: Esto no es lo mismo que conectarse por ssh a un host o una VM separada. No necesitamos un servidor ssh para conectarnos con un proceso bash. Recuerde que los contenedores utilizan características a nivel de kernel para lograr el aislamiento y que los contenedores se ejecutan sobre el kernel. Nuestro contenedor es solo un grupo de procesos que se ejecutan en aislamiento en el mismo host, y podemos usar docker container exec para entrar en ese aislamiento con el proceso bash. Después de ejecutar docker container exec, el grupo de procesos que se ejecutan en aislamiento (es decir, nuestro contenedor) incluye top y bash.

Desde la misma terminal, ejecute ps -ef para inspeccionar los procesos en ejecución.

root@b3ad2a23fab3:/## ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 20:34? 00:00:00 top
root 17 0 0 21:06? 00:00:00 bash
root 27 17 0 21:14? 00:00:00 ps -ef

Debería ver solo el proceso top, el proceso bash y nuestro proceso ps.

Para comparar, salga del contenedor y ejecute ps -ef o top en el host. Estos comandos funcionarán en Linux o Mac. Para Windows, puede inspeccionar los procesos en ejecución usando tasklist.

root@b3ad2a23fab3:/## exit
exit
$ ps -ef
## Muchos procesos!

Descripción técnica detallada
PID es solo uno de los espacios de nombres de Linux que proporciona aislamiento a los contenedores de los recursos del sistema. Otros espacios de nombres de Linux incluyen:

  • MNT - Montar y desmontar directorios sin afectar a otros espacios de nombres
  • NET - Los contenedores tienen su propia pila de red
  • IPC - Mecanismos de comunicación interproceso aislados, como colas de mensajes.
  • Usuario - Vista aislada de los usuarios en el sistema
  • UTC - Establecer el nombre de host y el nombre de dominio por contenedor

Estos espacios de nombres juntos proporcionan el aislamiento para los contenedores que les permite ejecutarse juntos de manera segura y sin conflicto con otros contenedores que se ejecutan en el mismo sistema. A continuación, demostraremos diferentes usos de los contenedores y el beneficio del aislamiento a medida que ejecutamos múltiples contenedores en el mismo host.

Nota: Los espacios de nombres son una característica del kernel de Linux. Pero Docker le permite ejecutar contenedores en Windows y Mac... ¿cómo funciona eso? El secreto es que integrado en el producto Docker o el motor de Docker hay un subsistema de Linux. Docker abrió este subsistema de Linux a un nuevo proyecto: LinuxKit. Ser capaz de ejecutar contenedores en muchas plataformas diferentes es una ventaja de usar la herramienta Docker con contenedores.

Además de ejecutar contenedores de Linux en Windows usando un subsistema de Linux, ahora es posible utilizar contenedores nativos de Windows debido a la creación de primitivas de contenedores en el sistema operativo Windows. Los contenedores nativos de Windows se pueden ejecutar en Windows 10 o Windows Server 2016 o versiones posteriores.

Nota: si ejecuta este ejercicio en un terminal contenedorizado y ejecuta el comando ps -ef en el terminal, todavía verá un conjunto limitado de procesos después de salir del comando exec. Puede intentar ejecutar el comando ps -ef en un terminal de su máquina local para ver todos los procesos.

Limpie el contenedor que está ejecutando los procesos top escribiendo: <ctrl>-c, liste todos los contenedores y elimine los contenedores por su id.

docker ps -a

docker rm <CONTAINER ID>

Ejecute múltiples contenedores

Explore el Docker Hub

El Docker Hub es el registro central público de imágenes de Docker, que contiene imágenes comunitarias y oficiales.

Al buscar imágenes, encontrará filtros para "Certificados por Docker", "Editor Verificado" e "Imágenes Oficiales". Seleccione el filtro "Certificados por Docker" para encontrar imágenes que se consideran aptas para la empresa y que se han probado con el producto Docker Enterprise Edition. Es importante evitar usar contenido no verificado de la Tienda de Docker al desarrollar sus propias imágenes destinadas a ser desplegadas en el entorno de producción. Estas imágenes no verificadas pueden contener vulnerabilidades de seguridad o incluso software malicioso.

En el paso 2 de este laboratorio, iniciaremos varios contenedores usando algunas imágenes verificadas del Docker Hub: el servidor web nginx y la base de datos mongo.

Ejecute un servidor Nginx

Vamos a ejecutar un contenedor usando la imagen oficial de Nginx del Docker Hub.

docker container run --detach --publish 8080:80 --name nginx nginx

Estamos usando un par de nuevas banderas aquí. La bandera --detach ejecutará este contenedor en segundo plano. La bandera publish publica el puerto 80 en el contenedor (el puerto predeterminado para nginx), a través del puerto 8080 en nuestro host. Recuerde que el espacio de nombres NET da a los procesos del contenedor su propia pila de red. La bandera --publish es una característica que nos permite exponer la red a través del contenedor hacia el host.

¿Cómo sabe que el puerto 80 es el puerto predeterminado para nginx? Porque está listado en la documentación del Docker Hub. En general, la documentación de las imágenes verificadas es muy buena, y la tendrá en cuenta cuando ejecute contenedores usando esas imágenes.

También estamos especificando la bandera --name, que nombra el contenedor. Cada contenedor tiene un nombre, si no lo especifica, Docker le asignará uno aleatoriamente. Especificar su propio nombre facilita la ejecución de comandos posteriores en su contenedor, ya que puede hacer referencia al nombre en lugar del id del contenedor. Por ejemplo: docker container inspect nginx en lugar de docker container inspect 5e1.

Dado que esta es la primera vez que ejecuta el contenedor nginx, descargará la imagen nginx de la Tienda de Docker. Los contenedores posteriores creados a partir de la imagen de Nginx usarán la imagen existente ubicada en su host.

Nginx es un servidor web ligero. Puede acceder al servidor nginx en la pestaña Web 8080 de la VM de LabEx. Cambie a ella y actualice la página para ver la salida de nginx.

step 2 nginx

Ejecute un servidor de base de datos mongo

Ahora, ejecute un servidor de base de datos mongo. Usaremos la imagen oficial de mongoDB del Docker Hub. En lugar de usar la etiqueta latest (que es la predeterminada si no se especifica una etiqueta), usaremos una versión específica de la imagen de mongo: 4.4.

docker container run --detach --publish 8081:27017 --name mongo mongo:4.4

Nuevamente, dado que esta es la primera vez que ejecutamos un contenedor de mongo, descargaremos la imagen de mongo de la Tienda de Docker. Estamos usando la bandera --publish para exponer el puerto 27017 de mongo en nuestro host. Tenemos que usar un puerto diferente de 8080 para el mapeo del host, ya que ese puerto ya está expuesto en nuestro host. Vuelva a consultar la documentación oficial del Docker Hub para obtener más detalles sobre el uso de la imagen de mongo.

Vea la salida de mongoDB usando 0.0.0.0:8081 en el navegador web. Debería ver un mensaje que devolverá una advertencia de MongoDB.

MongoDB server output warning

Verifique sus contenedores en ejecución con docker container ls

$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6777df89fea nginx "nginx -g 'daemon..." Menos de un segundo atrás En ejecución hace 2 segundos 0.0.0.0:8080- nginx > 80/tcp
ead80a0db505 mongo "docker-entrypoint..." Hace 17 segundos En ejecución hace 19 segundos 0.0.0.0:8081- mongo > 27017/tcp
af549dccd5cf ubuntu "top" Hace 5 minutos En ejecución hace 5 minutos priceless_kepler

Debería ver que tiene un contenedor de servidor web Nginx y un contenedor de MongoDB en ejecución en su host. Tenga en cuenta que no hemos configurado estos contenedores para que se comuniquen entre sí.

Puede ver los nombres "nginx" y "mongo" que le dimos a nuestros contenedores, y el nombre aleatorio (en mi caso "priceless_kepler") que se generó para el contenedor ubuntu. También puede ver los mapeos de puerto que especificamos con la bandera --publish. Para obtener más detalles sobre estos contenedores en ejecución, puede usar el comando docker container inspect [container id.

Una cosa que puede notar es que el contenedor de mongo está ejecutando el comando docker-entrypoint. Este es el nombre del ejecutable que se ejecuta cuando se inicia el contenedor. La imagen de mongo requiere alguna configuración previa antes de iniciar el proceso de base de datos. Puede ver exactamente lo que hace el script mirándolo en github. Por lo general, puede encontrar el enlace al código fuente de github desde la página de descripción de la imagen en el sitio web de la Tienda de Docker.

Los contenedores son autónomos e aislados, lo que significa que podemos evitar posibles conflictos entre contenedores con diferentes dependencias de sistema o tiempo de ejecución. Por ejemplo: desplegar una aplicación que utiliza Java 7 y otra aplicación que utiliza Java 8 en el mismo host. O ejecutar múltiples contenedores de nginx que todos tienen el puerto 80 como sus puertos de escucha predeterminados (si se expone en el host usando la bandera --publish, los puertos seleccionados para el host deben ser únicos). Los beneficios del aislamiento son posibles gracias a los espacios de nombres de Linux.

Nota: No tuvo que instalar nada en su host (aparte de Docker) para ejecutar estos procesos. Cada contenedor incluye las dependencias que necesita dentro del contenedor, por lo que no necesita instalar nada directamente en su host.

Ejecutar múltiples contenedores en el mismo host nos da la capacidad de utilizar al máximo los recursos (cpu, memoria, etc.) disponibles en un solo host. Esto puede resultar en grandes economías de costos para una empresa.

Si bien ejecutar imágenes directamente del Docker Hub puede ser útil en ocasiones, es más útil crear imágenes personalizadas y referirse a las imágenes oficiales como punto de partida para estas imágenes. Profundizaremos en la creación de nuestras propias imágenes personalizadas en el Laboratorio 2.

Limpie

Completar este laboratorio resulta en una serie de contenedores en ejecución en su host. Limpiemos estos.

Primero, obtenga una lista de los contenedores en ejecución usando docker container ls.

$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6777df89fea nginx "nginx -g 'daemon..." 3 minutos atrás En ejecución hace 3 minutos 0.0.0.0:8080- nginx > 80/tcp
ead80a0db505 mongo "docker-entrypoint..." 3 minutos atrás En ejecución hace 3 minutos 0.0.0.0:8081- mongo > 27017/tcp
af549dccd5cf ubuntu "top" 8 minutos atrás En ejecución hace 8 minutos priceless_kepler

Luego, ejecute docker container stop [container id] para cada contenedor de la lista. También puede usar los nombres de los contenedores que especificó anteriormente.

$ docker container stop d67 ead af5
d67
ead
af5

Nota: Solo tiene que referirse a suficientes dígitos del ID para que sea único. Tres dígitos casi siempre son suficientes.

Elimine los contenedores detenidos

docker system prune es un comando muy útil para limpiar su sistema. Eliminará cualquier contenedor detenido, volúmenes y redes no utilizados y imágenes sueltas.

$ docker system prune
ADVERTENCIA! Esto eliminará:
- todos los contenedores detenidos
- todos los volúmenes no utilizados por al menos un contenedor
- todas las redes no utilizadas por al menos un contenedor
- todas las imágenes sueltas
¿Está seguro de que desea continuar? [y/N] y
Contenedores eliminados:
7872fd96ea4695795c41150a06067d605f69702dbcb9ce49492c9029f0e1b44b
60abd5ee65b1e2732ddc02b971a86e22de1c1c446dab165462a08b037ef7835c
31617fdd8e5f584c51ce182757e24a1c9620257027665c20be75aa3ab6591740

Espacio recuperado en total: 12B

Resumen

En este laboratorio, creó sus primeros contenedores de Ubuntu, Nginx y MongoDB.

Conclusiones Clave

  • Los contenedores están compuestos por espacios de nombres de Linux y grupos de control que proporcionan aislamiento de otros contenedores y del host.
  • Debido a las propiedades de aislamiento de los contenedores, puede programar muchos contenedores en un solo host sin preocuparse por dependencias en conflicto. Esto facilita la ejecución de múltiples contenedores en un solo host: aprovechando al máximo los recursos asignados a ese host y, en última instancia, ahorrando dinero en los costos del servidor.
  • Evite usar contenido no verificado de la Tienda de Docker al desarrollar sus propias imágenes, ya que estas imágenes pueden contener vulnerabilidades de seguridad o incluso software malicioso.
  • Los contenedores incluyen todo lo necesario para ejecutar los procesos dentro de ellos, por lo que no es necesario instalar dependencias adicionales directamente en su host.