Herramientas de usuario

Herramientas del sitio


clase:smr:sr:1eval:docker2

02 - Docker II

En el tema anterior vimos lo básico para trabajar con Docker. En este tema, veremos aspectos más avanzados como la creación de imágenes, la gestión de las redes en Docker y una forma más sencilla de crear varios contenedores conectados entre sí.

Creación de imágenes

Hay veces que nos interesa crear imágenes si ninguna de las hay cumple todos nuestros requisitos. Este proceso se divide en dos partes:

  • Creación del archivo de configuración de la imagen
  • Construcción de la imagen

DockerFile

Para gestionar la configuración de una imagen de Docker, necesitamos crear un archivo especial llamado Dockerfile.

Un Dockerfile es un archivo de texto que contiene un conjunto de instrucciones para construir una imagen de Docker de manera automática. Cada instrucción en un Dockerfile ejecuta un comando en el sistema operativo base, y su resultado forma parte de la imagen final. Esto permite definir, de forma declarativa, todos los pasos necesarios para que un contenedor se configure y ejecute de la manera deseada, incluyendo la instalación de paquetes, la copia de archivos, la exposición de puertos y la definición del comando de inicio.

Un Dockerfile generalmente sigue la siguiente estructura:

1. FROM
2. LABEL
3. RUN
4. COPY / ADD
5. WORKDIR
6. ENV
7. EXPOSE
8. CMD / ENTRYPOINT

  • FROM : Establece la imagen base sobre la cual se construirá la nueva imagen. Toda imagen Docker comienza con esta instrucción. Se puede especificar una versión particular de la imagen base.

FROM ubuntu:20.04

  • LABEL : Se utiliza para agregar metadatos a la imagen, como el autor, la versión, una descripción, etc. Esto puede ayudar a identificar y gestionar las imágenes.

LABEL maintainer="tu_nombre@example.com" version="1.0"

  • RUN : Ejecuta comandos en la imagen durante la construcción. Suele utilizarse para instalar paquetes, configurar el entorno, o cualquier otra tarea que deba realizarse en la imagen.

RUN apt-get update && apt-get install -y nginx

  • COPY / ADD : Permiten copiar archivos desde el sistema local al sistema de archivos de la imagen. La diferencia principal es que ADD puede también manejar URL y archivos comprimidos.

COPY . /app

  • WORKDIR : Establece el directorio de trabajo para las siguientes instrucciones en el Dockerfile. Es útil para evitar escribir rutas largas en varias instrucciones.

WORKDIR /app

  • ENV : Se utiliza para definir variables de entorno que estarán disponibles en la imagen final y en los contenedores creados a partir de ella.

ENV NODE_ENV=production

  • EXPOSE : Configura el puerto en el que la aplicación dentro del contenedor está diseñada para escuchar. Aunque no publica el puerto fuera del contenedor, sirve como una referencia.

EXPOSE 8080

  • CMD / ENTRYPOINT : Definen los comandos que se ejecutará cuando se inicie un contenedor basado en la imagen. CMD proporciona un comando predeterminado, mientras que ENTRYPOINT establece un comando principal que no se puede sobrescribir fácilmente.

CMD ["nginx", "-g", "daemon off;"]

Así, un ejemplo completo de un Dockerfile podría ser:

# Usamos una imagen base de Ubuntu
FROM ubuntu:20.04

# Instalamos paquetes necesarios
RUN apt-get update && apt-get install -y \
    curl \
    vim

# Establecemos el directorio de trabajo
WORKDIR /app

# Copiamos los archivos de nuestra aplicación al contenedor
COPY . .

# Exponemos el puerto que usará la aplicación
EXPOSE 8080

# Definimos el comando que se ejecutará al iniciar el contenedor
CMD ["bash"]

Es importante que el archivo de configuración se llame exactamente Dockerfile, sin ninguna extensión. Docker busca automáticamente un archivo con este nombre para construir la imagen. Un nombre diferente o la inclusión de una extensión podría provocar errores o hacer que Docker no encuentre el archivo.

Docker build

Una vez que tenemos el Dockerfile con la configuración deseada, el siguiente paso es construir la imagen a partir de ese archivo. Para ello, se utiliza el comando docker build. Este comando procesa el Dockerfile y genera una imagen que luego puede ser utilizada para crear contenedores.

La sintaxis básica del comando es la siguiente:

docker build -t nombre_imagen:tag ruta_dockerfile

Donde:

  • -t nombre_imagen:tag: Asigna un nombre y una etiqueta (tag) a la imagen que se va a construir. El nombre ayuda a identificar la imagen, y la etiqueta es opcional, pero se suele utilizar para especificar una versión (por ejemplo, v1.0 o latest). Si no se especifica una etiqueta, Docker asigna latest por defecto.
  • ruta_dockerfile: Ruta al directorio que contiene el Dockerfile. Lo normal es estar en el directorio donde está el fichero Dockerfile por lo que sea pondrá un punto indicando que es el directorio actual.

Por ejemplo, si estamos en el mismo directorio donde tenemos nuestro Dockerfile, podríamos crear una imagen de la siguiente forma:

docker build -t mi_aplicacion:1.0 .

Gestión de redes

Docker incluye un sistema de redes que permite a los contenedores comunicarse entre sí y con el mundo exterior. Las principales ordenes para trabajar con redes de Docker son:

Comando Descripción
docker network create Crea una red
docker network rm Elimina una red
docker network ls Lista las redes existentes
docker network connect Conecta un contenedor a una red
docker network disconnect Desconecta un contenedor de una red
docker network inspect Muestra los detalles de una red

Crear una red

Por defecto, Docker crea varias redes cuando se instala, y los contenedores nuevos se conectan automáticamente a una de estas redes según sea necesario.

Además, podmos crear nuestras propias redes para organizar los contenedores según las necesidades de nuestra aplicación. Esto se realiza con el comando docker network create:

docker network create mi_red

Esto crea una nueva red llamada mi_red, que será una red de tipo bridge por defecto. Los contenedores conectados a esta red pueden comunicarse entre ellos por nombre, usando el nombre del contenedor como si fuera un hostname.

Si queremos cambiar el tipo de red, podemos usar el parámetro –driver indicando el tipo de red:

docker network create --driver tipo_red mi_red

Los tipos de redes más comunes son:

  • bridge: Red por defecto, donde los contenedores pueden comunicarse entre ellos en la misma red y con el host a través de NAT.
  • host: Los contenedores comparten la pila de red con el host, sin aislamiento de red.
  • overlay: Utilizado principalmente en configuraciones de Docker Swarm para permitir la comunicación entre varios hosts.
  • macvlan: Permite asignar una dirección MAC a cada contenedor, haciéndolo aparecer como un dispositivo físico en la red.
  • none: Desconecta el contenedor de todas las redes.

Añadir y eliminar contenedores de una red

Una vez que has creado una red, puedes añadir contenedores a esta red, tanto en el momento de su creación como después.

Para añadir un contenedor a una red en el momento de su creación utilizamos la opción –network con el comando docker run:

docker run -d --name mi_contenedor --network mi_red nginx

Este comando crea un contenedor llamado mi_contenedor basado en la imagen nginx y lo conecta a la red mi_red.

Para añadir un contenedor existente a una red usamos el comando docker network connect:

docker network connect mi_red mi_contenedor

Esto conecta el contenedor mi_contenedor a la red mi_red.

Para eliminar un contenedor de una red utiliza el comando docker network disconnect:

docker network disconnect mi_red mi_contenedor

Esto desconecta el contenedor mi_contenedor de la red mi_red.

Eliminar una red

Para eliminar una red, usamos el comando docker rm:

docker rm mi_contenedor

Docker no te permitirá eliminar una red si todavía hay contenedores conectados a ella. Si intentas hacerlo, recibirás un mensaje de error indicando que la red no puede ser eliminada porque está en uso.

Para eliminar una red, primero debes desconectar todos los contenedores asociados a esa red o detener y eliminar los contenedores. También se puede utilizar el parámetro -f para forzar la eliminación de la red, desconectando automáticamente todos los contenedores que estén asociados a ella.

Inspeccionar una red

Para obtener información detallada sobre una red, como los contenedores conectados a ella, puedes utilizar el comando docker network inspect:

docker network inspect mi_red

Este comando muestra detalles como la configuración de la red, los contenedores que la utilizan, sus direcciones IP dentro de la red, y más:

[
    {
        "Name": "kea_dhcp-net",
        "Id": "6cdc6ee7b4bc543dfb877d587579285dcc57bedc6289460b4f9bbb6b5b510956",
        "Created": "2024-07-24T11:46:09.349440923+02:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.18.2.0/24",
                    "Gateway": "172.18.2.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "806bb109a752a2dcfd7f81fc531e516728a1f002a2c6e3890e25a6fbca7c56c3": {
                "Name": "dhcp-mysql",
                "EndpointID": "e2e2ceaccc99b91a84466808297e23fbeaac1c9d20134e34161d544fef9af03a",
                "MacAddress": "02:42:ac:12:02:03",
                "IPv4Address": "172.18.2.3/24",
                "IPv6Address": ""
            },
            "80f038e5572004df1d566ec650be56a342f0e8e9e094f2b0d84d36c384981327": {
                "Name": "dhcp-kea-server",
                "EndpointID": "2fc6bbf08db6b5d29b8ffc9e4a788926ec54e255f661de7b026037cdb7df75d4",
                "MacAddress": "02:42:ac:12:02:02",
                "IPv4Address": "172.18.2.2/24",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "dhcp-net",
            "com.docker.compose.project": "kea",
            "com.docker.compose.version": "1.25.0"
        }
    }
]

Docker Compose

Docker Compose es una herramienta que permite definir y gestionar aplicaciones multicontenedor en Docker. Utiliza archivos de configuración en formato YAML para describir los servicios, redes y volúmenes que conforman una aplicación. Con un solo comando, puedes crear y arrancar todos los servicios definidos en el archivo, facilitando la orquestación de aplicaciones complejas.

Para instalarlo, basta seguir las instrucciones de su página oficial

Estructura básica de un archivo docker-compose.yml

Un archivo docker-compose.yml define la configuración de una aplicación multicontenedor. Aquí se presentan las secciones principales:

name: myapp

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html
    networks:
      - mi_red

  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: ejemplo
      MYSQL_DATABASE: mi_basededatos
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - mi_red

networks:
  mi_red:

volumes:
  db_data:

  • name: Se utiliza para definir el nombre del proyecto. Este nombre se utiliza para agrupar y gestionar los contenedores, redes y volúmenes asociados con el proyecto Docker Compose.
  • services:Define los servicios o contenedores que forman parte de la aplicación. En este caso, hay dos servicios: web (basado en Nginx) y db (basado en MySQL).
    • web:
      • image: Define la imagen Docker que se usará para este servicio, en este caso nginx:alpine.
      • ports: Especifica el mapeo de puertos, conectando el puerto 8080 del host con el puerto 80 del contenedor.
      • volumes: Monta un volumen desde el sistema local (./html) a una ubicación en el contenedor (/usr/share/nginx/html).
      • networks: Conecta el servicio a la red mi_red.
    • db:
      • image: Utiliza la imagen mysql:5.7.
      • environment: Establece variables de entorno necesarias para la configuración de MySQL, como la contraseña del root y el nombre de la base de datos.
      • volumes: Define un volumen persistente para los datos de la base de datos.
      • networks: Conecta el servicio a la red mi_red.
  • networks:Define las redes personalizadas que los servicios utilizarán. Aquí se crea una red llamada mi_red.
  • volumes: Define los volúmenes que pueden ser utilizados por los servicios, como el volumen db_data para almacenar los datos de MySQL.

Comandos básicos de Docker Compose

Comando Descripción
docker compose up Inicia los servicios definidos en el archivo docker-compose.yml. Si los contenedores no existen, los crea; si ya existen, los inicia. Si se agrega el parámetro -d ejecutará los servicios en segundo plano (detached mode)
docker compose down Detiene y elimina los contenedores, redes y volúmenes (si se utiliza el párametro -v) creados por docker-compose up
docker compose start Inicia los contenedores que ya han sido creados por docker-compose up, pero que están detenidos. A diferencia de up, no crea nuevos contenedores
docker compose stop Detiene los contenedores en ejecución, pero no los elimina. Los contenedores pueden reiniciarse con docker-compose start
docker compose ps Muestra el estado actual de los contenedores gestionados por Docker Compose, indicando si están en ejecución, detenidos, etc.

Ejercicios

Ejercicio 1

  • Crea una imagen de Docker basada en php:8.0-apache que copie el contenido de un archivo index.html en la carpeta /var/www/html del contenedor. El contenido del archivo será:

<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

  • Además, actualiza el SO e instala el editor de texto Nano
  • Construye la imagen con docker build y asígnale el nombre smr_apache, mapeando el puerto 11211 local al 80 del contenedor.
  • Ejecuta un contenedor basado en la imagen creada y verifica que puedes ver la web en el navegador al acceder al puerto 11211.
  • Entra dentro del contenedor y comprueba que puedes editar el archivo index.html con Nano

Ejercicio 2

  • Crea una imagen basada en Mysql con smr como password de root
  • Construye la imagen con el nombre smr_mysql
  • Crea otro contenedor basado en phpmyadmin. Añade como parámetros:

PMA_ARBITRARY=1
UPLOAD_LIMIT=64

  • Construye esta segunda imagen con el nombre smr_phpmyadmin
  • Crea una red Docker llamada smr_red
  • Construye dos contenedores basados en las imágenes anteriores y conéctalos a la red recién creada. Los nombres serán mysql_server y phpmyadmin. Además, el contenedor phpmyadmin mapeará el puerto local 22322 al 80 del contenedor
  • Abre tu navegador y accede a http://localhost:22322. Comprueba que se carga la página de login de phpmyadmin y que puedes acceder a ella (el nombre del servidor será el del contenedor de Mysql)
  • Inspecciona la red y comprueba que ambos contenedores están conectados a la misma

Ejercicio 3

  • Modifica el ejercicio anterior para hacer todo con Docker Compose
  • Crea un volumen para persistir los datos de Mysql
Si quieres ampliar tus conocimientos sobre Docker, puedes bajarte la imagen getting-started y seguir su tutorial
clase/smr/sr/1eval/docker2.txt · Última modificación: 2024/08/16 11:28 por cesguiro