Portada! Que es Docker y como usarlo!

epic

Pro
Se incorporó
11 Febrero 2007
Mensajes
846
01-primary-blue-docker-logo.png


Hola a todos, hace unos meses me había hecho un documento sobre lo que es Docker, su arquitectura, sobre las imágenes y todo lo relacionado a contenedores (volumenes, redes ,etc) y sus comandos, mas lo que era docker-compose.... lo comparto para ver si a mas de aguno le sirve o si tienen dudas vayamos en este mismo hilo compartiendo y ayudándonos. :)




Que es Docker

Docker por definición es una herramienta que permite desplegar aplicaciones en contenedores de forma rápida y portable, en otras palabras Docker es capaz de generar “aplicaciones de bolsillo” debido a que su arquitectura utiliza contenedores e imagines, en una imagen se definen toda la configuración que necesita la aplicación para funcionar y en un contenedor se vuelve realidad.

Eso mismo permite desplegar y escalar las aplicaciones, porque todos van a tener la misma configuración que esta definida en la imagen, adicional permite destruir o recrear las imágenes o contenedores de una manera muy fácil ya que todo esta basado en las imágenes y esto permite que todo sea muy rápido.​

  • Aplicaciones de bolsillo​
  • Desplegar y escalar aplicaciones​
  • Destruir y recrear​


Por Ejemplo: Crear un contenedor de apache​

$ docker run -d -p 80:80 –name web httpd


run= para crear un contenedor por primera vez
-d = Para que lo corra en el fondo
-p = definir el puerto que tendrá abierto y por el que escuchara
--name = Nombre que se le dará al contenedor



Ahora si se quiere destruir:​
$ docker rm -fv web


rm = Para eliminar el contenedores
-fv = Para forzar la eliminación y para eliminar el volumen


Arquitectura de Docker


Docker para funcionar necesita de un Host y en el Host se instala el servicio de Docker llamado “Docker Deamon” el cual presta todo el servicio.

También existe un Docker CLI, que son comando que se escriben en la terminal, escribiendo “docker” nos conectamos por medio de la API hacia el servidor y por medio del servidor utilizando la API para contestarle al cliente.

La API es el canal de comunicación entre el docker client y el docker server, server y client están en el docker host, osea en la misma maquina, pero el server e un servicio que esta corriendo.

Docker CLI es el cliente que se comunica con la API a través de la API.

Con el Client podemos manejar:​
  • Contenedores​
  • Imágenes​
  • Volumen​
  • Redes​
Que es una imagen

Las imágenes se encuentran dentro del Docker Host, se pueden pensar como paquetes que contienen toda la configuración necesaria para que funcione la aplicación.

Las imágenes se componen por capas, pueden tener “N” capas y serán de SOLO LECTURA.


Este ejemplo tiene 3:

Capa 1 – FROM → Indicar que Sistema Operativo tendrá
Capa 2 – RUN → Que viene luego del sistema operativo, por ejemplo apache
Capa 3 – CMD → Es lo que levantara el servicio de la capa 2

Las capas se crean utilizando un archivo llamado “Dockerfile”.

Dockerfile: Puede llamarse de otras maneras pero este nombre de archivo es el que busca docker​

Código:
FROM centos:7
RUN yum -t httpd
CMD [“apachectl”, “-DFOREGROUND]
Código:



Es importante que la linea del CMD ejecute un servicio en primer plano, osea que se quede pegado en la consola, ya que de esta manera el contenedor se mantendrá “vivo”, si el CMD muere la aplicación también.

Que son los Contenedores

Es una capa adicional que traerá una ejecución en tiempo real de las capas anteriores(imágenes), esta capa si es de escritura ya que es de ejecución. Todos los cambios que hagamos en la capa 4 sera temporales ya que son modificaciones realizadas en el contenedor y no en la imagen y es por eso que no se recomienda modificar la capa 4 ya que es temporal y si eliminamos el contenedor toda la configuración se perderá.

El contenedor además de contener las capas anteriores también tiene:

Volúmenes → Sirve para persistir la data
Redes → Para lograr comunicar contenedores entre si

Contenedor V/S Maquina Virtual

Los contenedores son instancia en ejecución de una imagen, se crea a partir de una imagen, es un proceso mas del sistema, osea utilizará la misma RAM, el mismo disco y la misma CPU del Host. Al ser un proceso esto significa que utilizará una mínima cantidad de memoria al contrario de una MV.

Si se compara con una MV, el peso es mucho mayor ya que se instala el software para virtualizar, tener la ISO del S.O crear un disco virtual, luego instalar el S.O , agregar memoria y CPU y todo eso ya no es un proceso dentro del Host, si no mas bien una nueva maquina completa dentro del host.

Por ejemplo si uno quiere instalar apache y utiliza la tecnología de virtualizar e instalamos ubuntu, este además instala una serie de cosas como por ejemplo un firewall, en ocasiones entorno gráfico, navegadores, librerías, actualizaciones y muchos otros servicios… si lo único que se requiere es apache.

Una VM puede pesar quizás 40GB, poner el computador o el servidor lento porque consume demasiada memoria o CPU, en cambio un contenedor es un proceso aislado que corre en nuestro host consumiendo muy poco recursos y con una instalación muy rápida ya que se tendrá la imagen con todo lo necesario, en cambio una VM se tendrá que volver a instalar todo el S.O nuevamente y luego todas las aplicaciones necesarias.

En definitiva eso es en parte lo que resuelven los contenedores, un proceso mucho mas liviano, ya que solo se levanta el servicio que se necesita, una instalación mucho mas rápida ya que todo esta en la imagen y el contenedor se crea en base a ella, pudiendo tener una imagen de apache y otra de mysql y entre los 2 servicios consumir a lo mas 500mb de memoria v/s 3gb de una VM.


IMAGENES
Imágenes Oficiales

Hay mucho software libre como por ejemplo apache, jenkins, mongo, php, mysql, etc. La gente que creo estos software son los que crean las imágenes oficiales de sus softwares y en estas imágenes oficiales vienen toda la configuración que necesita un contenedor para funcionar.

Hay una web oficial donde se almacenan todas las imágenes llamada https://hub.docker.com , y es desde acá donde se podrán descargar las imágenes que uno necesite.

Con el siguiente comando se descargara la imagen de mongo:

$ docker pull mongo​


se podrá observar que se descarga la ultima versión con el nombre “tag: latest”, los tag son etiquetas que indican la versión de la imagen, sirven para versionar la aplicación. Si al momento de descargar la imagen no se le define un tag, por defecto se descargará la ultima versión que la gente de mongo haya subido a docker hub. Si por el contrario se le define un tag, se descargará esa versión especifica de la aplicación con esa configuraron especifica.

$ docker pull mongo:7.0.0-rc6-jammy​

Todas las versiones de las imágenes se encuentran en la pagina dockerhub (NO se pueden inventar tag) si hay una versión que no existe, entonces recién uno podría crear imágenes personalizadas, pero si existe lo mejor es descargarla, ya que en teoría cuenta con todo lo necesario para que funcione de forma correcta pues esta mejor optimizada, tiene las mejores practicas y fue creada por la misma gente de la mongo (o de mysql, apache, etc).

Cuando uno hace un pull comienza el proceso de descarga de la imagen y este proceso va descarando capa por capa, por ejemplo si uno descarga la versión httpd:2.4 descargara 10 capas y si luego descargamos la versión httpd:2.4.5 docker se dará cuenta que ya tenemos la versión anterior y solo descargara las capas distintas de apache, osea las que hacen falta.

Con el siguiente comando podremos ver las imagenes descargadas:

$ docker images​

Con este comando se listaran todas las imágenes que se han descargado con el comando “pull” y mostrara también los tag de cada una de ellas.

*** Si tratamos de descargar una versión de imagen que ya tenemos, docker nos dirá que ya la tenemos y no la descargará nuevamente.

Imágenes dangling

Si se descargo por ejemplo la versión mysql , esto descargará la ultima versión automáticamente y quedará almacenada en el servidor, si al tiempo después se hace otro pull a mysql y existe una nueva versión, entonces docker descagará solamente las capas faltantes y creará una nueva versión con el tag de “latest” y dejará la versión antigua sin tag (<none>) quedando como “huérfana”, ya que no pueden haber 2 imágenes con el mismo tag.

Creación de Imágenes

En caso de no encontrar una imagen que necesitemos se podrá crear una imagen personalizada, por ejemplo crear una imagen que contenga Apache y PHP:

Para esto se creara un archivo llamado Dockerfile:

FROM centos:7
RUN yum -y install httpd php
CMD apachectl -DFOREGROUND​

Para construir una imagen tomando como referencia el Dockerfile:

$ docker build --tag apache-centos .​

Con la primera capa se instalara Centos versión 7 y luego con el comando RUN se comenzará a instalar los paquetes que necesitamos (dentro de Centos), si la instalación solicita intervención humana para instalar los paquetes docker arrojará un error, por lo tanto se agrega el comando “-y” en el install.

Luego con el CMD mantenemos el servicio de apache corriendo en primer plano, si no lo hacemos el contenedor se creará y se “morirá” de manera inmediata.

Y con el siguiente comando se podrá ver la historia de la imagen:

$ docker history -H apache-centos --no-trunc​

Donde se podrán visualizar las capas de la imagen, donde se observaran las capas que traía la imagen de Centos mas la que le agregamos nosotros.



Creación de un contenedor en base a la imagen anterior

Para crear el contenedor:

$ docker run -d --name -p 80:80 apache apache-centos​

Para poder ver los contenedores que se están ejecutando es con el siguiente comando:

# docker ps​

Y para ver todos los contenedores, (ejecutándose y detenidos):

$ docker ps -a​

Para eliminar un contenedor:

$ docker rm -fv apache-centos​

De esta manera de manera simple podemos crear una imagen personalizada llamada “apache-centos” y luego levantar un contenedor llamado “apache”.
Para probar y visualizar la web simplemente hay que ingresar a http://localhost del servidor

Introducción Dockerfile

Es el archivo donde se define la configuración de la imagen y se verán todos los conceptos para entender como se construye una imagen.

FROM →Sistema Operativo que queremos
RUN → Instrucciones que se ejecutan en la terminal, cualquier comando que este disponible en linux(touch, mkdir, rm, adduser, etc)​
COPY/ADD → Copiar archivos
ENV → Variables de entorno
WORKDIR → Directorio de trabajo
LABEL → Etiquetas
USER → que usuarios ejecutara la tarea
VOLUME → Para persistir la data
CMD →

Dockerfile – FROM / RUN/COPY / ADD

Se creará una imagen utilizando estos 3 argumentos:

Se creara un archivo llamado index.html (con el texto PRUEBA en el interior) al mismo nivel de donde se encuentra el archivo Dockerfile

FROM centos:7
RUN yum install httpd -y
COPY index.html /var/www/html
# ADD index.tar /var/www/html
CMD apachectl -DFOREGROUND​
Se construirá la imagen:

$ docker build -t apache2 .​

Levantar el contenedor:​

$ docker run -d --name apache2 -p 80:80 apache2​

Luego se ingresara a http://localhost y la pagina a cargar debería estar el texto “PRUEBA”. De esta manera podemos meter archivos o toda una web dentro de la imagen y una vez levantemos el contenedor estará todo listo.

El comando ADD nos permite agregar URL, entonces descargara el archivo y lo dejara dentro del contenedor, también se puede copiar un archivo .tar y el contenido sera extraído automáticamente dentro del contenedor en la ruta especificada.

*** ADD tiene cierta lógica para descargar archivos remotos y extraer archivos

Aunque también cumple la función de agregar el archivo local dentro de la imagen pero para copiar del local al contenedor se recomienda utilizar COPY.

Dockerfile ENV / WORKDIR

Agregaremos nuevos argumentos al mismo Dockerfile creado anteriormente:


- ENV hace referencia a la opción que permite definir variables de entorno que pueden utilizarse en el interior de los contenedores.​
- WORKDIR significa donde se esta trabajando actualmente dentro del contenedor.

FROM centos:7
RUN yum install httpd -y
WORKDIR /var/www/html
COPY index.html .
ENV palabra Prueba_Docker_WORKDIR
RUN echo “$palabra” > /var/www/html/prueba.html
CMD apachectl -DFOREGROUND​
Se construirá la imagen:

$ docker build -t apache3 .​

Levantar el contenedor:​

$ docker run -d --name apache3 -p 80:80 apache3​

Luego se ingresara a http://localhost/prueba.html y la pagina a cargar debería estar el texto “Prueba_DOCKER”.

La variable llamada “palabra” tomará el texto “Prueba_Docker” y luego en la linea de RUN se esta pasando el contenido de la variable “palabra” al archivo “prueba.html”.

Además con el comando WORKDIR se podrá indicar en que directorio de trabajo se estará trabajando dentro del contenedor, entonces luego en el COPY se puede poner un “.”


Dockerfile LABEL / USER / VOLUME

- LABEL es una etiqueta que normalmente va al inicio.
- USER sirve para indicar quien ejecutara la siguiente tarea.
- VOLUME sirve para mantener la data al momento de eliminar el contenedor y así no perderla.​

FROM centos:7
LABEL version=1.0
RUN yum install httpd -y
WORKDIR /var/www/html
COPY index.html .

RUN echo “$(whoami)” > /var/www/html/user1.html
RUN useradd test
USER test
RUN echo “$(whoami)” > /tmp/user2.html
USER root
RUN cp /tmp/user2.html /var/www/html/user2.html

ENV palabra Prueba_Docker_WORKDIR
RUN echo “$palabra” > /var/www/html/prueba.html
CMD apachectl -DFOREGROUND​

Se construirá la imagen:​

$ docker build -t apache4 .​
Levantar el contenedor:

$ docker run -d --name apache4 -p 80:80 apache4​

El usuario root deja un archivo de user1.html en “/var/www/html” y luego se crea el usuario test, nos cambiamos al usuario test y creamos el archivo user2.html en “/tmp/user2.html”, luego volvemos a ser root y copiamos el archivo “user2.html” a “/var/www/html” (porque el usuario test no puede escribir en este directorio).

Luego se ingresara a http://localhost/user1.html y la pagina a cargar debería estar el texto “root” y en http://localhost/user2.html el contenido deberá ser “test”.

Los VOLUME se verán mas adelante, en el capitulo de Contenedores.

Dockerfile CMD / dockerignore

- CMD se utiliza para mantener vivo al contenedor, puede ser un comando o un script
- dockerignore es un archivo oculto y sirve para ignorar cualquier cosa que tenga el directorio de trabajo actual y que no queramos incluir en la imagen.

$ nano run.sh​
#!/bin/bash
echo “Iniciando contenedor…”
apachectl -DFOREGROUND
FROM centos:7
LABEL version=1.0
RUN yum install httpd -y
WORKDIR /var/www/html
COPY index.html .

RUN echo “$(whoami)” > /var/www/html/user1.html
RUN useradd test
USER test
RUN echo “$(whoami)” > /tmp/user2.html
USER root
RUN cp /tmp/user2.html /var/www/html/user2.html

ENV palabra Prueba_Docker_WORKDIR
RUN echo “$palabra” > /var/www/html/prueba.html

COPY run.sh /run.sh

CMD sh /run.sh

Se construirá la imagen:​

$ docker build -t apache5 .​

Levantar el contenedor:​

$ docker run -d --name apache5 -p 80:80 apache5​
Para ver si el contenedor esta corriendo y validar el “COMMAND”

$ docker ps --no-trunc

Si revisamos los logs del contenedor también se observara la linea que se agrego en el script “Iniciando contenedor...”​

$ docker logs apache5
Cuando trabajamos con el archivo dockerignore, lo primero que debemos hacer es crearlo con un “.” al comienzo ya que es un archivo oculto y en su interior escribir el nombre de los archivos o carpetas que no queremos que estén en nuestra imagen.

$ nano .dockerignore​
.git/
node_modules/
dist/
*/prueba*
De esta manera creamos una imagen mas liviana dejando solo lo necesario para nuestra aplicación.

Una imagen con todos los argumentos

En esta ocasión se trabajará con una imagen directamente de nginx

FROM nginx
LABEL version=1
RUN useradd test
WORKDIR /usr/share/nginx/html
COPY index.html .
ENV archivo docker
RUN echo “$archivo” > ./env.hmtl
EXPOSE 90
USER test
RUN echo “Soy el usuario $(whoami)” > /tmp/yo.html
USER root
RUN cp /tmp/yo.html .
VOLUME /var/log/nginx
CMD nginx -g 'daemon off;'
Ahora se construirá la imagen en base a la información del Dockerfile

$ docker build -t nginx:v1 .
Ahora se ejecutara un contenedor en base a la imagen creada.

$ docker run -d -p 80:80 --name nginx nginx:v1
http://localhost → Debería mostrar el contenido del archivo index.html
http://localhost/env.html → Debería decir “docker”
http://localhost/yo.html → Debería decir “Soy el usuario test”

Eliminar Imágenes

$ docker tmi <nombre de la imagen> <nombre imagen> <nombre imagen>

Cambia de nombre el Dockerfile

Por defecto al construir una imagen docker buscar el archivo Dockerfile, pero en ocasiones podríamos cambiarle el nombre y para que docker lo encuentre se le agrega al comando el “-f”​

$ docker build -t test -f mydockerfile .


Multi-Stage Build

Existe una características que permite utilizar varios FROM dentro del mismo dockerfile para construir imágenes diferentes por tema de dependencias. Por ejemplo:​

FROM centos:7 as test

RUN fallocate -l 10M /opt/file1
RUN fallocate -l 20M /opt/file2
RUN fallocate -l 30M /opt/file3

FROM alpine
COPY --from=test /opt/file1 /opt/myfile


Este ejemplo es muy básico, pero para que se logre entender la idea del multi-stage, se construye la primera imagen en base a Centos 7 y se le asigna un alias llamado “test”, luego se utiliza el comando “fallocate” para crear archivos de distintos tamaños en diferentes rutas. Si solamente creamos la imagen con la primera parte(Color verde) tendremos como resultado una imagen de aproximadamente 260MB ya que centos pesa 200mb mas los 3 archivos sumarían en total 60 mb aprox.

Si luego agregamos el segundo from y creamos la imagen no daremos cuenta que solamente se creara una imagen de unos 17MB ya que la imagen de alpine es 7mb mas el archivo “file1” de 10mb quedaría una imagen resultante de unos 17MB.

Con esto nos damos cuenta que la imagen final es la del segundo FROM, donde en el primer FROM se puede hacer todo el trabajo de instalar dependencias, desempaquetar archivos e instalar para que luego se copie el resultado final al segundo FROM y la imagen quede con el mínimo de características.

Buenas Practicas

Las buenas practicas para construir un contenedor serian las siguientes:

- Efímero: Hay que pensar que la idea de docker es que el contenedor se pueda destruir, lo que significa que el servicio que esta corriendo se debe poder destruir con facilidad y luego poder volver a levantarlo rápidamente.

- Un solo servicio: En teoría debe haber un solo servicio instalado por contenedores, por ejemplo un contenedor con nginx y otro contenedor con mysql… nunca juntos.

- dockerignore: Utilizar el archivo de .dockerignore para evitar meter archivos innecesarios dentro de nuestra imagen.

- Pocas Capas: Es importante en lo posible reducir el numero de capas que tiene la imagen, la idea es que sea una imagen pequeña con pocas capas.

- Multi Linea: Cuando una sola linea es demasiado larga se recomienda sdividilar en diferentes lineas finalizándola con “\” y continuando abajo.

- No instalar paquetes innecesarios, por ejemplo no instalar ssh, nano, vim, etc. las imágenes están dedicadas a un solo servicio.

- Es recomendable utilizar LABEL para detallar versiones, descripciones, etc.​

FROM nginx
ENV dir /usr/share/nginx/html/test.txt

RUN \
echo “1” » $dir & \
echo “2” » $dir & \
echo “3” » $dir
En este ejemplo estamos utilizando una sola capa para ejecutar los 3 echo y al mismo tiempo utilizamos Multi lineas separadas por el símbolo “\” y para finalizar utilizamos una variable de entorno para simplificar la linea del directorio.

 

Archivo adjunto

  • Manual Docker.docx
    421,1 KB · Visitas: 217
Última modificación por un moderador:

epic

Pro
Se incorporó
11 Febrero 2007
Mensajes
846
CONTENEDORES

1.- Los contenedores son una instancia de ejecución de una imagen
2.- Son temporales, no se deben hacer cambios en el contenedor, ya que si el contenedor se elimina se perderán los datos. Si queremos que un cambio sea persistente debemos definirlo en el Dockerfile, en la imagen.
3.- Capa de RW.
4.- Se pueden crear varios contenedores a partir de una sola imagen.

Mapear Puertos

Los contenedores se listan de la siguiente manera:


$ docker ps

o

$ docker ps -a

Para crear un contenedor, necesitamos como requisito una imagen.

Para crear un contenedor en segundo plano ejecutamos el siguiente comando:​

$ docker run -d nginx
$ docker ps

Al ejecutar el comando “docker ps” nos mostrara los contenedores que se están ejecutando cada uno con sus respectivos ID, el nombre de la imagen con la que se creo, el CMD, la fecha de creación del contenedor, los puertos que esta escuchando el contenedor (80/tcp) y el nombre que se le dio (si no se la da un nombre Docker le asignara uno automáticamente).

Con este comando se levantará el contenedor , pero si revisamos el navegador en localhost no se vera nada ya que hace falta mapear el puerto del contenedor para que sea accesible desde fuera:​

$ docker run -d -p 80:80 nginx
Ahora existirán 2 contenedores, el primero y el de ahora, pero solo tendremos acceso al navegador al segundo contenedor ya que le indicamos que todas las peticiones que ingresen a nuestro equipo por el puerto 80 sean enviados al puerto 80 del contenedor (-p 80:80). También podemos utilizar cualquier puerto de nuestra maquina y que apunte al puerto 80 del contender:

$ docker run -d -p 9090:80 nginx
Y ahora tendremos 3 contenedores, uno de ellos que no es accesible, otro que es accesible por el puerto 80 y otro por el puerto 9090

http:localhost

Así podremos levantar la cantidad de contenedores que necesitemos, siempre y cuando los puertos no se repitan y los nombres de los contenedores sean distintos.

Ahora si queremos eliminar los contenedores lo realizamos con el comando “rm”:​

$ docker rm <nombre del contenedor 1> <nombre del contenedor 2 > <nombre del contenedor 3> -f
f = para forzar la eliminación, si el contenedor se esta ejecutando y no lo hemos detenido con el comando “docker stop <contenedor>” entonces se debe forzar la eliminación.

Ahora al entrar a https://localhost ya no se visualizará nada, ya que los contenedores han sido eliminados, pero al volver a ejecutar el comando de “docker run….” los contenedores se crearan nuevamente en cuestión de segundos y se tendrán nuevamente los servicios operativos, esto gracias a que tenemos la imagen en nuestro equipo, imagen que podemos crear con nuestros archivos y aplicativos ya dentro.​


Renombrar / Iniciar / Reiniciar / Detener / Ingresar / Eliminar

Algunos de los comandos importantes para utilizar en el día a día son los siguientes:

Rename:
Si queremos cambiarle el nombre a un contenedor utilizamos el siguiente comando:

$ docker rename <nombre_contenedor> <nuevo_nombre>


stop:
Si queremos detener un contenedor utilizamos el siguiente comando:

# docker stop <contenedor>


start:
Si queremos iniciar un contenedor detenido utilizamos el siguiente comando:

$ docker start <contenedor>

restart:
Si queremos reiniciar un contenedor utilizamos el siguiente comando:

$ docker restart <contenedor>

exec:
Si necesitamos ingresar al contenedor utilizamos el siguiente comando y para salir escribimos “exit”:

$ docker exec -it <contenedor> bash

rm:

$ docker rm <nombre del contenedor 1> <nombre del contenedor 2 > <nombre del contenedor 3> -f

o

$ docker rm $(docker ap) -fv

El segundo comando eliminará todos los contenedores, forzándolos si es necesario y además también eliminara los volúmenes.

Variables de Entorno

Son variables que se pueden acceder desde cualquier parte del contenedor, las podemos definir en un Dockerfile:

FROM centos:7
ENV prueba 1234
RUN useradd test

Luego entramos al contenedor y podemos visualizar la variable

$ docker build -t env .
$ docker run -dti --name env env
$ docker exec -it env bash
$ echo $prueba

También podemos pasar un valor de variable desde el propio “docker run…”

$ docker run -e prueba1=4321 -dti --name env2 env
$ echo $prueba
$ echo prueba1
$ env

Utilizamos la misma imagen que ya tenia la primera variable de entorno, pero ahora al ejecutar un contenedor en base a esa imagen, le pasamos otra variable desde el comando docker run. Con esto podemos agregar variables desde el Dockerfile y que quedaran en la imagen y también podemos agregarle variables al propio contenedor al momento de levantarlo, pero que no existirá en la imagen base.

Contenedor MySQL

Como toda imagen la podemos descargar desde DockerHub, detallando el “:tag” o sin el y de esta manera descargará siempre la ultima versión(latest):

En la misma pagina de DockerHub aparecen las indicaciones de como se instalan las aplicaciones y cuales son las variables de entornos validas.

$ docker run -d --name my-db1 -e MYSQL_ROOT_PASSWORD=1234567 -e MYSQL_DATABASE=docker -e MYSQL_USER=docker -e MYSQL_PASSWORD=87654321 -p 3306:3306 mysql:5.7

Con esto estamos instalando la versión 5.7 de MySQL y asignándole un password al usuario ROOT, creando un usuario llamado docker con password 87654321 y creando tambien una BD llamada docker todo esto mediante variables de entorno, variables que ya existen y fueron sacadas desde la pagina de mysql en dockerhub y por ultimo le indicamos que mapee el puerto 3306 de nuestra maquina al contenedor con el objetivo de poder ingresar a la base de datos utilizando localhost.

Si queremos ver que ocurre mientras se inicia el contenedor podemos ver los logs:

$ docker logs my-db1

Una vez levantado el contenedor ya podremos ingresar a el y revisar la BD:

$ mysql -u root -p1234567 -h 127.0.0.1

o

$ mysql -u docker -p87654321 -h 127.0.0.1

Contenedor Apache / nginx / Tomcat

A continuación crearemos un contenedor para Apache, nginx y Tomcat

$ docker run -d -p 7777:80 –name nginx nginx

http://localhost:7777

$ docker run -d -p 8888:80 –name apache httpd

http://localhost:8888

$ docker run -d -p 8889:8080 tomcat:8.0



Consumo de RAM Y CPU

Para poder visualizar cuanto están consumiendo los contenedores se ejecuta el siguiente comando:

$ docker stats

Y nos mostrará el consumo de memoria ram , cpu y de red /I/O de cada contenedor que se este ejecutando, lo cual es bastante útil para conocer que contenedor es el que esta consumiendo mas recursos y luego poder limitar estos recursos para que no colapse la maquina host.​

Administrar usuarios

En esta ocasión crearemos un usuario y una variable de entorno:

FROM centos:7
ENV prueba 1234
RUN adduser test
USER test

$ docker build -t centos:prueba .
$ docker run -d -ti –name prueba centos:prueba

Y ahora ingresamos al contenedor:​

$ docker exec -it prueba bash

Y podremos observar que al iniciar el contenedor iniciará automáticamente con el usuario “test” y no con el usuario “root”, eso es por la linea “USER test” al final del Dockerfile.

Si quisieras ingresar al contenedor como root deberíamos indicarlo en la linea de ingreso al contenedor (docker exec):​

$ docker exec -u root -it prueba bash


Limitar recursos a un contenedor

Ahora se controlaran los recursos que un contenedor puede consumir, crearemos un contenedor de mongo para hacer las pruebas:​

$ docker run -d –name mongo mongo
Y con el siguiente comando se podrán observar los recursos que esta consumiendo el o los contenedores:

$ docker stats
Como se puede ver esta consumiendo 75.11MB de 15.51GB lo cual es un 0,47% de la memoria ram del equipo, al mismo tiempo se observa que consume un 2,18% de CPU.

Si queremos limitar el uso de memoria se agrega el comando “-m”:​

$ docker run -d -m 500mb –name mong2 mongo
$ docker run -d -m 2gb –name mong3 mongo
$ docker stats
Y ahora se puede observar que el segundo contenedor tiene solo 500mb de memoria para utilizar, por lo tanto esta utilizando el 13,46% y el tercer contenedor tiene 2GB de limite… Como en ocasiones hay contenedores que pueden utilizar demasiada RAM, es mejor mantenerlos controlarlos y así evitar que la maquina host colapse.

Para limitar la CPU podremos ver primero cuantas tiene la maquina host con el comando y observaremos donde indique “cpu cores”:​

$ lscpu | grep 'CPU(s)'

En mi caso tengo 8 cpu’s por lo tanto podría asignar 2 cpu al contenedor:​

$ docker run -d -m 1gb –cpuset-cpus 0-1 –name mongo4 mongo

De esta manera le indicamos que el contenedor 4 solo podrá utilizar la CPU 0 y la 1, dejando libre o para otros contenedores la 2 y 3.

En el comando stats no hay algo que indique cuantas cpu esta usando el contenedor.

Acabo de levantar 41 contenedores mongo utilizando la cpu 3 “--cpuset-cpus 3”:​

docker run -d -m 1gb –cpuset-cpus 3 mongo

Si repetimos la linea de “docker run” muchas veces y de forma rápida podremos ver en otra ventana como el comando htop muestra el aumento significativo en el consumo de la cpu 3, alcanzando hasta el 100%, para luego cuando se detienen las creaciones de contenedor bajar y mantenerse en un % mayor a como estaba cuando no existían contenedores.

Y si ejecutamos un htop veremos que la CPU 3 alcanzo los 10.8% de consumo:​

$ htop

Luego si eliminamos todos los contenedores, esperamos un momento y hacemos otro htop:​

$ docker rm $(docker ps -aq) -f
$ htop

Copiar archivos a un contenedor

En ocasiones necesitaremos copiar archivos de la maquina hacia dentro del contenedor o desde el contenedor hacia afuera, estas 2 cosas se hace con el comando “docker cp”:

host → contenedor

Crearemos un archivo llamado index.html (y escribimos algo dentro) en la maquina host y la copiaremos al contenedor apache en el directorio /tmp:​

$ docker run -p 80:80 -d --name apache httpd
$ docker cp index.html apache:/usr/local/apache2/htdocs
$ docker exec -it apache bash
$ cat /tmp/index.html

Y podremos ver el archivo que creamos con su contenido o si ingresamos por el navegador http://localhost se nos cargara una pagina con el mensaje que nosotros escribimos, ya que sobre escribira el index por defecto de apache.

contenedor → host

Ahora copiaremos un archivo del contenedor hacia nuestra maquina, esto puede servir para cuando queramos rescatar por ejemplo un log del contenedor y revisarlo o mandarlo por mail.​

$ docker cp apache:/var/log/dpkg.log .

Con este comando copiara el archivo “dpkg.log” en el directorio actual donde estoy parado.


Convertir un contenedor en una imagen

Con el comando commit podemos tomar el estado de un contenedor que esta corriendo y transformarlo en una imagen, en ocasiones podrías entrar a un contenedor y hacer cambios y como el contenedor es efímero y al eliminarse se pierden los datos entonces se podría hacer un “Docker commit” lo cual no es muy buena practica ya que para eso podemos utilizar volúmenes, pero de todas formas se explicara el comando.​

FROM centos:7
VOLUME /opt/volumen
$ docker build -t centos-test .
$ docker run -dti –name centos centos-test

imaginemos que entramos al contenedor y hacemos algunos cambios dentro de el (cosas que no debería ser, pro puede ser necesario):​

$ docker exec -it centos bash
$ cd /opt/
$ touch file1.txt
$ cd volumen/
$ touch file1.txt

Entonces entramos al contenedor y creamos un archivo llamado file1.txt en /opt y otro file1.txt en /opt/volumen.

Luego ejecutamos el comando para transformar el contenedor en una imagen:​

$ docker commit centos centos-resultante

Ahora veremos las imágenes:​

$ docker images

Y veremos la nueva imagen creada a partir del contenedor con los file1.txt dentro.​

$ docker run -dti –name centos2 centos-resultante
$ docker exec -it centos2 bash
$ cd /opt

Levantamos el contenedor en base a la nueva imagen e ingresamos a el para observar que ahora el contenedor levantado tendrá el archivo “/opt/file1.txt”, pero NO tendrá el archivo “/opt/volumen/file1.txt”, todo lo que este dentro de un volumen en dockerfile no se almacenará en un commit. se guardará solamente lo que esta fuera de un volumen, así que ojo cuando hagan un commit y tengan información en volúmenes.


Sobre escribir el CMD de una imagen sin un Dockerfile

Obtendremo el bash por defecto “/bin/bash”​

$ docker run -dit centos:7

Ahora para sobre escribirlo:​

$ docker run -dit centos echo hola mundo

Ahora el bash cambiará, pero el contenedor obviamente se va a morir ya que nada lo mantendra arriba:​

$ docker ps -a

Como se observa el CMD cambio a “echo hola mundo”:

Destruir contenedores automáticamente

Acá podremos crear contenedores que se auto destruyan con el comando “--rm”:​

$ docker run –rm ---name centos-dest -it centos:7
Con este comando se creará un contenedor y entraremos a el, pero al escribir exit y salirnos del contenedor automáticamente se destruirá (ojo que la linea del “docker run” ya no va el -d).

Cambiar Document root de Docker

En el siguiente directorio se encuentra toda la jerarquía de directorios que Docker crea para guardar las imagenes, redes , etc.​

$ docker info | grep -i root
$ cd /var/lib/docker

Por ejemplo cuando escribimos “docker images” la data que aparece es el resultado a la consulta realizada a la carpeta “image” del directorio “var/lib/docker/image”.

Para cambiar el documento root de Docker editamos el siguiente archivo:​

$ nano /lib/systemd/system/docker.service

Y en la linea “ExecStart” le agregamos al final “--data-root /opt” y guardamos:​

ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --data-root /opt

Y reiniciamos el servicio:​

$ systemctl daemon-reload
$ systemctl restart docker

Si ahora hacemos un “docker images” no existirá ninguna imagen, ya que hemos cambiamos la ruta y la carpeta esta vacía.


Podríamos mover la carpeta “docker” (/var/lib/docker) hacia “/opt”, cambiar el document root por “--data-root /opt/docker” y luego volver a recargar el servicio y ya tendríamos todas las imágenes que teníamos antes de hacer todo el cambio, peor ahora estamos en otro document root.


VOLUMES

Los volumen son una herramienta que nos permite almacenar datos de una manera persistente en nuestro servidor, muy útil en contenedores de Base de Datos, ya al instalar un contenedor de mysql este nos la entrega limpia y si el contenedor se elimina la data de pierde, si usamos VOLUMES entonces aunque el contenedor se elimine la data no se perderá, ya que al volver a levantar el contenedor le indicamos donde estará el volume y reconocerá la data.+

En Docker tenemos 3 tipos de Volumenes:​
  • Host: Son aquellos que se almacenan en nuestro Docker Host y que se alojan en una carpeta dentro de nuestro file system y que nosotros definimos.​
  • Anonymous: Son aquellos donde no definimos una carpeta, pero Docker automáticamente crea una carpeta random y aloja ahí la información.​
  • Named Volumes: Volumenes que creamos y que normalmente no son carpetas nuestras , si no que carpetas administradas por Docker , pero si tienen un nombre y son manejadas netamente por Docker.​

Crearemos una BD para entender el ejemplo:​

$ docker run -d -p 3306:3306 --name my-db -e MYSQL_ROOT_PASSWORD=12345678 -e MYSQL_DATABASE=docker-db -e MYSQL_USER=docker-user -e MYSQL_PASSWORD=87654321 mysql:5.7

Ingresaremos a nuestro contenedor, nos conectaremos a la BD y crearemos una tabla dentro dela BD “docker-db” y nos salimos del contenedor para luego eliminarlo​

$ docker exec -it my-db bash
$ mysql -u root -p
$ show databases;
$ use docker-db

CREATE TABLE Persons (
PersonID int,
LastName varchar(255),
FirstName varchar(255),
Address varchar(255),
City varchar(255)
);

$ exit
Si creamos nuevamente el contenedor y revisamos la BD y validamos si existe a Tabla “Persons” nos daremos cuenta que no existe y la información se perdió y es por eso que se utilizan los volumens.

$ docker run -d -p 3306:3306 --name my-db -e MYSQL_ROOT_PASSWORD=12345678 -e MYSQL_DATABASE=docker-db -e MYSQL_USER=docker-user -e MYSQL_PASSWORD=87654321 mysql:5.7

$ docker exec -it my-db bash
$ mysql -u root -p
$ show databases;
$ use docker-db
$ show tables;


VOLUME Host

Por ejemplo para resguardar la data de MySQL nos fijamos que la data se almacena en “/var/lib/mysql”, dentro de este directorio mysql almacena todas las BD con las que trabaja., entonces crearemos un volumen de este directorio.​

$ mkdir /opt/mysql
$ docker run -d --name mysql-db -p 3306:3306 -e MYSQL_ROOT_PASSWORD=12345678 -v /opt/mysql/:/var/lib/mysql mysql:5.7

Con esto mapeamos el directorio de mysql en nuestro equipo y en el directorio /opt/mysql comenzaran aparecer archivos y carpetas del servicio de myql.

Una vez el servicio haya levantado entramos y creamos nuestra BD y le ingresamos algunas cosas.​

$ mysql -u root -h 127.0.0.1 -p12345678
$ create database test;
$ create database test1;
$ create database tes2;
Y ahora podremos observar que en nuestra carpeta “/opt/mysql” se crearon 3 nuevas carpetas, ahora probaremos en eliminar el contenedor, en el ejemplo anterior al hacer esto perdíamos toda la data de nuestra BD ya que no estábamos definiendo un volumen.

$ docker rm -fv mysql-db
$ docker run -d --name mysql-db -p 3306:3306 -e MYSQL_ROOT_PASSWORD=12345678 -v /opt/mysql/:/var/lib/mysql mysql:5.7

$ mysql -u root -h 127.0.0.1 -p12345678
$ show databases;

Si ingresamos nuevamente a mysql, veremos que las bases de datos “test”, test1” y “test2” siguen existiendo.

VOLUME Anonimos

Para este caso lanzaremos la misma linea, peor eliminaremos la parte “/opt/mysql/:” y Docker automaticamente le dara una carpeta al azar dentro de la maquina.​

$ docker run -d --name mysql-db -p 3306:3306 -e MYSQL_ROOT_PASSWORD=12345678 -v /var/lib/mysql mysql:5.7

Si ejecutamos el siguiente comando podremos saber el directorio de Docker y donde almacena los “volumens”​

$ docker info | grep -i root

Si entramos a esa carpeta podremos observar que se encuentras los volumens

Para levantar un nuevo contenedor en base a la información del volumen debemos créalo como si fuese un volumen host, anteponiendo la ruta del volumen con su carpeta “_data”:​

$ docker run -d --name mysql-db -p 3306:3306 -e MYSQL_ROOT_PASSWORD=12345678 -v /var/lib/docker/volumes/c9ffa0fd5a414dcd9afcad39f4e81dd4615ec4ed82361a0cd759e6f9e305a746/_data:/var/lib/mysql mysql:5.7

***No es muy recomendado utilizar este tipo de volúmenes ya que se crean nombre extraños difíciles de memorizar y de acceder, además si eliminamos el contenedor con el comando “-fv” el volumen también se eliminara, cosa que es muy peligroso y si no agregamos el “-v” entonces los volúmenes quedaran almacenados (utilizando espacio) en nuestro equipo aunque eliminemos el contenedor.

Podemos crearlo también dentro de un Dockerfile:​

FROM centos:7
VOLUME opt

$ docker build -t test-vol .
$ docker run -dti –name test test-vol
$ docker volume ls

Tendremos un volume anónimo creado.

VOLUME Nombrados

Para crear un volume nombrado podemos realziarlo ejecutando el siguiente comando:​

$ docker volume create mysql-data
$ docker volume ls

Y para asignárselo a un contenedor:​

$ docker run -d --name mysql -v mysql-data:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=12345678 -e MYSQL_DATABASE=docker-db mysql:5.7

Ahora crearemos 2 bases de datos mas:​

$ mysql -u root -h 127.0.0.1 -p12345678
$ create database test1;
$ create database test2;
$ exit

Y revisaremos la carpeta donde se almacena los volumenes:​

$ docker info | grep -i root
$ sudo ls /var/lib/docker/volumes/mysql-data/_data

Se podrá observar que ahora también aparecen las 2 BD que acabamos de crear en el directorio “test1” y “test2”.

Ahora si eliminamos el contenedor con la opción “-v” el volumen quedará persistente y si creamos nuevamente el contenedor con el mismo comando indicando el volumen “myql-data” aparecerá toda la información.

Si una vez eliminamos el contenedor también queremos eliminar el volumen, debemos eliminarlo de manera independiente:​

$ docker volume rm mysql-data

Dangling Volumes

Tal cual como en las imágenes existen las Dangling Images acá con los volúmenes sucede lo mismo. Si creamos 2 contenedores con volúmenes anónimos:​

$ docker run -d --name mysql -v /var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=12345678 -e MYSQL_DATABASE=docker-db mysql:5.7

$ docker run -d --name mysql1 -v /var/lib/mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=12345678 -e MYSQL_DATABASE=docker-db mysql:5.7

Veremos que nos creara 2 nuevos volúmenes en el directorio de trabajo de Docker:​

$ sudo ls /var/lib/docker/volumes/
$ docker volume ls
$ docker rm mysql mysql1 -f
$ docker volume ls -f dangling=true

Luego si eliminamos estos contenedores sin pasarle el parámetro “-v” sucederá que los volúmenes quedaran sin ninguna referencia hacia un contenedor, utilizando espacio en nuestra maquina.

Para eliminar estos volúmenes utilizamos estos comandos:​

$ docker volumen rm <id> ,<id>
ó
$ docker volume ls -f dangling=true -q | xargs docker volume rm

Persistiendo logs en Nginx

Por ejemplo si queremos persistir otras cosas que no sea una base de datos también lo podemos hacer, para el ejemplo utilizaremos una imagen de nginx:​

$ docker run -d --name nginx nginx
$ docker exec -it nginx bash
$ cd /var/log/nginx

Creamos el contenedor y entramos a el para observar donde guarda los logs, una vez sabemos eliminamos el contenedor.

Crearemos una carpeta en el home de nuestro usuario para el volumen y almacenar los logs:​

$ mkdir /home/user/nginx
$ docker run -d --name nginx -p 80:80 -v /home/user/nginx:/var/log/nginx nginx

Una vez creado el conteneor y mapeado el volumen veremos que la carpeta que creamos “nginx” tiene 2 archivos llamado saccess.log y error.log.

Para probar miraremos el archivo error.log con el siguiente comando.​

$ tail -f error.log

y en un navegador ingresaremos a una pagina que no exista:​


Con esto podremos observar que funciona el volumen y estamos observando lo que sucede en nuestro nginx.​

2023/08/15 21:19:11 [error] 30#30: *2 open() "/usr/share/nginx/html/prueba.php" failed (2: No such file or directory), client: 172.17.0.1, server: localhost, request: "GET /prueba.php HTTP/1.1", host: "localhost"

Ahora eliminaremos el contenedor y lo crearemos nuevamete agregando el volumen:​

$ docker rm nginx -fv
docker run -d --name nginx -p 80:80 -v /home/user/nginx:/var/log/nginx nginx
Si ahora revisamos el archivo error.log veremos que tiene cargado los logs anteriores, por ejemplo:​

2023/08/15 21:19:11 [error] 30#30: *2 open() "/usr/share/nginx/html/prueba.php" failed (2: No such file or directory), client: 172.17.0.1, server: localhost, request: "GET /prueba.php HTTP/1.1", host: "localhost"

De esta manera salvamos los logs de nginx y de cualquier otro servicio, como también podemos resguardar cualquier otro archivo de un contenedor que no queremos perder si nuestro contenedor se elimina.


Compartir Volumenes entre uno o mas Contenedores:

Un volumen puede ser compartido entre mas de un contenedor, por ejemplo crearemos una carpeta llamada “compartido” y en el mismo nivel de carpeta crearemos un Dockerfile:​

FROM centos:7
COPY start.sh /start.sh
RUN chmod +x /start.sh
CMD /start.sh
Luego creamos el script que escribirá la hora cada 10 segundos en el archivo index.htm

#!/bin/bash
while true; do
echo $(date +%H:%M:%S) >> /opt/index.htm && \
sleep 10
done

Ahora crearemos la imagen y correremos el contenedor:​

$ docker build -t testhora .
$ docker run -v $PWD/compartido:/opt -d --name testhora testhora

Ahora creamos otro contenedor y compartimos el volumen:​

$ docker run -d --name nginx -p 80:80 -v $PWD/compartido:/usr/share/nginx/html nginx

Ahora podremos ver como el contenedor de nginx esta leyendo la data del mismo volumen donde el contenedor “testhora” esta escribiendo


Redes en Docker

En esta sección detallaremos todo lo relacionado a las redes en Docker, que son, los tipos, como se crean, como se eliminan, diferencia, etc. Se conectaran los contenedores a estas redes, asignar IP, y todo el tema de Networking.


Red por defecto

Cuando instalamos Docker y ejecutamos el comando:​

$ ip a | grep docker

Podremos observar la interfaz llamada “docker0” la cual tiene su propia IP, por ejemplo “172.17.0.1” y si creamos un contenedor sin definir una red entonces docker le asignara una ip dentro del rango.

Por ejemplo para conocer la ip de un contenedor escribimos:​

$ docker inspect nginx
o
$ docker inspect nginx | grep IPAddress

Con esto podremos observar la información que tiene el contenedor y dentro de toda esa info estará la IP, por ejemplo “172.17.0.3”, como gateway la ip de nuestra interfaz “172.17.0.1” y la red que esta utilizando “bridge”.

Para conocer todas las redes que tenemos, escribiremos el siguiente comando:​

$ docker network ls

Y con este comando se podrán ver las redes que trae docker docker, mas las que hayamos creado nosotros. Dentro del listado podremos encontrar la red llamada “bridge” que es la por defecto:​

$ docker network inspect bridge

Y podremos ver que dentro de su información nos aparecerá el segmento de red que hemos estado observado:​

"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},

Si creamos 2 contenedores centos:7 podremos observar sus direcciones ip y hacer ping de uno al otro:​

$ docker run -dti --name centos1 centos:7
$ docker run -dti --name centos2 centos:7

Ahora veremos las direcciones IP de los 2 contenedores, los cuales están en la misma red “Bridge”, que es la red por defecto:​

$ docker inspect centos1

"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
"IPAddress": "172.17.0.2",
$ docker inspect centos2

"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.3",
"IPAddress": "172.17.0.3",

Y haremos un ping desde el contenedor “centos1” a “centos2”:​

$ docker exec centos1 bash -c "ping 172.17.0.3"

Crear una Red definida por el usuario

Para crear una nueva Red lo haremos con el siguiente comando y luego listaremos las redes para observarla:​

$ docker network create test-network
$ docker network ls

Si no agregamos el “driver” la creara como “bridge” y si queremos cambiar el drivers agregamos el siguiente comando:​

$ docker network create -d bridge

También podemos crear esta nueva subred con mas detalles:​

$ docker network create -d bridge --subnet 10.10.10.0/24 --gateway 10.10.10.1 test-network-2
$ docker inspect test-network-2

Agregar contenedores a una red distinta

Cuando uno crear un contenedor y no le indica una red entonces lo agrega por defecto a la red Bridge, para decirle que lo meta a otra red lo haremos de la siguiente manera:​

$ docker run --network test-network -d --name test3 -ti centos:7

Aca creamos un contenedor llamado “test3”, con una imagen de centos7 en la red creada anteriormente llamada test-network, si le hacemos un inspect al contenedor veremos que ahora aparece que tiene la red "test-network" y el segmento ip que esta red maneja.​

$ docker inspect test3

Conectar contenedores en la misma Red

Crearemos un contenedor nuevo llamado cont1 y cont2:​

$ docker network create docker-test-network
$ docker run -d --network docker-test-network --name cont1 -it centos:7
$ docker run -d --network docker-test-network --name cont2 -it centos:7

Ahora haremos inspect a estos 2 contenedores para visualizar toda la info de estos:​

$ docker inspect cont1
$ docker inspect cont2

Ambos contenedores están en la misma red y en el mismo segmento de red, y como están en una red creada por nosotros y no es la red por defecto podremos hacerle ping al nombre del contenedor, cuando creamos el contenedor en la red or defecto solo podremos hacerle ping a la IP.​

$ docker exec cont1 bash -c "ping cont2"
$ docker exec cont2 bash -c "ping cont1"
Al poder hacerle ping al nombre facilita demasiado, ya que es mas fácil recordar un nombre a una IP, además que el nombre no va a cambiar, si borramos el contenedor y lo creamos nuevamente la IP podría variar y ya no podremos llegar al contenedor.

Conectar contenedores en distintas redes

Crearemos 2 redes y 2 contenedores:​

$ docker network create red01
$ docker run -d --network red01 --name contred01 -it centos:7
$ docker inspect contred01
"Gateway": "172.28.0.1",
"IPAddress": "172.28.0.2",
$ docker network create red02
$ docker run -d --network red02 --name contred02 -it centos:7
$ docker inspect contred02
"Gateway": "172.29.0.1",
"IPAddress": "172.29.0.2",
Ambos contenedores están en redes totalmente distintas, por lo tanto no podrán verse y los ping no llegaran de un contenedor a otro.

Para poner conectar ambas redes existe un comando llamado “connect”:​

$ docker network connect red01 contred02

Con este comando le estamos indicando a docker que conecte el contenedor “contred02” a la red “red01” . Ahora si hacemos un inspect al contenedor “contred02” podremos observar que además te tener la red “red02” también tiene la red “red01” dentro de su configuración, por lo tanto si ahora hacemos un ping desde el contenedor “contred02” al “contred01” o viseversa este sera exitoso.​

$ docker exec contred02 bash -c "ping contred01"
Si ahora queremos desconectar el contenedor “contred02” de la red “red01” lo hacemos con el siguiente comando:

$ docker network connect red01 contred02

Y si tratamos de hacer los ping estos ya no funcionaran, pues ambos contenedores quedaron aislados en sus propias redes.


Eliminar Redes

Para eliminar las redes no debe haber ningún contenedor conectado a esa red, por lo tanto, primero debemos eliminar los contenedores y luego ejecutar el comando para eliminar la red:

$ docker network rm red01 red02

Asignar IP a un contenedor

Primero crearemos una nueva Red y un contenedor en la red creada:​

$ docker network create --subnet 172.22.1.0/24 --gateway 172.22.1.1 -d bridge my-net
$ docker run --network my-net -d --name test1 nginx

Al contenedor “test1” docker le asignara una IP por defecto comenzado por la mas baja, pero si quisiéramos asignarle una ip nosotros al contenedor lo haremos con el siguiente comando:​

$ docker run --network my-net --ip 172.22.1.8 -d --name test2 nginx



Red de Host
Dentro de las redes de Docker existe una llamada “host”, la cual replica los mismos parámetros del equipo donde esta corriendo docker:

$ docker run --network host -d --name test-host nginx


Si luego hacemos un “ifconfig” o un “ip a” podremos observar que el contenedor tiene las mismas interfaces que nuestro equipo, incluyendo el hostname.

Red None

Dentro de las redes de Docker existe una llamada “none”, la cuel tiene como “drive” null.​

$ docker network ls | grep none

Cada contenedor que metamos acá no tendrán red.​
 
Upvote 1

epic

Pro
Se incorporó
11 Febrero 2007
Mensajes
846
DOCKER COMPOSE

Es una herramienta de docker que ayuda a crear aplicaciones multi contenedor, por ejemplo wordpress necesita un contenedor web de apache o nginx con php instalado y otro contenedor para alojar su base de datos. Un caso como este lo podríamos efectuar ejecutando lineas de docker run pasándole la red que compartirán y sus nombre, esto lo podríamos crear a mano y repetir quizás unas 10 veces y podría funcionar, pero con docker compose definimos todo esto en un solo archivo y luego que se ejecute todas las instrucciones (imagenes, redes, volumenes, nombres, etc) que están dentro del archivo yaml.

Primeros Pasos

Docker Compose nos ayuda en la automatizaron de la creación de contenedores, para esto definiremos todos los comando en un archivo .yaml.​

$ nano docker-compose.yaml

y comenzaremos a introducir algunos comandos:

Docker:​

$ docker run -d –name nginx -p 80:80 nginx

docker-compose:​

Código:
version: '3'
services:
  web:
    container_name: nginx1
    ports:
      - "8080:80"
    image: nginx

Una vez creado el archivo y guardado lo ejecutamos de la siguiente manera:​

$ docker-compose up -d
Ahora podremos observar que tenemos 2 contenedor ejecutándose (uno por el puert 80 y el otro por el puerto 8080), uno creado con el comando de docker run y el otro mediante docker-compose.

Importante saber que la primera linea indica la versión del docker-compose, actualmente esta en la versión 3 y a medida que va aumentando se van agregando nuevas funcionalidades y/o depreciando otras.

Ahora si queremos eliminar nuestro contenedor creado por docker-compose:​

$ docker-compose down


Variables de entorno en Compose

Código:
version: '3'
services:
  db:
    container_name: mysql
    image: mysql:5.7
    ports:
      - "3306:3306"
    environment:
      - "MYSQL_ROOT_PASSWORD=12345678"
$ docker-compose up -d
Con esto crearemos un contenedor de MySQL version 5.7, escuchando en el puerto 3306 y con una clave root de “12345678” enviada a través de una variable de entorno.

También podemos mandarle la variable de entorno desde un archivo, enviaremos la variable a un archivo llamado common.env:​

$ echo "MYSQL_ROOT_PASSWORD=1234567890" > common.env

y editamos nuestro docker-compose:​

Código:
version: '3'
services:
  db:
    container_name: mysql
    image: mysql:5.7
    ports:
      - "3306:3306"
    env_file: common.env
$ docker-compose up -d

Y si entramos al contenedor podremos observar que podemos entrar a mysql con la nueva clave.

Entonces podremos definir variables de entorno indicándolas en el mismo docker-compose o crear un archivo (cualquier nombre) y agregarlas ahí y luego indicar el archivo en el docker-compose.


Volumenes en Compose

Volumen nombrado

Código:
version: '3'
services:
  web:
    container_name: nginx
    image: nginx   
    ports:
      - "80:80"
    volumes:
      - "vol2:/usr/share/nginx/html"

volumes:
  vol2:

Con este archivo hemos creado un contenedor nginx, escuchando en el puerto 80 y le creamos un volumen nombrado al final del archivo:​

volumes:
vol2:
Para luego montarserlo al contenedor:

volumes:
- "vol2:/usr/share/nginx/html"

Luego ejecutamos docker-compose para crear el contenedor:​

$ docker-compose up -d
[+] Running 2/2
⠿ Volume "docker_vol2" Created 0.0s
⠿ Container nginx Started

Vayamos a ver el volumen:​

$ docker info | grep -i root
$ cd /var/lib/docker/volumes/docker_vol2/_data
$ ls

Y observaremos el archivo index.html y 50x.html que son propios de nginx. Si queremos podemos editar ese archivo “index.html”, lo guardamos y veremos el cambio reflejado en nuestro navegador desde http://localhost/



Volumen de Host

Crearemos una carpeta en el mismo nivel del docker-compose.yaml llamado compartido y dentro de este directorio crearemos un index.html con el contenido que uno quiera:​

Código:
version: '3'
services:
  web:
    container_name: nginx
    image: nginx
    ports:
      - "80:80"
    volumes:
      - "/opt/lampp/htdocs/Docker/compartido:/usr/share/nginx/html"

Luego en el docker-compose editaremos la linea del volumen le pondremos la ruta de nuestro index.html (en mi caso fue /opt/lampp/htdocs/Docker/compartido), ahora al ejecutar el docker-compose veremos en nuestro localhost la pagina que hemos puesto en el index.​

$ docker-compose up -d


Redes en Compose

En el siguiente ejemplo crearemos un docker-compose donde indicaremos una red llamada “net-test” y luego se le asignara al contenedor:​

Código:
version: '3'
services:
  web:
    container_name: nginx
    image: nginx
    ports:
      - "80:80"
    networks:
      - net-test

  web2:
    container_name: nginx2
    image: nginx
    ports:
      - "81:80"
    networks:
      - net-test


networks:
  net-test:
Si hacemos un “docker network ls” veremos la nueva red y si hacemos un “docker inspect nginx” también veremos que el contenedor pertenece a la red creada en el docker-compose.

En este ejemplo hemos creado 2 contenedores web en el mismo docker-compose y ambos están en la misma red, por lo tanto, si ingresamos a uno de los 2 contenedores podremos hacerle ping al otro contenedor sin problema. Lo interesante es que podremos hacerle ping tanto ala IP, al nombre del contenedor(nginx o nginx2) o al nombre del servicio (web o web2).


Construyendo imagenes en Compose

Acá construiremos imágenes a partir del a opción “build”, para esto crearemos una carpeta en el mismo nivel de docker-compose.yaml llamada “build” y dentro de ella crearemos un Dockerfile.

docker-compose.yaml​

Código:
version: '3'
services:
  web:
    container_name: nginx
    image: web-test
    build: ./build
    ports:
      - "80:80"

Dockerfile​
FROM centos:7
RUN mkdir /opt/test
Si hacemos un “docker images” veremos nuestra nueva imagen llamada “web-test” en la lista. Si tenemos un dockerfile con un nombre distinto debemos cambiar las siguientes lineas:

Código:
version: '3'
services:
  web:
    container_name: nginx
    image: web-test
    build:
      context: ./build
      dockerfile: dockernew
    ports:
      - "80:80"

Con la linea “context” indicaremos la ubicación del archivo dockerfile y con la linea “dockerfile” indicaremos el nombre que tiene.


Sobreescribir el CMD con Compose

En esta sección modificaremos el CMD de una imagen sin necesidad de crear un dockerfile… por ejemplo si creamos un contenedor de centos veremos que su CMD es “/bin/bash/”:​

$ docker run -dti centos:7
$ docker ps
Entonces crearemos un docker-compose con el siguiente contenido:

YAML:
version: '3'
services:
  web:
    container_name: nginx
    image: nginx:alpine
    mem_limit: 20m
    cpuset: "0"
    ports:
      - "8080:8080"

Y veremos que el CMD de este nuevo Centos ya no es “/bin/bash/”, si no que el que agregamos en el docker-compose. Lo único que debemos hacer es indicarle un command distinto y docker entenderá que queremos reemplazar el existente.


Limitar Recursos en contenedores

version: '3'
services:
web:
container_name: nginx
image: nginx:alpine
mem_limit: 20m
cpuset: "0"
ports:
- "8080:8080"
Con esto estamos limitando al contenedor a utilizar solo 20m de Ram y a una sola CPU, si ultilicamos el comando “docker stats” podremos observar el limite de ram.



Política de reinicio de contenedores

En los contenedores existe algo llamado docker restar policy y que no es mas que una condicion en que un contenedor debe ser reiniciado: “on-failure”, “unless-stopped” y “always”.

Crearemos los siguientes archivos para las pruebas:

start.sh​
#!/bin/bash
echo "Estoy vivo"
sleep 5
echo "Estoy detenido"


Dockerfile​
FROM centos:7
COPY start.sh /start.sh
RUN chmod +x /start.sh
CMD /start.sh


1.- docker-compose.yaml​
Código:
version: '3'
services:
  test:
    container_name: test
    image: restart-image
    build: .
$ docker-compose up --build -d

Con el siguiente docker-compose el contenedor durará 5 segundo y luego se detendra y quedara detenido.

Si visualizamos con un “docker ps” no se encontrara , pero si lo vemos con un “docker ps -a” aparecerá con STATUS “Exited”

2.- docker-compose.yaml​
Código:
version: '3'
services:
  test:
    container_name: test
    image: restart-image
    build: .
    restart: always
$ docker-compose up --build -d

Con el siguiente docker-compose el contenedor durará 5 segundo y luego se detendrá, pero docker intentara reiniciarlo. Si ejecutamos un “docker ps” lo tendremos ahí con estado “UP”, luego en 5 segundos pasara a STATUS “Restarting”, luego UP nuevamente y así por siempre ya que Docker lo levantara cada vez que se caiga.

Si vemos los logs del cntenedor tendremos muchas lineas de “Estoy vivo” y “Estoy detenido”.

3.- docker-compose.yaml​
YAML:
version: '3'
services:
  test:
    container_name: test
    image: restart-image
    build: .
    restart: unless-stopped
$ docker-compose up --build -d

Ahora Docker hará el mismo proceso, a los 5 segundo el contenedor va a morir y docker lo reiniciará, pero si al contenedor lo detenemos a mano con un “docker stop” el contenedor parará, ya que este comando indica si docker lo detiene o alguien lo detiene que lo deje así.


4.- docker-compose.yaml​
YAML:
version: '3'
services:
  test:
    container_name: test
    image: restart-image
    build: .
    restart: on-failure
$ docker-compose up --build -d

Ahora Docker hará el mismo proceso, a los 5 segundo el contenedor va a morir y docker lo dejará detenido, ya que el contenedor se detuvo sin un mensaje de error, el script stat.sh lo termina limpio.

Si cambiamos el script ára que no termine el 0 y ternine en 1 simulando un error:

start.sh​
#!/bin/bash
echo "Estoy vivo"
sleep 5
echo "Estoy detenido"
exit 1

Agregando un “exit 1” el contenedor a los 5 segundos terminara con un “error” por lo tanto docker lo intetará reiniciar porque el código de error es distinto a 0.

En Docker lo podemos hacer mediante la siguiente linea:​

$ docker run dit --restart unless-stopped nginx
Personaliza el nombre de tu proyecto Compose

Podremos cambiar el prefijo que va a estar acompañando el nombre de los volumenes y las redes:

docker-compose.yaml​

Código:
version: '3'
services:
  test:
    container_name: test
    image: nginx
    ports:
      - "80:80"
    networks:
      - net-test2

networks:
  net-test2:
$ docker-compose up --build -d

[+] Running 2/2
⠿ Network docker_net-test2 Created 0.0s
⠿ Container test Started 0.4s

Como nos fijamos cuando creamos una red esta tiene como prefijo el “nombre de nuestra carpeta + nombre que le asignamos”. Para que podamos elegir otro nombre lo hacemos de la siguiente manera:​

$ docker-compose -p nuevonom up -d
[+] Running 2/2
⠿ Network nuevonom_net-test2 Created 0.1s
⠿ Container test Started 0.4s


Usar nombres distintos en e docker-compose.yaml

Podemos utilizar nombres distintos para el archivo docker-compose, al cual como lo hacíamos en el dockerfile:​

$ docker-compose -f nuevodocker-compose.yaml up -d
Mas opciones en Compose

Para conocer todas las copiones simplemente escribimos “docker-compose”, de esta forma nos entregar todas las opciones y argumentos que podemos utilizar.

Instalar WordPress + MySQL
YAML:
version: '3'
services:
  db:
    container_name: my-sql
    image: mysql:5.7
    volumes:
      - $PWD/data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: 12345678
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
    ports:
      - "3306:3306"
    networks:
      - net_wp

  wordpress:
    container_name: wp
    depends_on:
      - db
    image: wordpress:latest
    ports:
      - "80:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
    networks:
      - net_wp

networks:
  net_wp:

Acá tenemos 2 servicios, la base de datos y el contenedor web de wordpress. Manejamos un volumen llamado “data” para la información de la base de datos y otro llamado html para almacenar lo que corresponde a wordpress, también utilizamos variables de entornos para los datos de creación de la BD y la información de conexión entre el contenedor wordpress y la BD, agregamos también la opción de “depends_on” lo que indica que primero se cree la BD y luego el contenedor de wordpress, con esto nos aseguramos que la BD este lista antes de crear wordpress y sus conexiones. Abrimos el puerto 80 y creamos una red llamada “net_wp” donde estarán ambos contenedores y de esta manera WP se pueda conectar con la BD.

Gracias a los volumenes tendremos de manera persistente tanto nuestra BD como la informacion de wordpress, en el caso que eliminemos los contenedores podremos volver a levantarlo y estara todo tal cual estaba antes de ser eliminados.

Luego ejecutamos para crear nuestro servicio:​

$ docker-compose up -d
[+] Running 3/3
⠿ Network docker_net_wp Created 0.1s
⠿ Container my-sql Started 0.4s
⠿ Container wp Started 0.6s


*** Toda esta información la podemos encontrar el docker hub y buscamos por wordpress.

Luego entramos a http://localhost y nos mostrará la pantalla de wordpress para comenzar con su instalación.

Hagamos la prueba de instalar wordpress y ponerle una clave, luego eliminemos los contenedores:​

$ docker-compose down

o

$ docker rm $(docker ps -aq) -f


Y volvamos a ejecutar “docker-compose up -d”, si todo funciona bien entonces levantara nuevamente nuestro wordpress con los cambios que habíamos realizado antes de eliminar el contenedor.

Con esto tenemos 2 contenedores independientes, cada uno con su servicio, sus volumenes y puertos y comunicandose entre ellos ya que se encuentran dentro de la misma red.​
 
Upvote 1

mmirandap

Gold Member
Se incorporó
1 Septiembre 2006
Mensajes
2.470
Wena choro, yo me pegué el salto directo a kubernetes y tuve que aprender docker en el camino, sigo aprendiendo de todas maneras pero tu post está muy bueno como cortapalos
 
Upvote 0

NSonic

* Mako-Chan *
Se incorporó
23 Abril 2007
Mensajes
789
Buena, justo estamos con capacitación de Docker & Kubernetes , se agradece.
 
Upvote 0

epic

Pro
Se incorporó
11 Febrero 2007
Mensajes
846
Me dio lata hacer uno de kubernetes, pero si alguien se anima xD

a ver si prendemos mas el foro con estos temas de contenedores y orquestadores.
 
Upvote 0

unreal4u

I solve problems.
Miembro del Equipo
ADMIN
Se incorporó
2 Octubre 2005
Mensajes
13.601
Excelente guía! La subí a la portada :)

Puedes no editar el primer post por favor? Si lo haces, sacarás el artículo de portada :)

Saludos.
 
Upvote 0

brujoadr

Pro
Se incorporó
24 Septiembre 2019
Mensajes
510

He aprendido hartas cosillas siguiendo el canal de networkChuck, lo recomiendo totalmente. Para lo que uso, el primer vídeo me es suficiente.

1) you need to learn Docker RIGHT NOW!! // Docker Containers 101​


2) Docker Compose will BLOW your MIND!!​


3) learning Docker is HARD!! (this makes it easy, portainer)​

 
Upvote 0
Se incorporó
21 Marzo 2022
Mensajes
149
DOCKER COMPOSE

Es una herramienta de docker que ayuda a crear aplicaciones multi contenedor, por ejemplo wordpress necesita un contenedor web de apache o nginx con php instalado y otro contenedor para alojar su base de datos. Un caso como este lo podríamos efectuar ejecutando lineas de docker run pasándole la red que compartirán y sus nombre, esto lo podríamos crear a mano y repetir quizás unas 10 veces y podría funcionar, pero con docker compose definimos todo esto en un solo archivo y luego que se ejecute todas las instrucciones (imagenes, redes, volumenes, nombres, etc) que están dentro del archivo yaml.

Primeros Pasos

Docker Compose nos ayuda en la automatizaron de la creación de contenedores, para esto definiremos todos los comando en un archivo .yaml.​

$ nano docker-compose.yaml

y comenzaremos a introducir algunos comandos:

Docker:​

$ docker run -d –name nginx -p 80:80 nginx

docker-compose:​

Código:
version: '3'
services:
  web:
    container_name: nginx1
    ports:
      - "8080:80"
    image: nginx

Una vez creado el archivo y guardado lo ejecutamos de la siguiente manera:​

$ docker-compose up -d
Ahora podremos observar que tenemos 2 contenedor ejecutándose (uno por el puert 80 y el otro por el puerto 8080), uno creado con el comando de docker run y el otro mediante docker-compose.

Importante saber que la primera linea indica la versión del docker-compose, actualmente esta en la versión 3 y a medida que va aumentando se van agregando nuevas funcionalidades y/o depreciando otras.

Ahora si queremos eliminar nuestro contenedor creado por docker-compose:​

$ docker-compose down


Variables de entorno en Compose

Código:
version: '3'
services:
  db:
    container_name: mysql
    image: mysql:5.7
    ports:
      - "3306:3306"
    environment:
      - "MYSQL_ROOT_PASSWORD=12345678"
$ docker-compose up -d
Con esto crearemos un contenedor de MySQL version 5.7, escuchando en el puerto 3306 y con una clave root de “12345678” enviada a través de una variable de entorno.

También podemos mandarle la variable de entorno desde un archivo, enviaremos la variable a un archivo llamado common.env:​

$ echo "MYSQL_ROOT_PASSWORD=1234567890" > common.env

y editamos nuestro docker-compose:​

Código:
version: '3'
services:
  db:
    container_name: mysql
    image: mysql:5.7
    ports:
      - "3306:3306"
    env_file: common.env
$ docker-compose up -d

Y si entramos al contenedor podremos observar que podemos entrar a mysql con la nueva clave.

Entonces podremos definir variables de entorno indicándolas en el mismo docker-compose o crear un archivo (cualquier nombre) y agregarlas ahí y luego indicar el archivo en el docker-compose.


Volumenes en Compose

Volumen nombrado

Código:
version: '3'
services:
  web:
    container_name: nginx
    image: nginx 
    ports:
      - "80:80"
    volumes:
      - "vol2:/usr/share/nginx/html"

volumes:
  vol2:

Con este archivo hemos creado un contenedor nginx, escuchando en el puerto 80 y le creamos un volumen nombrado al final del archivo:​

volumes:
vol2:
Para luego montarserlo al contenedor:

volumes:
- "vol2:/usr/share/nginx/html"

Luego ejecutamos docker-compose para crear el contenedor:​

$ docker-compose up -d
[+] Running 2/2
⠿ Volume "docker_vol2" Created 0.0s
⠿ Container nginx Started

Vayamos a ver el volumen:​

$ docker info | grep -i root
$ cd /var/lib/docker/volumes/docker_vol2/_data
$ ls

Y observaremos el archivo index.html y 50x.html que son propios de nginx. Si queremos podemos editar ese archivo “index.html”, lo guardamos y veremos el cambio reflejado en nuestro navegador desde http://localhost/



Volumen de Host

Crearemos una carpeta en el mismo nivel del docker-compose.yaml llamado compartido y dentro de este directorio crearemos un index.html con el contenido que uno quiera:​

Código:
version: '3'
services:
  web:
    container_name: nginx
    image: nginx
    ports:
      - "80:80"
    volumes:
      - "/opt/lampp/htdocs/Docker/compartido:/usr/share/nginx/html"

Luego en el docker-compose editaremos la linea del volumen le pondremos la ruta de nuestro index.html (en mi caso fue /opt/lampp/htdocs/Docker/compartido), ahora al ejecutar el docker-compose veremos en nuestro localhost la pagina que hemos puesto en el index.​

$ docker-compose up -d


Redes en Compose

En el siguiente ejemplo crearemos un docker-compose donde indicaremos una red llamada “net-test” y luego se le asignara al contenedor:​

Código:
version: '3'
services:
  web:
    container_name: nginx
    image: nginx
    ports:
      - "80:80"
    networks:
      - net-test

  web2:
    container_name: nginx2
    image: nginx
    ports:
      - "81:80"
    networks:
      - net-test


networks:
  net-test:
Si hacemos un “docker network ls” veremos la nueva red y si hacemos un “docker inspect nginx” también veremos que el contenedor pertenece a la red creada en el docker-compose.

En este ejemplo hemos creado 2 contenedores web en el mismo docker-compose y ambos están en la misma red, por lo tanto, si ingresamos a uno de los 2 contenedores podremos hacerle ping al otro contenedor sin problema. Lo interesante es que podremos hacerle ping tanto ala IP, al nombre del contenedor(nginx o nginx2) o al nombre del servicio (web o web2).


Construyendo imagenes en Compose

Acá construiremos imágenes a partir del a opción “build”, para esto crearemos una carpeta en el mismo nivel de docker-compose.yaml llamada “build” y dentro de ella crearemos un Dockerfile.

docker-compose.yaml​

Código:
version: '3'
services:
  web:
    container_name: nginx
    image: web-test
    build: ./build
    ports:
      - "80:80"

Dockerfile​
FROM centos:7
RUN mkdir /opt/test
Si hacemos un “docker images” veremos nuestra nueva imagen llamada “web-test” en la lista. Si tenemos un dockerfile con un nombre distinto debemos cambiar las siguientes lineas:

Código:
version: '3'
services:
  web:
    container_name: nginx
    image: web-test
    build:
      context: ./build
      dockerfile: dockernew
    ports:
      - "80:80"

Con la linea “context” indicaremos la ubicación del archivo dockerfile y con la linea “dockerfile” indicaremos el nombre que tiene.


Sobreescribir el CMD con Compose

En esta sección modificaremos el CMD de una imagen sin necesidad de crear un dockerfile… por ejemplo si creamos un contenedor de centos veremos que su CMD es “/bin/bash/”:​

$ docker run -dti centos:7
$ docker ps
Entonces crearemos un docker-compose con el siguiente contenido:

YAML:
version: '3'
services:
  web:
    container_name: nginx
    image: nginx:alpine
    mem_limit: 20m
    cpuset: "0"
    ports:
      - "8080:8080"

Y veremos que el CMD de este nuevo Centos ya no es “/bin/bash/”, si no que el que agregamos en el docker-compose. Lo único que debemos hacer es indicarle un command distinto y docker entenderá que queremos reemplazar el existente.


Limitar Recursos en contenedores

version: '3'
services:
web:
container_name: nginx
image: nginx:alpine
mem_limit: 20m
cpuset: "0"
ports:
- "8080:8080"
Con esto estamos limitando al contenedor a utilizar solo 20m de Ram y a una sola CPU, si ultilicamos el comando “docker stats” podremos observar el limite de ram.



Política de reinicio de contenedores

En los contenedores existe algo llamado docker restar policy y que no es mas que una condicion en que un contenedor debe ser reiniciado: “on-failure”, “unless-stopped” y “always”.

Crearemos los siguientes archivos para las pruebas:

start.sh​
#!/bin/bash
echo "Estoy vivo"
sleep 5
echo "Estoy detenido"


Dockerfile​
FROM centos:7
COPY start.sh /start.sh
RUN chmod +x /start.sh
CMD /start.sh


1.- docker-compose.yaml​
Código:
version: '3'
services:
  test:
    container_name: test
    image: restart-image
    build: .
$ docker-compose up --build -d

Con el siguiente docker-compose el contenedor durará 5 segundo y luego se detendra y quedara detenido.

Si visualizamos con un “docker ps” no se encontrara , pero si lo vemos con un “docker ps -a” aparecerá con STATUS “Exited”

2.- docker-compose.yaml​
Código:
version: '3'
services:
  test:
    container_name: test
    image: restart-image
    build: .
    restart: always
$ docker-compose up --build -d

Con el siguiente docker-compose el contenedor durará 5 segundo y luego se detendrá, pero docker intentara reiniciarlo. Si ejecutamos un “docker ps” lo tendremos ahí con estado “UP”, luego en 5 segundos pasara a STATUS “Restarting”, luego UP nuevamente y así por siempre ya que Docker lo levantara cada vez que se caiga.

Si vemos los logs del cntenedor tendremos muchas lineas de “Estoy vivo” y “Estoy detenido”.

3.- docker-compose.yaml​
YAML:
version: '3'
services:
  test:
    container_name: test
    image: restart-image
    build: .
    restart: unless-stopped
$ docker-compose up --build -d

Ahora Docker hará el mismo proceso, a los 5 segundo el contenedor va a morir y docker lo reiniciará, pero si al contenedor lo detenemos a mano con un “docker stop” el contenedor parará, ya que este comando indica si docker lo detiene o alguien lo detiene que lo deje así.


4.- docker-compose.yaml​
YAML:
version: '3'
services:
  test:
    container_name: test
    image: restart-image
    build: .
    restart: on-failure
$ docker-compose up --build -d

Ahora Docker hará el mismo proceso, a los 5 segundo el contenedor va a morir y docker lo dejará detenido, ya que el contenedor se detuvo sin un mensaje de error, el script stat.sh lo termina limpio.

Si cambiamos el script ára que no termine el 0 y ternine en 1 simulando un error:

start.sh​
#!/bin/bash
echo "Estoy vivo"
sleep 5
echo "Estoy detenido"
exit 1

Agregando un “exit 1” el contenedor a los 5 segundos terminara con un “error” por lo tanto docker lo intetará reiniciar porque el código de error es distinto a 0.

En Docker lo podemos hacer mediante la siguiente linea:​

$ docker run dit --restart unless-stopped nginx
Personaliza el nombre de tu proyecto Compose

Podremos cambiar el prefijo que va a estar acompañando el nombre de los volumenes y las redes:

docker-compose.yaml​

Código:
version: '3'
services:
  test:
    container_name: test
    image: nginx
    ports:
      - "80:80"
    networks:
      - net-test2

networks:
  net-test2:
$ docker-compose up --build -d

[+] Running 2/2
⠿ Network docker_net-test2 Created 0.0s
⠿ Container test Started 0.4s

Como nos fijamos cuando creamos una red esta tiene como prefijo el “nombre de nuestra carpeta + nombre que le asignamos”. Para que podamos elegir otro nombre lo hacemos de la siguiente manera:​

$ docker-compose -p nuevonom up -d
[+] Running 2/2
⠿ Network nuevonom_net-test2 Created 0.1s
⠿ Container test Started 0.4s


Usar nombres distintos en e docker-compose.yaml

Podemos utilizar nombres distintos para el archivo docker-compose, al cual como lo hacíamos en el dockerfile:​

$ docker-compose -f nuevodocker-compose.yaml up -d
Mas opciones en Compose

Para conocer todas las copiones simplemente escribimos “docker-compose”, de esta forma nos entregar todas las opciones y argumentos que podemos utilizar.

Instalar WordPress + MySQL
YAML:
version: '3'
services:
  db:
    container_name: my-sql
    image: mysql:5.7
    volumes:
      - $PWD/data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: 12345678
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
    ports:
      - "3306:3306"
    networks:
      - net_wp

  wordpress:
    container_name: wp
    depends_on:
      - db
    image: wordpress:latest
    ports:
      - "80:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
    networks:
      - net_wp

networks:
  net_wp:

Acá tenemos 2 servicios, la base de datos y el contenedor web de wordpress. Manejamos un volumen llamado “data” para la información de la base de datos y otro llamado html para almacenar lo que corresponde a wordpress, también utilizamos variables de entornos para los datos de creación de la BD y la información de conexión entre el contenedor wordpress y la BD, agregamos también la opción de “depends_on” lo que indica que primero se cree la BD y luego el contenedor de wordpress, con esto nos aseguramos que la BD este lista antes de crear wordpress y sus conexiones. Abrimos el puerto 80 y creamos una red llamada “net_wp” donde estarán ambos contenedores y de esta manera WP se pueda conectar con la BD.

Gracias a los volumenes tendremos de manera persistente tanto nuestra BD como la informacion de wordpress, en el caso que eliminemos los contenedores podremos volver a levantarlo y estara todo tal cual estaba antes de ser eliminados.

Luego ejecutamos para crear nuestro servicio:​

$ docker-compose up -d
[+] Running 3/3
⠿ Network docker_net_wp Created 0.1s
⠿ Container my-sql Started 0.4s
⠿ Container wp Started 0.6s


*** Toda esta información la podemos encontrar el docker hub y buscamos por wordpress.

Luego entramos a http://localhost y nos mostrará la pantalla de wordpress para comenzar con su instalación.

Hagamos la prueba de instalar wordpress y ponerle una clave, luego eliminemos los contenedores:​

$ docker-compose down

o

$ docker rm $(docker ps -aq) -f


Y volvamos a ejecutar “docker-compose up -d”, si todo funciona bien entonces levantara nuevamente nuestro wordpress con los cambios que habíamos realizado antes de eliminar el contenedor.

Con esto tenemos 2 contenedores independientes, cada uno con su servicio, sus volumenes y puertos y comunicandose entre ellos ya que se encuentran dentro de la misma red​
 
Upvote 0
Se incorporó
21 Marzo 2022
Mensajes
149
Tremendo post!! Yo llevo unos meses utilizando docker para ciertos servicios y la verdad es una genialidad!! Actualmente tengo un servidor Apache+PHP, uno con MySQL, uno con MongoDB y un par de servidores Ngix, todo bajo MacOS, y de verdad ha sido toda una revelacion, sobre todo de la mano de Docker Compose.

Para los que estan trabajando con esto, les recomiendo mucho el software DockStation... simplemente genial!

Screenshot 2023-08-23 at 13.12.38.png
 
Upvote 0

Miguelwill

I am online
Miembro del Equipo
MOD
Se incorporó
23 Febrero 2004
Mensajes
12.403
Kubernetes es un sistema de orquestacion de contenedores y recursos
esta pensada para ser aprovechada en un cluster de varios servidores (fisicos o virtuales, en la nube, etc ), y permite distribuir servicios en varios nodos/equipos/workers comunicandose entre si como si estuvieran en uno solo (o una misma red)

la configuracion puede variar segun las necesidades (mucho, mas necesidades, mas recursos, mas servicios, mas control), pero hay unas faciles que se pueden instalar en un solo servidor linux, y usar un mini-cluster de un unico nodo.

un ejemplo simplificado:
Kubernetes-Components-The-Kubernetes-setup-has-at-least-three-components-kublet-daemon.png



una de las facilidades que me gusta aprovechar es la de los "Ingress" , que funcionan como un proxy reverso
ya que en un contenedor se define un puerto (80 por ej)
se define el "servicio" con el nombre "puerto-web-sitio" que apunte a esa "app" o contenedor al puerto "80" del ejemplo
luego se define el "ingress" que indicara la url publica/local a usar, que apunte al servicio "puerto-web-sitio" al puerto "80"

luego en el proxy reverso publico (o en el dns publico si tienen ip publica) se apunta a la ip : puerto del ingress (igual para todos los sitios del cluster), y si la url concuerda, ingress te enviara la peticion al servicio, y este finalmente al o los contenedores (pueden ser 1 o 5000, usando algo como round-robin)

algo asi:
ingress.png


pd: POD es la unidad de "aplicacion" que usa kubernetes, y en esta puede tener 1 o varios contenedores (como un php-fpm+nginx por ejemplo)
 
Upvote 0

epic

Pro
Se incorporó
11 Febrero 2007
Mensajes
846
Podrias explicarme de que trata esto de los Kubernetes?

Gracias de antemano
uuufff bien en palabras simple te sirve para orquestar contenedores (no se si conocer Docker Swarm que seria algo "parecido")... Kubernetes te ayudara a administrar todos tus contenedores de una forma super facil, con facil me refiero a que con un manifiesto yaml tu le indicas cuantas replicas del contenedor quieres, que imagen quieres (nginx, mysql, apache, etc) defines un servicio para llegar al contenedor (que en kubernetes estan dentro de PODS( que es la unidad mas pequeña en kubernetes), y por encima puedes tener un loadbalancer o un ingress para llegar desde el exterior a tus servicios.

Si en un momento un pod falla, una parte de kubernetes lo detecta y como en el manifiesto indicaste que querias 3 replicas y ahora te quedaste cn 2 el automaticamente te crea otro en base a la misma imagen y vuelves a tenr los 3... si detecta en base a ciertas configuraciones en tu manifiesto que los pods estan consumiento mucho recursos te escala a 4 , 5 6 o mas pods para que tu servicio no se sature y cuando el consumo de cpu o ram vuelve a la normalidad entonces comienza a maar los pods hasta dejarte las 3 replicas que indicaste al comienzo.

entonces tu le defines que quieres y cuentos pods quieres y kubernetes se encarga de mantenerte todo... eso en grandes rasgos xD


Para hacer pruebas puedes instalar Minikube en tu equipo linux y probarlo.
 
Upvote 0

chertsey

Pro
Se incorporó
25 Julio 2006
Mensajes
516
Solo un tema, el uso de docker y docker desktop requieren licenciamiento para uso comercial.


En reemplazo las distros estan migrando a podman/buildah, que son un poco mas rústicos y complejos de implementar si no eres usuario de Linux, pero funcionan parecido. Eso si, me ha pasado que algunos dockerfile no son directamente compatibles.


Slds
 
Upvote 0
Se incorporó
21 Marzo 2022
Mensajes
149
uuufff bien en palabras simple te sirve para orquestar contenedores (no se si conocer Docker Swarm que seria algo "parecido")... Kubernetes te ayudara a administrar todos tus contenedores de una forma super facil, con facil me refiero a que con un manifiesto yaml tu le indicas cuantas replicas del contenedor quieres, que imagen quieres (nginx, mysql, apache, etc) defines un servicio para llegar al contenedor (que en kubernetes estan dentro de PODS( que es la unidad mas pequeña en kubernetes), y por encima puedes tener un loadbalancer o un ingress para llegar desde el exterior a tus servicios.

Si en un momento un pod falla, una parte de kubernetes lo detecta y como en el manifiesto indicaste que querias 3 replicas y ahora te quedaste cn 2 el automaticamente te crea otro en base a la misma imagen y vuelves a tenr los 3... si detecta en base a ciertas configuraciones en tu manifiesto que los pods estan consumiento mucho recursos te escala a 4 , 5 6 o mas pods para que tu servicio no se sature y cuando el consumo de cpu o ram vuelve a la normalidad entonces comienza a maar los pods hasta dejarte las 3 replicas que indicaste al comienzo.

entonces tu le defines que quieres y cuentos pods quieres y kubernetes se encarga de mantenerte todo... eso en grandes rasgos xD


Para hacer pruebas puedes instalar Minikube en tu equipo linux y probarlo.
muy clara tu explicacion. Muchas gracias!
 
Upvote 0

epic

Pro
Se incorporó
11 Febrero 2007
Mensajes
846
Solo un tema, el uso de docker y docker desktop requieren licenciamiento para uso comercial.


En reemplazo las distros estan migrando a podman/buildah, que son un poco mas rústicos y complejos de implementar si no eres usuario de Linux, pero funcionan parecido. Eso si, me ha pasado que algunos dockerfile no son directamente compatibles.


Slds

Osea , yo se que Docker Desktop dejo de ser gratuito hace un tiempo, pero que Docker en Linux desde la consola sea pagado no lo he leído y tampoco creo que vaya a ser pagado ya que es de código abierto bajo la licencia Apache v2
 
Upvote 0

unreal4u

I solve problems.
Miembro del Equipo
ADMIN
Se incorporó
2 Octubre 2005
Mensajes
13.601
Solo un tema, el uso de docker y docker desktop requieren licenciamiento para uso comercial.


En reemplazo las distros estan migrando a podman/buildah, que son un poco mas rústicos y complejos de implementar si no eres usuario de Linux, pero funcionan parecido. Eso si, me ha pasado que algunos dockerfile no son directamente compatibles.


Slds
Docker Desktop es sólo una UI. docker-ce es el proceso que corre en el background, no necesitas una UI para manejar eso y sigue siendo Open Source.

Saludos.
 
Upvote 0
Subir