Docker
Acerca de este artículo
Se que no incluye algunos aspectos técnicos profundos, pero recoge en gran medida la mayoría de aspectos que deben de tenerse en cuenta a la hora de iniciarse en Docker. Si necesita una guía acerca de como manejar las imágenes, committear a Dockerhub o si quiere más información sobre las capas de las imágenes exportar las imágenes, etc, busque otra guía, esta se dirige a lo más básico y fundamental para empezar a ser productivo con Docker.
Docker vs VMs
La diferencia entre Docker y la virtualización tradicional es bastante compleja de explicar pero básicamente en la virtualización tradicional se necesista de un sistema operativo virtual, mientras que en Docker los contenedores tienen la capacidad de comunicarse con el kernel del sistema operativo host. Además gracias al standar OCI (Open Container initiative) parece que su integración es cada vez mayor debido a su fácil portabilidad. Como ya introduje este artículo no pretende indagar en detalles técnicos complejos y profundos.
Ficheros Dockerfile y compose.yaml
Son la base del funcionamiento de Docker, reunen las instrucciones para construir los contenedores
Dockerfile
Un fichero Dockerfile contiene las instrucciones para generar una instancia de un contenedor Docker. Estas son las principales instrucciones que definen un Dockerfile
1
2
3
4
5
6
FROM: Imagen base que se utilizará para construir la nueva.
RUN: Ejecuta comandos en la imagen. Por ejemplo apt install python
COPY: Copia archivos o directorios desde el host a la imagen.
WORKDIR: Establece el directorio de trabajo por defecto.
CMD: Comando que se ejecutará cuando se arranque el contenedor.
ENTRYPOINT: Comando que se ejecutará cuando se inicie un contenedor.
¿Quieres empezar a escribir tus propios Dockerfile?, aquí está la guía oficial: https://docs.docker.com/get-started/docker-concepts/building-images/writing-a-dockerfile/
compose.yaml
Un fichero compose.yaml contiene las instrucciones para generar varios contenedores. Algunas veces estos archivos contienen información de que ficheros Dockerfile se utilizarán para contruir alguno de los contenedores que se geneararán. Así que con un solo comando se puede levantar varios contenedores definidos en estos archivos.
En este ejemplo sacado de hub.docker.com se muestra un ejemplo de compose.yaml , se declaran dos servicios, la base de datos con una imagen de mariadb y un wordpress.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
services:
wordpress:
image: wordpress
restart: always
ports:
- 8080:80
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: exampleuser
WORDPRESS_DB_PASSWORD: examplepass
WORDPRESS_DB_NAME: exampledb
volumes:
- wordpress:/var/www/html
db:
image: mysql:8.0
restart: always
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: exampleuser
MYSQL_PASSWORD: examplepass
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- db:/var/lib/mysql
volumes:
wordpress:
db:
Construir los contenedores con Compose:
1
2
3
docker-compose up -d
docker-compose up -d --build # reconstruye el contenedor.
docker-compose up # sin -d podemos ver la salida
En algunos sistemas el comando es:
1
docker compose up -d
Aquí la guía para Compose: https://docs.docker.com/compose/gettingstarted/
Imágenes
Una imagen de docker es un archivo binario que contiene todo lo necesario para generar un contenedor, las imágenes de Docker las proporciona la comunidad a través de repositorios por defecto si una imagen no se encuentra descargada con el comando “docker pull”, entonces Docker intentará descargarla de un repositorio, como se puede ver en el siguiente ejemplo:
1
2
3
4
5
root@office:/home/pablo# docker run nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
3da95a905ed5: Pull complete
6c8e51cf0087: Pull complete
Algunos comandos para manejar las imágenes
1
2
3
4
5
docker pull nombre:tag # descarga una imagen normalmente de dockerhub
docker images #listar imagenes
docker rmi <id_imagen> #borrar imagen
docker system prune # borrar todas la imagenes que no están en uso
docker rmi $(docker images -q) --force # borrar todas las imagenes
Contenedores
Es la ejecución de una imagen, una instancia de esta.
1
2
3
4
5
6
7
8
9
docker run -p 4000:4000 <id_imagen> # levantar/recrear/genear un contenedor
docker exec -it <id_contenedor>sh # ejecutar comando con iteracion -it "sh" (Bourne Shell)
docker ps # Ver que contenedores están corriendo
docker logs <id_contenedor> # ver logs de un contenedor
docker stats # Ver consumo de recursos de los contenedores
docker attach <id_contenedor> # Ver consola del contenedor
docker stop <id_contenedor> # Para un contenedor
docker rm <id_contenedor> # Destruir un contenedor
docker container prune # Borrar todos los contenedores parados
docker cp
No hay que darle muchas vueltas a las cosas, con cp puedes copiar del host al contenedor y viceversa
1
2
docker cp archivo <id_contenedor> /ruta/archivo # host => contenedor
docker cp <id_contenedor>:/ruta/archivo ./archivo # contenedor => host
ENTRYPOINT y CMD
Entrypoint se ejecutará siempre, mientras que CMD se puede reescribir cuando lanzas el contenedor, esto puede ser útil para algunos casos de uso donde se quiere parametrizar variables de entorno y parametros del propio contenedor o alterar el comportamiento del mismo. En el siguiente ejemplo se utilizaría un volumen, o sea en el proyecto existiría una carpeta docker que contendría los archivos .sql que se ejecutarían automáticamente al crear el contenedor.
Versión Dockerfile
1
COPY init.sql /docker-entrypoint-initdb.d/
Versión compose.yaml
1
2
3
volumes:
- ./docker/mysql/scripts:/docker-entrypoint-initdb.d
- ./mysql_data:/var/lib/mysql
Persistencia
Docker nos permite montar volúmenes lógicos para poder compartir datos con el contenedor y tener una persistencia y control sobre los mismos. De esta forma si por ejemplo nuestro contenedor de base de datos, se destruye por cualquier motivo, incluído el error humano, siempre podemos disponer de una copia del lado del host, es una de las funcionalidades más útiles de Docker
Podemos correr un contenedor indicando la persistencia en el comando
1
2
3
docker run -v /ruta/local:/ruta/contenedor # -v de volume
docker volume ls # ver volúmenes
docker volume inspect mivolumen # inspeccionar un volumen
O bien indicando la persistencia en el compose.yaml
1
2
3
4
5
6
7
8
version: "3.9"
services:
nginx:
image: nginx
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
En este ejemplo de persistencia hay que poner atención a la línea de volumes, al usar el “./” delante del volumen se está indicando que dicho volumen se montará en el host, cualquier modificación de la web se progará a ese directorio.
Redes
Docker opera en varios modos de red según necesidades de nuestros proyectos.
- bridge: Red por defecto, permite la comunicación entre contenedores en el mismo host. Es la más común.
- host: Permite que los contenedores compartan la red del host
- overlay: Permite la comunicación entre contenedores en diferentes hosts.
- macvlan: Permite asignar una dirección MAC a un contenedor y hacer que se comporte como un dispositivo físico en la red.
- none: Sin acceso a la red.
1
2
3
4
5
6
docker network ls #lista las redes
docker network create --driver bridge testred #crear una red con el driver bridge
docker inspect <id_red> # ver detalles de la red
docker network connect <id_contenedor> # conectar un contenedor
docker network disconnect <id_contenedor> # desconectar un contenedor
docker network rm testred # borrar una red
Cheatsheet comandos
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
docker-compose up -d # compose -d daemonize
docker-compose up -d --build # reconstruye el contenedor.
docker-compose up # sin -d podemos ver la salida
docker pull nombre:tag # descarga una imagen normalmente de dockerhub
docker images #listar imagenes
docker rmi <id_imagen> #borrar imagen
docker system prune # borrar todas la imagenes que no están en uso
docker rmi $(docker images -q) --force # borrar todas las imagenes
docker run -p 4000:4000 <id_imagen> # levantar/recrear/genear un contenedor
docker exec -it <id_contenedor>sh # ejecutar comando con iteracion -it "sh" (Bourne Shell)
docker ps # Ver que contenedores están corriendo
docker logs <id_contenedor> # ver logs de un contenedor
docker stats # Ver consumo de recursos de los contenedores
docker attach <id_contenedor> # Ver consola del contenedor
docker stop <id_contenedor> # Para un contenedor
docker rm <id_contenedor> # Destruir un contenedor
docker container prune # Borrar todos los contenedores parados
docker cp archivo <id_contenedor> /ruta/archivo # host => contenedor
docker cp <id_contenedor>:/ruta/archivo ./archivo # contenedor => host
docker run -v /ruta/local:/ruta/contenedor # -v de volume
docker volume ls # ver volúmenes
docker volume inspect mivolumen # inspeccionar un volumen
docker network ls #lista las redes
docker network create --driver bridge testred #crear una red con el driver bridge
docker inspect <id_red> # ver detalles de la red
docker network connect <id_contenedor> # conectar un contenedor
docker network disconnect <id_contenedor> # desconectar un contenedor
docker network rm testred # borrar una red
Como esto es una wiki, es muy probable que este documento se amplie, altere o modifique en el futuro.