Docker es una plataforma que permite construir, ejecutar y compartir aplicaciones mediante contenedores.

Los componentes de Docker son; Docker daemon el cual es el corazón ya que gracias a él podemos comunicarnos con los servicios de docker, REST API expone el docker daemon y el cliente de docker permite hacer uso de los servicios (por defecto es la línea de comandos). También encontramos:
- Un contenedor es una agrupación de procesos que corren nativamente en la máquina anfitriona, estos no pueden ver más allá del contenedor. No puede consumir más recursos de los que se les permite.
- Las imágenes son artefactos que usa docker para empaquetar contenedores, similar a un snapshot.
- Los volúmenes de datos permiten ingresar a los datos de la máquina anfitriona.
- La red (network) permite comunicarse entre contenedores o con el mundo exterior.
Comandos importantes de Docker
- docker run name: ejecuta un contenedor con el nombre del contenedor.
- docker ps: muestra los contenedores activos.
- docker ps -a: muestra todos los contenedores:
- docker inspect <container ID>: muestra los detalles completos de un contenedor.
- docker inspect <name>: similar al anterior pero con el nombre.
- docker run –name nombre: se le asigna un nombre personalizado.
- docker rename old new: cambia el nombre.
- docker rm <ID o nombre>: elimina el contenedor.
- docker container prune: elimina todos los contenedores que estén parados.
- docker exec -it name-container
Datos en Docker

- Bind mount: permite enlazar datos dentro del contenedor hacía el sistema de archivos local.
- Volúmenes: es una manera más estándar de manejar los datos. Permite solo a docker – solo con permisos – hacer uso de estos volúmenes, por lo cual es más seguro que bind mount. En otras palabras, no se puede ver algún directorio con archivos enlazados… mas bien, se debe acceder desde docker.
- Insertar archivos de un contenedor: docker cp archivo.extension nombreContenedor:/directorio/archivo.extension.
- Extraer archivos de un contenedor: docker cp nombreContenedor:/nombreArchivo ruta
Imágenes

Una imagen contiene distintas capas de datos: distribución, diferente software, bibliotecas, etcetera. En otras palabras, una imagen se compone de diferentes capas de personalización partiendo una capa inicial (base image).
Comandos importantes
- <em>docker image ls</em>: ver las imágenes que existen localmente.
- <em>docker pull imageName:Version:</em> descargar una imagen de docker.
- docker history nombreImagen:nombreTag: ver el historial de capas.
- <em>dive nombreImagen:tag</em>: analizar las capas usando Dive.
Construir una imagen propia
Partiendo de un archivo podemos generar alguna imagen propia, por ejemplo:
Se crea un archivo llamado Dockerfile con el comando touch Dockerfile, se agrega el contenido de este archivo:
FROM ubuntu:latest RUN touch /ust/src/hola-mundo.txt # este comando se ejecutará en tiempo de build
Se crea la imagen pasando el contexto del build: docker build -t ubuntu:holaMundo
Se inicia una conexión por terminal al contenedor de ubuntu docker run -it ubuntu:holaMundo
Para publicar la imagen se cambia el tag ubuntu (ya que este existe como uno oficial) con docker tag ubuntu:holaMundo miNombreUsuario/ubuntu:holaMundo
Para publicar esta imagen – es parecido a git – se usa docker push miusuario/ubuntu:holaMundo
Caché de capas para estructurar correctamente las imágenes
Es recomendable seguir una estructura para el archivo Dockerfile; por ejemplo:
- Se usa una imagen base.
- Dependencias del código.
- Código de la aplicación.
De esta manera cuando se construya la imagen personalizada se rehusaran las capas de la imagen base y las dependencias; y solo se modificara el código de la aplicación. Además es recomendable que el código de la aplicación tenga un bind mount a nuestro sistema de archivos local para que no se tenga que construir la imagen continuamente, en otras palabras, solo se edita el código local y se actualiza en el contenedor.
Docker networking
Sirve para colaborar entre contenedores, por ejemplo: que un contenedor de una aplicación se conecte a un contenedor de base de datos.
Comandos
- docker network ls: listar las redes.
- docker network create –attachable : crear una red y se pueda usar con un contenedor.
- docker network inspect : inspeccionar una red.
- docker network connect : conectar un conector a la red.
- docker run –env MY_VAR=” : correr un contenedor usando variables de entorno.
Docker compose
Esta funcionalidad de Docker permite gestionar la estructura de un conjunto de contenedores sin la necesidad de hacerlo todo por terminal de comandos mediante un archivo compose, por ejemplo:
# Versión del compose fileversion: "3.8"# Servicios que componen nuestra aplicación.## Un servicio puede estar compuesto por uno o más contenedores.services:# nombre del servicio. app: # Imagen a utilizar. image: app # Declaración de variables de entorno. environment: MONGO_URL: "mongodb://db:27017/test" # Indica que este servicio depende de otro, en este caso DB. # El servicio app solo iniciara si el servicio debe inicia correctamente. depends_on: - db # Puerto del contenedor expuesto. ports: - "3000:3000" db: image: mongo
Docker compose vs Dockerfile
Dockerfile es lo que se usa para crear una imagen de contenedor, y Docker Compose es lo que se usa para implementar una instancia de esa imagen como contenedor.
Un ejemplo rápido de esta diferencia: https://docs.docker.com/compose/gettingstarted/
Docker compose en equipo
Si se trabaja en equipo con docker es conveniente usar un archivo compose override el cual sobre escribirá la información del compose original; y mantendrá los datos de configuración del compose original en caso de que en el compose override no encuentre los datos de configuración. En otras palabras, le da prioridad al archivo de compose override.
Comandos importantes
- docker-compose build: construir los servicios.
- docker-compose up: levantar los servicios.
- docker-compose up -d: levantar los servicios en dettach.
- docker-compose down: bajar los servicios.
- docker-compose logs: permite ver los logs.
- docker-compose logs app: permite ver los logs solo de un contenedor del compose.
- docker-compose logs -f app: se hace seguimiento de los logs.
- docker-compose exec app bash: ingresar al shell del contenedor app.
- docker-compose ps: ver los contenedores generados por docker compose.
- touch docker-compose.override.yml: crear archivo para sobre escribir el original.
- docker-compose up -d –scale app=2: escalar dos contenedores de app.
Docker avanzado
Administrando ambiente de Docker
Una vez que se ha usado docker constantemente es recomendable eliminar los archivos, imágenes, cache, contenedores, etc. que no se usaran. Para esto se tienen los siguientes comandos.
- docker container prune: elimina todos los contenedores que no se están ejecutando o están apagados.
- docker rm -f $(docker ps -aq): elimina todos los contenedores incluyendo los que se están ejecutando (-q: muestra por ID, -a: muestra los ocultos, -f: fuerza bruta).
- docker network prune: elimina las redes que no se están usando.
- docker volume ls: lista los volumenes.
- docker volume prune: elimina los volúmenes que no se están usando.
- docker system prune: elimina todos los contenedores, imágenes, redes y cache.
- docker run -d –name app –memory 1g nombreApp: se limita el uso de memoria.
- docker stats: se muestran los recursos que consume docker en el sistema.
SHELL vs EXEC: detener contenedores correctamente
Cuando se tiene un contenedor recién creado o activo este debería estar ejecutando algún proceso para mantenerse en funcionamiento. Si el proceso principal se detiene entonces el contenedor debería dejar de funcionar.
Cuando se usa el comando docker stop <name-container> docker manda una señal estándar de linux llamada SIGTERM al proceso donde después de un tiempo el proceso se debería detener; pero si el proceso no se detiene enviara una señal llamada SIGKILL que garantiza que el proceso se terminara forzadamente.
Existen dos formas de definir CMD:
- CMD /process.sh: se genera el shell como un shell hijo del principal.
- CMD [“/process.sh”]: manera recomendada.
La linea CMD ejecuta un archivo bash a través de un shell , esta forma de expresar esta línea (primer forma) se conoce como shell form y esto genera que al momento de detener un contenedor que esté ejecutando un proceso por shell form necesariamente tendrá que usar SIGKILL; para evitar esto, el CMD debe ejecutar el proceso main de form exec form. Es decir, debería estar configurado cómo la segunda manera para que el contenedor tenga tiempo a que el contenedor procese las solicitudes restantes y pueda hacer un great full shutdown.
Comandos importantes
- docker stop <name><name>: envía la señal SIGTERM al contenedor.</name>
- docker kill <name>: envía la señal SIGKILL al contenedor. </name>
ENTRYPOINT vs CMD: contenedores ejecutables.
ENTRYPOINT permite ejecutar la configuración de un contenedor como ejecutable; que tiene dos formas:
- exec form: ENTRYPOINT [“executable”, “param1”, “param2”]
- shell form: ENTRYPOINT command param1 param2
CMD son instrucciones dentro del Dockerfile que si se llega a colocar más de uno tomará el último y ese tomará efecto en la ejecución. Hay tres formas de usarlo:
- exec form: CMD [“executable”,”param1″,”param2″]
- cómo parametro del ENTRYPOINT: CMD [“param1″,”param2”]
- shell form: CMD command param1 param2
Contexto de build
Existe un archivo .dockerignore que funciona de manera similar que .gitignore. En otras palabras, omite archivos locales hacia un contenedor.
Multi-stage build
Para que no este todo el código en la imagen entonces Docker permite crear diferentes imágenes. Ya que se pueden crear diferentes archivos dockerfile o crear diferentes builds dependientes en un dockerfile. Por ejemplo, supongamos que :
- El archivo Dockerfile de producción contiene 2 “fases de build” que se pueden pensar cómo hacer 2 build seguidos, en donde al final la imagen construida contendrá lo especificado en el ultimo de los build.
- El primer build corre un test que verifica que todo funcione bien. El segundo build construye la imagen final aprovechando el caché de las capas del primer build.
- Al final el segundo build es solo una extracción de lo que nos intereza del primer build.
- Lo importante en este caso especifico es que si el test falla, entonces el build 2 no se corre, lo que significa que la imagen no se construye.
Docker-in-Docker
Usar Docker dentro de un contenedor es posible con la ayuda de sockets; con bind mount se accede al archivo docker socket a la máquina anfitriona; y accediendo a el desde el otro Docker el cliente puede accederlo.
Comentarios
Publicar un comentario