Los contenedores Docker están diseñados para estar aislados unos de otros por defecto incluso desde el host gracias a namespaces y cgroups de Linux. – Cada contenedor tiene su propio espacio de red, procesos y sistema de archivos (a menos que se compartan explícitamente).
Dentro de su entorno aislado, los contenedores pueden abrir cualquier puerto.
Y también por defecto, los puertos internos no están mapeados al host, por lo que son inaccesibles desde fuera. Esto hace que sean inaccesibles desde cualquier red. Esto esto favorece la portabilidad y seguridad.
En un servidor podemos ejecutar varios contenedores al mismo tiempo que estarían todos intentando abrir el puerto 80 por ejemplo, y esto funciona dentro de un contenedor Docker porque estos contenedores están aislados del host.
Cada puerto puede ser utilizado una vez o por una sola aplicación, pero gracias a Docker estos puertos pueden ser accesibles por múltiples aplicaciones ya que Docker los mantiene en entornos aislados. Es decir, varios contenedores pueden usar el mismo puerto internamente (ej: dos contenedores con nginx escuchando en :80 dentro de cada uno). El “conflicto” solo ocurre si intentas mapear el mismo puerto del host (ej: -p 80:80 en dos contenedores a la vez).
La forma de acceder es publicando el puerto. Con el parámetro -p o -publish, nos permite mapear un puerto desde nuestra maquina host para acceder a un puerto en un contenedor.
Ejemplo con Nginx:
docker run -it -p 8888:80 nginx
El parámetro -it significa interactive terminal.
Desde nuestro navegador web accedemos http://localhost:8888 y nos mostrará la bienvenida de Nginx.
Esto mapea el puerto 80 que utiliza nginx de forma predeterminada al puerto 8888 de nuestro host. Lo que permite acceder a el contenedor.
El puerto 8888 queda ocupado y no puede ser utilizado por ningún otro servicio o contenedor.
Si lanzamos otro contenedor Docker esta vez en el puerto 8889, podemos ver que ambos servicios funcionan correctamente en simultáneo.
docker run -it -p 8889:80 nginx
Accedemos por http://localhost:8889
Esto debemos ejecutarlo en segundo plano para que todo funcione de manera mas fluida, ya que el contenedor se mantiene vivo mientras el proceso principal se esté ejecutando.
Para lograr ejecutar un contenedor en segundo plano lo hacemos con el parametro -d o –detach.
docker run -d -p 8889:80 nginx
Nos mostrá el id del contenedor lo que significa que se esta ejecutando en segundo plano.
Para saber que está pasando internamente podemos acceder a los logs
Con el comando docker container logs id_del_contenedor
A los contenedores se puede acceder por su ID. Tambie por su nombre de contenedor. Cuando creamos un contenedor se le asigna un nombre automaticamente y de forma aleatoria. Estos nombres deben ser únicos.
Podemos asignarle un nombre propio a un contenedor con el parametro –name cuando ejecutemos docker run:
docker run -it –name nginx-test-devops nginx
Si detenemos el proceso y volvemos a ejecutar el docker run con el mismo nombre del contenedor nos mostra´ra un error ya que el nobre sigue existiendo y no pueden haber 2 contenedores con el mismo nombre.
Podemos renombrar el nombre de un contenedor con el parámetro rename
docker container rename nginx-test-devops nuevo_nombre
Cada contenedor en ejecución ocupa recursos del sistema.
Con el comando docker container ls podemos ver los contenedores en ejecucion.
Con el comando docker container stop id_contenedor detenemos el contenedor. docker stop id_contenedor también funciona.
Podemos iniciarlo nuevamente con docker container start nombre_contenedor o docker start id_contenedor.
Podemos eliminar un contenedor con el parámetro rm
docker container rm id_contenedor o docker rm id_contenedor
Solo podemos eliminar contenedores que no esten en ejecucion.
Si queremos eliminar todos los contenedores en una sola linea de comando:
docker container rm $(docker container ls -aq)
Esto mediante shell hace una lista de los contenedores y luego los elimina.
Aunque detengamos un contenedor, este sigue exitiendo, con estatus “exited”.
Podemos removerlo o eliminarlo manualmente con el parametro rm, sin embargo, tambien se puede eliminar automaticamente con el parámetro –rm lo que hace que el contenedor se elimine cuando se detenga:
docker run -it –rm ubuntu
detenemos el contenedor ubuntu con la palabra exit.
De forma predeterinada, cada vez que se ejecuta un contenedor se ejecuta con un programa. Es decir, ejecutamos nginx y su programa especifico es bash, python -> python shell y asi…
Podemos cambiar el programa predeterminado por otro. Normalmente usaríamos el comando:
docker run -it –rm python
Esto nos ejecuta un container basado en la imagen de python con la shell de pyhton por su puesto.
Y si queremos la shell normal?
Podemos usar el comando
docker run -it –rm python bash
Ahora podríamos instalar herramientas como numpy con pip
pip install numpy
Y luego poder utilizar el programa de python
import numpy as np
Esto nos permite modificar un contenedor y adaptarlo a los requerimientos específicos.
Y si el contenedor ya está en ejecucion y queremos cambiar el programa o ejecutar un programa adicional?
Para lograr eso podemos ejecutar el comando docker container exec, especificamos el contenedor y luego el comando que queremos ejecutar.
docker container exec necesita que el contenedor ya esté en ejecucion.
Es muy útil cuando por ejemplo queremos crear archivo, descargar herramientas adicionales o depurar un contenedor.
Supongamos que ejecutamos python en un contenedor
docker container run –rm –name python-hero -it python
Hasta aquí nos mostraría la shell de python. Si intentamos usar la herramienta numpy nos dará un error.

Debemos instalar la herramienta numpy.
Podemos hacerlo en el mismo contenedor, ejecutamos bash. Desde otra terminal:
docker container exec -it python-hero bash
Entonces podríamos ejecutar comandos
pip install numpy

Volvemos a la shell de python
ejecutamos nuevamente:
import numpy as np
asy Money.
Otro método con exec:
docker container exec python-hero pip install numpy
Funcionará perfectamente. Si ya está instalada la herramienta dirá el mensaje.
Esta sería la forma no interactiva.
Cuando creamos un container con docker create y queremos una terminal en su creación lo hacemos con el parámetro -t o –tty. (-t de terminal).
Con el parámetro -i o –interactive podremos interactuar con el contenedor (-i de interective). Es decir, permitir que el contenedor reciba instrucciones por parte del usuario.
También debemos especificar puertos -p, o volumenes -v o variables de entorno -e.
Una vez el contenedor esta creado, estas opciones son inmutables.
docker container create -it ubuntu
Esto crea el contenedor sin iniciarlo.
Para iniciarlo:
docker container start id_container
Sin embargo, esto no me permite imteractuar con la terminal aunque ya se lo dije al momento de crearlo. Para esto usamos:
docker container start -i id_container
Supongamos que tenemos un contenedor con nginx queremos modificar la pagina de bienvenida.
docker container exec -it id_contenedor bash

Hemos ingresado a la terminal de ese contenedor.
Vamos a la carpeta donde nginx sirve los archivos.
cd /usr/share/nginx/html/
Editamos el archivo index.html con nano ;DD
nano no viene por defecto en el contenedor asi que debemos instalarlo
apt update
apt install nano -y
Ahora si:
nano index.html
podrimos modificar la linea:<h1>Welcome to nginx</h1>
por esta:<h1>Welcome to nginx for DEVOPS!</h1>
Guardamos
Verificamos en el navegador
http://localhost:8888
