Tabla de Contenidos

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:

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 ubuntu:20.04

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

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

COPY . /app

WORKDIR /app

ENV NODE_ENV=production

EXPOSE 8080

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:

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:

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:

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

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

Ejercicio 2

PMA_ARBITRARY=1
UPLOAD_LIMIT=64

Ejercicio 3

Si quieres ampliar tus conocimientos sobre Docker, puedes bajarte la imagen getting-started y seguir su tutorial