Algunos problemas que influyeron para la creación de Docker
Problemas del desarrollo de software
Promesa de Docker:
Construir, distribuir y ejecutar cualquier aplicación en cualquier lado.
Suena a java.
Una forma de resolver los problemas antes mencionados, es la emulación de un recurso computacional, en el caso de virtualización se emula computadoras completas dentro de una computadora más grande.
Problemas de la virtualización
Contenedores
docker info Client: Context: default Debug Mode: false Plugins: buildx: Build with BuildKit (Docker Inc., v0.5.1-docker) compose: Docker Compose (Docker Inc., v2.0.0-beta.6) scan: Docker Scan (Docker Inc., v0.8.0) Server: Containers: 2 Running: 1 Paused: 0 Stopped: 1 Images: 3 Server Version: 20.10.7 Storage Driver: overlay2 Backing Filesystem: extfs Supports d_type: true Native Overlay Diff: true userxattr: false Logging Driver: json-file Cgroup Driver: cgroupfs Cgroup Version: 1 Plugins: Volume: local Network: bridge host ipvlan macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: inactive Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc Default Runtime: runc Init Binary: docker-init containerd version: d71fcd7d8303cbf684402823e425e9dd2e99285d runc version: b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7 init version: de40ad0 Security Options: seccomp Profile: default Kernel Version: 5.10.16.3-microsoft-standard-WSL2 Operating System: Docker Desktop OSType: linux Architecture: x86_64 CPUs: 16 Total Memory: 11.95GiB Name: docker-desktop ID: WZLE:RNY4:ZHJQ:OGFA:IEU2:I3W3:MBE6:PUVM:I6EU:4GCE:R7SP:C7ZL Docker Root Dir: /var/lib/docker Debug Mode: false Registry: https://index.docker.io/v1/ Labels: Experimental: false Insecure Registries: 127.0.0.0/8 Live Restore Enabled: false WARNING: No blkio throttle.read_bps_device support WARNING: No blkio throttle.write_bps_device support WARNING: No blkio throttle.read_iops_device support WARNING: No blkio throttle.write_iops_device support
Listar contenedores en ejecución
docker ps
Listar contenedores incluidos los detenidos
docker ps -a
Para crear e iniciar (create and start) un contenedor se puede usar el método run
docker run $IMAGE $COMMAND
A menudo un problema típico cuando uno empieza con Docker es que arrancamos un contenedor y este arranca y se detiene justo después de arrancar.
Esto se debe a que a diferencia de una VM, docker corre el contenedor como un árbol de procesos, a partir de un proceso principal.
Al momento que termina el proceso principal, el contenedor es terminado.
El proceso principal se especifica con el parametro COMMAND al hacer create o run.
Como se verá más adelante también se puede indicar mediante una combinación de ENTRYPOINT y COMMAND.
Ejemplos de inicio de contenedores con terminación inmediata
docker run debian
docker run debian /bin/bash
La opción -t permite asignar una terminal al contenedor, la cual será asociada a la terminal donde lo arrancamos. Sin embargo al no ser interactiva no se envian nuestras pulsaciones de tecla, por lo que la terminal queda como congelada (no recibe entrada del teclado).
docker run -t debian bash root@04a9fa415379:/#
La opción -i nos permite indicar que el contenedor corre en modo interactivo, es decir recibe entrada del teclado, sin embargo al no asociar a una tty no se puede interactuar correctamente.
docker run -i debian bash oeauoeuoeu bash: line 1: $'oeauoeuoeu\r': command not found ls bash: line 2: $'ls\r': command not found who bash: line 3: $'who\r': command not found echo bash: line 4: $'echo\r': command not found /bin/bash : No such file or directory bash: line 6: $'\r': command not found
Al arrancar un contenedor podemos solicitar que sea interactivo y que se genere y asocie una tty con la terminal que estamos utilizando, combinando los dos modificadores anteriormente explicados.
La terminal queda asociada y al terminar el proceso bash, con exit el contenedor es terminado.
docker run -it debian bash root@742234a35dc9:/# ls -lh total 64K drwxr-xr-x 2 root root 4.0K Aug 16 00:00 bin drwxr-xr-x 2 root root 4.0K Apr 10 20:15 boot drwxr-xr-x 5 root root 360 Aug 20 01:23 dev drwxr-xr-x 1 root root 4.0K Aug 20 01:23 etc drwxr-xr-x 2 root root 4.0K Apr 10 20:15 home drwxr-xr-x 8 root root 4.0K Aug 16 00:00 lib drwxr-xr-x 2 root root 4.0K Aug 16 00:00 lib64 drwxr-xr-x 2 root root 4.0K Aug 16 00:00 media drwxr-xr-x 2 root root 4.0K Aug 16 00:00 mnt drwxr-xr-x 2 root root 4.0K Aug 16 00:00 opt dr-xr-xr-x 288 root root 0 Aug 20 01:23 proc drwx------ 2 root root 4.0K Aug 16 00:00 root drwxr-xr-x 3 root root 4.0K Aug 16 00:00 run drwxr-xr-x 2 root root 4.0K Aug 16 00:00 sbin drwxr-xr-x 2 root root 4.0K Aug 16 00:00 srv dr-xr-xr-x 11 root root 0 Aug 20 01:23 sys drwxrwxrwt 2 root root 4.0K Aug 16 00:00 tmp drwxr-xr-x 11 root root 4.0K Aug 16 00:00 usr drwxr-xr-x 11 root root 4.0K Aug 16 00:00 var root@742234a35dc9:/# exit exit alfonso.baqueiro@laptop ~
Para no bloquear la terminal es necesario desasociarlo con la opción -d, de igual forma se requiere -it para que bash se quede a la espera de comando y no sea terminado.
docker run -d -it debian bash 89d65fbbd8f2c22d03105c90fb6ec89a13420a869a9f72f0e8dbbada0f502342 $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 89d65fbbd8f2 debian "bash" 6 seconds ago Up 5 seconds affectionate_heisenberg
Como se puede ver docker nombra al contenedor con un nombre aleatorio, si queremos nombrarlo usamos la opción --name
docker run --name ponche -it -d debian 694af83771e38cb00b8426bbd89ac1a9135b05ecc53292ba7af4419c74780b99 $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 694af83771e3 debian "bash" 4 seconds ago Up 3 seconds ponche $
bash es el COMMAND por defecto, como podemos comprobar el contenedor permanece corriendo y la terminal es liberada
Para acceder al bash del proceso principal podemos usar attach.
Si salimos del bash, al ser el proceso main, se detiene el contenedor.
docker container attach ponche root@694af83771e3:/# exit exit $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 694af83771e3 debian "bash" 10 minutes ago Exited (0) 14 seconds ago ponche
Para volver a arrancar el contenedor usamos start
docker start ponche ponche $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 694af83771e3 debian "bash" 15 minutes ago Up 4 seconds ponche
Para ejecutar otro comando en un contenedorexec si el comando termina regresa el control al anfitrión.
docker exec ponche cat /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin _apt:x:100:65534::/nonexistent:/usr/sbin/nologin
Se puede usar para obtener un shell bash adicional, pero para salga de inmediato es necesario crear un tty en modo interactivo.
docker exec -it ponche bash root@694af83771e3:/# apt update Get:1 http://deb.debian.org/debian bullseye InRelease [113 kB] Get:2 http://security.debian.org/debian-security bullseye-security InRelease [44.1 kB] Get:3 http://security.debian.org/debian-security bullseye-security/main amd64 Packages [25.8 kB] Get:4 http://deb.debian.org/debian bullseye-updates InRelease [36.8 kB] Get:5 http://deb.debian.org/debian bullseye/main amd64 Packages [8178 kB] Fetched 8397 kB in 7s (1120 kB/s) Reading package lists... Done Building dependency tree... Done Reading state information... Done All packages are up to date. root@694af83771e3:/# apt install htop Reading package lists... Done Building dependency tree... Done Reading state information... Done The following additional packages will be installed: libgpm2 libncursesw6 libnl-3-200 libnl-genl-3-200 Suggested packages: lm-sensors lsof strace gpm The following NEW packages will be installed: htop libgpm2 libncursesw6 libnl-3-200 libnl-genl-3-200 0 upgraded, 5 newly installed, 0 to remove and 0 not upgraded. Need to get 379 kB of archives. After this operation, 1070 kB of additional disk space will be used. Do you want to continue? [Y/n] Get:1 http://deb.debian.org/debian bullseye/main amd64 libncursesw6 amd64 6.2+20201114-2 [132 kB] Get:2 http://deb.debian.org/debian bullseye/main amd64 libnl-3-200 amd64 3.4.0-1+b1 [63.6 kB] Get:3 http://deb.debian.org/debian bullseye/main amd64 libnl-genl-3-200 amd64 3.4.0-1+b1 [21.2 kB] Get:4 http://deb.debian.org/debian bullseye/main amd64 htop amd64 3.0.5-7 [127 kB] Get:5 http://deb.debian.org/debian bullseye/main amd64 libgpm2 amd64 1.20.7-8 [35.6 kB] Fetched 379 kB in 1s (632 kB/s) debconf: delaying package configuration, since apt-utils is not installed Selecting previously unselected package libncursesw6:amd64. (Reading database ... 6653 files and directories currently installed.) Preparing to unpack .../libncursesw6_6.2+20201114-2_amd64.deb ... Unpacking libncursesw6:amd64 (6.2+20201114-2) ... Selecting previously unselected package libnl-3-200:amd64. Preparing to unpack .../libnl-3-200_3.4.0-1+b1_amd64.deb ... Unpacking libnl-3-200:amd64 (3.4.0-1+b1) ... Selecting previously unselected package libnl-genl-3-200:amd64. Preparing to unpack .../libnl-genl-3-200_3.4.0-1+b1_amd64.deb ... Unpacking libnl-genl-3-200:amd64 (3.4.0-1+b1) ... Selecting previously unselected package htop. Preparing to unpack .../htop_3.0.5-7_amd64.deb ... Unpacking htop (3.0.5-7) ... Selecting previously unselected package libgpm2:amd64. Preparing to unpack .../libgpm2_1.20.7-8_amd64.deb ... Unpacking libgpm2:amd64 (1.20.7-8) ... Setting up libgpm2:amd64 (1.20.7-8) ... Setting up libncursesw6:amd64 (6.2+20201114-2) ... Setting up libnl-3-200:amd64 (3.4.0-1+b1) ... Setting up libnl-genl-3-200:amd64 (3.4.0-1+b1) ... Setting up htop (3.0.5-7) ... Processing triggers for libc-bin (2.31-13) ... root@694af83771e3:/# exit
Correr por ejemplo htop dentro del contenedor
docker exec ponche htop Error opening terminal: unknown.
Hay que recordar que por eso es necesario usar -it. (Para salir de htop presionar la tecla q).
docker exec -it ponche htop 0[ 0.0%] 4[ 0.0%] 8[ 0.0%] 12[ 0.0%] 1[ 0.0%] 5[ 0.0%] 9[ 0.0%] 13[ 0.0%] 2[| 0.7%] 6[| 0.7%] 10[ 0.0%] 14[ 0.0%] 3[ 0.0%] 7[ 0.0%] 11[ 0.0%] 15[ 0.0%] Mem[|||||||||||||||||||||||||||| 1.11G/12.0G] Tasks: 2, 0 thr; 1 running Swp[ 0K/4.00G] Load average: 0.02 0.03 0.48 Uptime: 3 days, 15:15:55 PID USER PRI NI VIRT RES SHR S CPU%-MEM% TIME+ Command 1 root 20 0 3964 3284 2852 S 0.0 0.0 0:00.02 bash 343 root 20 0 5636 3988 2964 R 0.0 0.0 0:00.02 htop
Para detener un contenedor usamos stop
docker stop ponche ponche $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 694af83771e3 debian "bash" 37 minutes ago Exited (137) 4 seconds ago ponche
Matar un contenedor por la mala SIGKILL kill, check exit code 137 - 128 = 9, o sea recibio la SIGKILL que es 9
docker kill ponche ponche $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 694af83771e3 debian "bash" 37 minutes agoExited (137) 4 seconds ago ponche
Para borrar un contenedor que se encuentra ejecutandose
docker rm -f $CONTAINER
Para borrar un contenedor que esta parado
docker rm $CONTAINER
Ejecutar un comando en un contenedor en ejecución
docker exec -it $CONTAINER $COMMAND
Crear un contenedor que se detenga después de N segundos usando como proceso sleep N ej. de un contenedor que se detiene tras 600 segundos
docker run -d debian sleep 600
Podemos hacer que se autodestruya si incluimos --rm
docker run --rm -d debian sleep 600
Usar como proceso principal un proceso que no termine para que el contenedor siga ejecutandose ej.
docker run -d debian tail -f /dev/null
docker run -d debian tail -f -n0 /etc/passwd
Por supuesto que lo más simple es correr un terminal interactivo detachado -ditque se mantenga como proceso main (bash).
docker run -dit debian
docker run -d --name proxy nginx CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c2e3294cc58f nginx "/docker-entrypoint.…" 3 minutes ago Up 3 minutes 80/tcp proxy # delete running container docker rm -f proxy # export a port docker run --name proxy -p 8080:80 nginx $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e6c96e20008b nginx "/docker-entrypoint.…" 2 seconds ago Up 2 seconds 0.0.0.0:8080->80/tcp proxy # mirar logs docker logs proxy proxy container logs ... # dar seguimiento a logs docker logs -f proxy # solo las ultimas lineas docker logs --tail $N_LINES -f proxy
Si inspeccionamos un volume, vemos que contiene la ruta donde se guardan los datos, ej: /var/lib/docker/volumes/mungus-data-db/_data
en windows se guarda en
C:\Users\$USER\AppData\Local\Docker\wsl\data\
al parecer dentro de un archivo ext4.vhdx
Hay otro tipo de mount tmpfs mount, el cúal es volatil pero solo funciona en linux
Se puede usar para copiar archivos de o hacía un contenedor, util para inyectar o extraer datos
docker cp $SOURCE $DESTINATION # $SOURCE and $DESTINATION pueden ser # CONTAINER:PATH or PATH # se puede usar aún si el contenedor esta parado
docker create --name mungus --mount src=mungus-data-db,dst=/data/db mongo 533d964c1c49b15507711f2df80b94bdd950069cab87f5fa9f5bf765b720e6a6 docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 533d964c1c49 mongo "docker-entrypoint.s…" About a minute ago Created mungus
https://hub.docker.com/ es el registry oficial de imagenes, aúnque es posible añadir otros registry
TAG es la versión, si no ponemos usa latest por omisión
docker image list REPOSITORY TAG IMAGE ID CREATED SIZE debian latest fe3c5de03486 20 hours ago 124MB mongo latest 269b735e72cb 12 days ago 682MB abaqueiro jessie-apache-php5.6.40 4fd786ff7d56 13 days ago 500MB ubuntu latest 1318b700e415 3 weeks ago 72.8MB php 5.6.40-apache-jessie d34f09f63596 2 years ago 374MB
docker image pull debian:buster buster: Pulling from library/debian 1cfaf5c6f756: Pull complete Digest: sha256:e2fe52e17d649812bddcac07faf16f33542129a59b2c1c59b39a436754b7f146 Status: Downloaded newer image for debian:buster docker.io/library/debian:buster docker image list REPOSITORY TAG IMAGE ID CREATED SIZE debian buster 63652705977d 20 hours ago 114MB debian latest fe3c5de03486 20 hours ago 124MB mongo latest 269b735e72cb 12 days ago 682MB abaqueiro jessie-apache-php5.6.40 4fd786ff7d56 13 days ago 500MB ubuntu latest 1318b700e415 3 weeks ago 72.8MB php 5.6.40-apache-jessie d34f09f63596 2 years ago 374MB
Una imagen es un conjunto de capas ordenado o apilado
Listar las imagenes actualmente disponibles
docker image list REPOSITORY TAG IMAGE ID CREATED SIZE debian buster 63652705977d 25 hours ago 114MB debian latest fe3c5de03486 25 hours ago 124MB mongo latest 269b735e72cb 12 days ago 682MB abaqueiro jessie-apache-php5.6.40 4fd786ff7d56 2 weeks ago 500MB ubuntu latest 1318b700e415 3 weeks ago 72.8MB wagoodman/dive latest 822b23d200a3 5 months ago 82.4MB php 5.6.40-apache-jessie d34f09f63596 2 years ago 374MB
Traer una imagen al cache de imagenes
docker image pull $IMAGE
docker image pull ubuntu:18.04 18.04: Pulling from library/ubuntu feac53061382: Pull complete Digest: sha256:7bd7a9ca99f868bf69c4b6212f64f2af8e243f97ba13abb3e641e03a7ceb59e8 Status: Downloaded newer image for ubuntu:18.04 docker.io/library/ubuntu:18.04
Podemos mostrar la historia de una imagen para ver como ha sido construida
docker image history $IMAGE
docker image history httpd IMAGE CREATED CREATED BY SIZE COMMENT c8ca530172a8 2 days ago /bin/sh -c #(nop) CMD ["httpd-foreground"] 0B2 days ago /bin/sh -c #(nop) EXPOSE 80 0B 2 days ago /bin/sh -c #(nop) COPY file:c432ff61c4993ecd… 138B 2 days ago /bin/sh -c #(nop) STOPSIGNAL SIGWINCH 0B 2 days ago /bin/sh -c set -eux; savedAptMark="$(apt-m… 61.2MB 2 days ago /bin/sh -c #(nop) ENV HTTPD_PATCHES= 0B 2 days ago /bin/sh -c #(nop) ENV HTTPD_SHA256=1bc826e7… 0B 2 days ago /bin/sh -c #(nop) ENV HTTPD_VERSION=2.4.48 0B 2 days ago /bin/sh -c set -eux; apt-get update; apt-g… 7.38MB 2 days ago /bin/sh -c #(nop) WORKDIR /usr/local/apache2 0B 2 days ago /bin/sh -c mkdir -p "$HTTPD_PREFIX" && chow… 0B 2 days ago /bin/sh -c #(nop) ENV PATH=/usr/local/apach… 0B 2 days ago /bin/sh -c #(nop) ENV HTTPD_PREFIX=/usr/loc… 0B 3 days ago /bin/sh -c #(nop) CMD ["bash"] 0B 3 days ago /bin/sh -c #(nop) ADD file:87b4e60fe3af680c6… 69.3MB
https://github.com/wagoodman/dive
Esta herramienta es un programa escrito en GO que permite explorar como esta construida una imagen $IMAGE
Podemos correrla como imagen de docker:
docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive:latest $IMAGE
Listar ids de contenedores
docker ps -aq 7ca393266942 533d964c1c49 6103e041fff3 fa82169f5e33 8214592c1bd7 452a600e3c5e
Para borrar un contenedor que se encuentra corriendo podemos usar
docker rm -f $CONTAINER
Podemos hacer una combinacion para borrar todo aún cuando estén corriendo
docker rm -f $(docker ps -aq)
El comando prune funciona con cualquier elemento
docker image prune
docker network prune
docker volume prune
Incluso si queremos hacer una limpieza total
docker system prune
consultar estadisticas de uso de recursos, (Ctrl+C para terminar)
docker stats CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 533d964c1c49 mungus 0.62% 208.3MiB / 11.95GiB 1.70% 2.41kB / 0B 0B / 0B 34 6103e041fff3 debeianita 0.00% 26.26MiB / 11.95GiB 0.21% 16.8MB / 300kB 0B / 0B 2 fa82169f5e33 soyloquesoy 0.00% 876KiB / 11.95GiB 0.01% 4.14kB / 0B 0B / 0B 1
restringir la memoria a 1 Gb
docker run --memory 1g $IMAGE
Para ilustrar este punto, vamos a crear una instancia de debian versión 10
docker run -itd --name try-debian-10 debian:10
Nos agenciamos una shell a la instancia corriendo
docker exec -it try-debian-10 bash
Corremos comandos normales de administración de paquetes en debian
root@63e736f5cb4d:/# apt-get update Get:1 http://deb.debian.org/debian buster InRelease [122 kB] Get:2 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB] Get:3 http://deb.debian.org/debian buster-updates InRelease [51.9 kB] Get:4 http://deb.debian.org/debian buster/main amd64 Packages [7907 kB] Get:5 http://security.debian.org/debian-security buster/updates/main amd64 Packages [301 kB] Get:6 http://deb.debian.org/debian buster-updates/main amd64 Packages [15.2 kB] Fetched 8463 kB in 3s (2541 kB/s) Reading package lists... Done
Podemos determinar exactamente que archivos genera o afecta dicho comando, lo que nos permite identificar que archivos se pueden borrar para optimizar el tamaño de nuestras imagenes, y también para aprender que sucede tras bambalinas
$ docker diff try-debian-10 C /root A /root/.bash_history C /var C /var/lib C /var/lib/apt C /var/lib/apt/lists A /var/lib/apt/lists/auxfiles A /var/lib/apt/lists/deb.debian.org_debian_dists_buster_InRelease A /var/lib/apt/lists/deb.debian.org_debian_dists_buster_main_binary-amd64_Packages.lz4 A /var/lib/apt/lists/partial A /var/lib/apt/lists/security.debian.org_debian-security_dists_buster_updates_main_binary-amd64_Packages.lz4 A /var/lib/apt/lists/deb.debian.org_debian_dists_buster-updates_InRelease A /var/lib/apt/lists/deb.debian.org_debian_dists_buster-updates_main_binary-amd64_Packages.lz4 A /var/lib/apt/lists/lock A /var/lib/apt/lists/security.debian.org_debian-security_dists_buster_updates_InRelease
Como es fácil observar, se afectan archivos en /var/lib/apt/lists que como es muy probable son archivos de cache, por lo que probablemente se puedan remover para generar una imagen compacta.
root@63e736f5cb4d:/# du -hs /var/lib/apt/lists 17M /var/lib/apt/lists
Podemos por ejemplo lanzar una imagen efímera para saber cuanto espacio ocupa /var/lib/apt/lists antes del apt-get update
docker run --rm -it debian:10 du -hs /var/lib/apt/lists 4.0K /var/lib/apt/lists
Lo anterior nos confirma que ese directorio se encuentra vació en un estado inicial, y por tanto se puede generar mediante apt-get update.
Cabe destacar el derroche de poder, somos como dioses de la creación y destrucción, creando o destruyendo galaxias completas.
En este caso creamos un sistema debian solo para saber cuando espacio ocupaba uno de los directorios, y luego de saber, destruimos la instancia.
Continuando con el plan, la idea es instalar aplicaciones de uso común para desarrollo y testing como son:
setup:
root@63e736f5cb4d:/# apt-get update && apt-get install -y \ apt-file \ curl \ dnsutils \ git \ htop \ less \ man \ net-tools \ netcat \ nmap \ pv \ tree \ unzip \ vim \ wget \ zip
docker commit -a "Alfonso Baqueiro" try-debian-10 debian-tools:10 sha256:f3429b20f86e006d39fcb99cb13ee98802396be76029b372617b418afe5257f7 docker image list REPOSITORY TAG IMAGE ID CREATED SIZE debian-tools 10 f3429b20f86e 26 seconds ago 466MB
Todas estas moficicaciones manuales que hicimos a la instancia, se pueden hacer replicables y prácticamente como una receta de construcción mediante el Dockerfile
Creamos la imagen mediante build
docker build -t debian-tools:10 . [+] Building 44.4s (6/6) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 251B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/debian:10 0.0s => CACHED [1/2] FROM docker.io/library/debian:10 0.0s => [2/2] RUN apt-get update && apt-get install -y apt-file curl dnsutils git htop less man net-tools netcat nmap pv tree unzip vim wget zip 42.5s => exporting to image 1.8s => => exporting layers 1.8s => => writing image sha256:42522ffc8a73ba0d41e76cd6f1b881e1f5d668e32057ca2f7eb19b684cd91300 0.0s => => naming to docker.io/library/debian-tools:10 0.0s Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
Verificamos de que tamaño ha quedado la imagen, como podemos ver ocupa 367MB vs 466MB de la imagen que hicimos usando commit , esto seguramente debido a archivos cache, cosa que evitamos al hacer limpia.
docker image list REPOSITORY TAG IMAGE ID CREATED SIZE debian-tools 10 42522ffc8a73 38 hours ago 367MB <none> <none> f3429b20f86e 39 hours ago 466MB
Un aspecto valioso es poder compartir esta imagen, cosa que podemos hacer subiendola a docker hub mediante push
Para ello necesitamos tener una cuenta, que podemos crear en hub.docker.com
Y luego hacer login mediante
docker login
docker push debian-tools:10 The push refers to repository [docker.io/library/debian-tools] 40efc50d7e6b: Preparing c2ddc1bc2645: Preparing denied: requested access to the resource is denied
Esto se debe a que estamos tratando de ponerlo en el library principal, nos ha faltado especificar la cuenta de usuario donde se debe poner la imagen.
docker push abaqueiro/debian-tools:10 The push refers to repository [docker.io/abaqueiro/debian-tools] An image does not exist locally with the tag: abaqueiro/debian-tools
No encuentra la imagen, por lo que es necesario etiquetarla
docker tag debian-tools:10 abaqueiro/debian-tools:10 docker image list REPOSITORY TAG IMAGE ID CREATED SIZE abaqueiro/debian-tools 10 42522ffc8a73 39 hours ago 367MB
Reintentamos el push
docker push abaqueiro/debian-tools:10 The push refers to repository [docker.io/abaqueiro/debian-tools] 40efc50d7e6b: Pushed c2ddc1bc2645: Pushed 10: digest: sha256:d18a263a3b0ad52f335f59cd63bfcc9d0d2e6c1526d1b6deec32a0eff75805db size: 741
docker network list NETWORK ID NAME DRIVER SCOPE 610dcd163dd2 bridge bridge local 3ab918f7294b host host local 89ccac87dd2e none null local
docker network inspect bridge [ { "Name": "bridge", "Id": "610dcd163dd2f3391d56b1e51724f464307d2a13d9c1cdc49a263257456056a1", "Created": "2021-08-22T12:44:55.04629582Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "45a111c7e4ab2301d8f4fa222cdac7a4a6bc2a837c9a4d8de44ef154065324b8": { "Name": "platziapp", "EndpointID": "6c67031fd5a66e6ca71827bf8b313c035ae3d8a5d468130d3901de5ec378c5a4", "MacAddress": "02:42:ac:11:00:04", "IPv4Address": "172.17.0.4/16", "IPv6Address": "" }, "533d964c1c49b15507711f2df80b94bdd950069cab87f5fa9f5bf765b720e6a6": { "Name": "mungus", "EndpointID": "9953358bc0e00ba0be67f34ccb54f21261618fc5e2eb65cf76484e3425d3fb65", "MacAddress": "02:42:ac:11:00:03", "IPv4Address": "172.17.0.3/16", "IPv6Address": "" }, "63e736f5cb4d1246984e1ffdcb0cdcbd56f8af9e53ebc900899146abda1b0e97": { "Name": "try-debian-10", "EndpointID": "979b35dc1821e54fa704575d09c4145d3e103da5adb65337e86f2ce4e229fbc2", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ]
Crear una red extra
docker network create --attachable --driver=bridge --subnet=172.23.0.0/16 --ip-range=172.23.5.0/24 --gateway=172.23.0.1 skynet 31a8e6735c835159fcab3dd5a33baa4fa9cd4a52eda2067f467ab3f6c2d12f34 docker network list NETWORK ID NAME DRIVER SCOPE 610dcd163dd2 bridge bridge local 3ab918f7294b host host local 89ccac87dd2e none null local 31a8e6735c83 skynet bridge local docker network inspect skynet [ { "Name": "skynet", "Id": "31a8e6735c835159fcab3dd5a33baa4fa9cd4a52eda2067f467ab3f6c2d12f34", "Created": "2021-08-24T18:10:48.581489897Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.23.0.0/16", "IPRange": "172.23.5.0/24", "Gateway": "172.23.0.1" } ] }, "Internal": false, "Attachable": true, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": {}, "Labels": {} } ] docker network connect skynet mungus docker network inspect skynet [ { "Name": "skynet", "Id": "31a8e6735c835159fcab3dd5a33baa4fa9cd4a52eda2067f467ab3f6c2d12f34", "Created": "2021-08-24T18:10:48.581489897Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.23.0.0/16", "IPRange": "172.23.5.0/24", "Gateway": "172.23.0.1" } ] }, "Internal": false, "Attachable": true, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "45a111c7e4ab2301d8f4fa222cdac7a4a6bc2a837c9a4d8de44ef154065324b8": { "Name": "platziapp", "EndpointID": "24f2ba319e5bef98ae3db52873e8868e7f9a8f4872066948cdf7081c7f5f5734", "MacAddress": "02:42:ac:17:05:00", "IPv4Address": "172.23.5.0/16", "IPv6Address": "" }, "533d964c1c49b15507711f2df80b94bdd950069cab87f5fa9f5bf765b720e6a6": { "Name": "mungus", "EndpointID": "f21693a794e89cbe6601f68d54b86d3db793ad062d1606b4bd9d777548607d6c", "MacAddress": "02:42:ac:17:05:01", "IPv4Address": "172.23.5.1/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ]
Cabe destacar que si analizamos como ven la red los contenedores encontramos que se crea una interface de red adicional eth1
docker exec -it mungus ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.3 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet) RX packets 15045 bytes 19908156 (19.9 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 8085 bytes 442611 (442.6 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0eth1 : flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.23.5.1 netmask 255.255.0.0 broadcast 172.23.255.255 ether 02:42:ac:17:05:01 txqueuelen 0 (Ethernet) RX packets 12 bytes 936 (936.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 docker exec -it platziapp ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.4 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:ac:11:00:04 txqueuelen 0 (Ethernet) RX packets 6070 bytes 8638989 (8.2 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 2498 bytes 137181 (133.9 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0eth1 : flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.23.5.0 netmask 255.255.0.0 broadcast 172.23.255.255 ether 02:42:ac:17:05:00 txqueuelen 0 (Ethernet) RX packets 19 bytes 1522 (1.4 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Un aspecto interesante es que cuando creamos una red y añadimos un contenedor, docker maneja y configura un servicio de DNS para los contenedores y resuelve a IP los nombres de los contenedores
* Para correr nslookup o dig es necesario instalar en el contenedor dnsutils mediante el gestor de paquetes apt.
docker exec -it platziapp nslookup mungus Server: 127.0.0.11 Address: 127.0.0.11#53 Non-authoritative answer: Name: mungus Address: 172.23.5.1 docker exec -it platziapp ping -c 5 mungus PING mungus (172.23.5.1) 56(84) bytes of data. 64 bytes from mungus.skynet (172.23.5.1): icmp_seq=1 ttl=64 time=0.076 ms 64 bytes from mungus.skynet (172.23.5.1): icmp_seq=2 ttl=64 time=0.073 ms 64 bytes from mungus.skynet (172.23.5.1): icmp_seq=3 ttl=64 time=0.164 ms 64 bytes from mungus.skynet (172.23.5.1): icmp_seq=4 ttl=64 time=0.101 ms 64 bytes from mungus.skynet (172.23.5.1): icmp_seq=5 ttl=64 time=0.162 ms
Una última prueba será destruir la red skynet
docker network rm skynet Error response from daemon: error while removing network: network skynet id 31a8e6735c835159fcab3dd5a33baa4fa9cd4a52eda2067f467ab3f6c2d12f34 has active endpoints docker network disconnect skynet mungus docker network disconnect skynet platziapp docker network rm skynet skynet
Ej. de archivo docker-compose.yml donde se declaran los servicios, en este caso app y db
Levantar servicios
docker-compose up
Revisamos los efectos generados por docker-compose, es decir que contenedores fueron levantados y sus recursos
docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d06a807d84de platziapp "docker-entrypoint.s…" 3 hours ago Up 3 hours 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp 014-docker_app_1 49cfe2494613 mongo "docker-entrypoint.s…" 3 hours ago Up 3 hours 27017/tcp 014-docker_db_1 docker network list NETWORK ID NAME DRIVER SCOPE 309a7fc12128 014-docker_default bridge local docker network inspect 014-docker_default [ { "Name": "014-docker_default", "Id": "309a7fc1212892eae515a836ad8b33401f0d57f06f0c6d7fe45f04e6bfd2d01f", "Created": "2021-08-24T19:30:30.013063875Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1" } ] }, "Internal": false, "Attachable": true, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "49cfe24946135f9af38daa4159ef741640fd2fa165062217f5fb30b3d1f1294b": { "Name": "014-docker_db_1", "EndpointID": "b0f6c0b06089066c692ed603b487679cc353f367f865baaf9fb7acca7f2ddebb", "MacAddress": "02:42:ac:12:00:02", "IPv4Address": "172.18.0.2/16", "IPv6Address": "" }, "d06a807d84deade968aacd66acfec128e69b80afd63bdbab7cc5cc8683aec846": { "Name": "014-docker_app_1", "EndpointID": "0860f7b81488d18dc9e789539aed1cebad541e91c8e28be098dabcdaca97ff3d", "MacAddress": "02:42:ac:12:00:03", "IPv4Address": "172.18.0.3/16", "IPv6Address": "" } }, "Options": {}, "Labels": { "com.docker.compose.network": "default", "com.docker.compose.project": "014-docker", "com.docker.compose.version": "1.29.2" } } ]
Como ejecutamos el up attached, podemos detener los contenedores con Ctrl+C
Ctrl+C CHECKPOINT_PROGRESS] saving checkpoint snapshot min: 67, snapshot max: 67 snapshot count: 0, oldest timestamp: (0, 0) , meta checkpoint timestamp: (0, 0) base write gen: 1"}} db_1 | {"t":{"$date":"2021-08-24T22:28:34.729+00:00"},"s":"I", "c":"STORAGE", "id":22430, "ctx":"Checkpointer","msg":"WiredTiger message","attr":{"message":"[1629844114:729347][1:0x7fd48afab700], WT_SESSION.checkpoint: [WT_VERB_ CHECKPOINT_PROGRESS] saving checkpoint snapshot min: 68, snapshot max: 68 snapshot count: 0, oldest timestamp: (0, 0) , meta checkpoint timestamp: (0, 0) base write gen: 1"}} db_1 | {"t":{"$date":"2021-08-24T22:29:34.769+00:00"},"s":"I", "c":"STORAGE", "id":22430, "ctx":"Checkpointer","msg":"WiredTiger message","attr":{"message":"[1629844174:769250][1:0x7fd48afab700], WT_SESSION.checkpoint: [WT_VERB_ CHECKPOINT_PROGRESS] saving checkpoint snapshot min: 69, snapshot max: 69 snapshot count: 0, oldest timestamp: (0, 0) , meta checkpoint timestamp: (0, 0) base write gen: 1"}} Gracefully stopping... (press Ctrl+C again to force) Stopping 014-docker_app_1 ... done Stopping 014-docker_db_1 ... done docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d06a807d84de platziapp "docker-entrypoint.s…" 3 hours ago Exited (137) 17 seconds ago 014-docker_app_1 49cfe2494613 mongo "docker-entrypoint.s…" 3 hours ago Exited (0) 16 seconds ago 014-docker_db_1
Es posible correr los comandos de docker sin necesidad de siempre estar en el directorio donde se encuentran el archivo docker-compose.yml, lo vamos a hacer para ver como vuelve a levantar en modo dettached los contenedores
cd ../../ docker-compose -f platzi/014-docker/docker-compose.yml up -d Starting 014-docker_db_1 ... done Starting 014-docker_app_1 ... done docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d06a807d84de platziapp "docker-entrypoint.s…" 3 hours ago Up 5 minutes 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp 014-docker_app_1 49cfe2494613 mongo "docker-entrypoint.s…" 3 hours ago Up 5 minutes 27017/tcp 014-docker_db_1
De todos los contenedores
docker-compose logs
De un solo contenedor y con seguimiento
docker-compose logs -f app
docker-compose exec app bash
docker-compose stop
docker-compose down Stopping 014-docker_app_1 ... done Stopping 014-docker_db_1 ... done Removing 014-docker_app_1 ... done Removing 014-docker_db_1 ... done Removing network 014-docker_default
Modificamos el Dockerfile para tener capas, una base para las dependencias y otra para nuestro código
De igual manera indicamos en el docker-compose.yml que para app se tiene que construir una imagen y no tomar una.
Ahora si le pedimos a docker compose hacer el build
docker compose build db uses an image, skipping Building app [+] Building 8.4s (11/11) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 210B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 133B 0.0s => [internal] load metadata for docker.io/library/node:12 1.2s => [auth] library/node:pull token for registry-1.docker.io 0.0s => [internal] load build context 0.0s => => transferring context: 103.03kB 0.0s => CACHED [1/5] FROM docker.io/library/node:12@sha256:61748e56917a2f65621d68c9d9497c7bc420551a29f4be3543a373665eafd6e3 0.0s => [2/5] COPY [package.json, package-lock.json, /usr/src/] 0.1s => [3/5] WORKDIR /usr/src 0.0s => [4/5] RUN npm install 6.4s => [5/5] COPY [index.js,/usr/src/] 0.0s => exporting to image 0.5s => => exporting layers 0.4s => => writing image sha256:e10443abd65d82d5404bba0662e48fd99c8e0769a7f0285901677fb80dc7a805 0.0s => => naming to docker.io/library/014-docker_app
Lo anterior crea una imagen y la nombre de forma automática de acuerdo al nombre del directorio
docker image list REPOSITORY TAG IMAGE ID CREATED SIZE 014-docker_app latest 0fc3e2326451 25 hours ago 931MB
La idea sería poder levantar un entorno más adecuado para desarrollo, destacando
No lleva image, indica que se tiene que hacer un build
En el caso de bind mounts, se pueden indicar mediante volumes
En este Dockerfile se monta el contexto pero ignorando lo que está en /usr/src/node_modules
El cambio en el command es para que node monitore cambios en index.js y reinicie el servicio cuando se requiera (por desgracia no funciona correctamente en windows)
Normalmente ocurre que queremos usar configuraciones diferentes para nuestro entorno de desarrollo
, pero no queremos modificar el docker-compose.yml original.
Para ello contamos con el archivo docker-compose.override.yml
Docker va a hacer una mezcla de las directivas en ambos archivos.
Ejemplo de docker-compose.override.yml
docker compose build [+] Building 1.8s (10/10) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 32B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 34B 0.0s => [internal] load metadata for docker.io/library/node:12 1.7s => [internal] load build context 0.0s => => transferring context: 100B 0.0s => [1/5] FROM docker.io/library/node:12@sha256:61748e56917a2f65621d68c9d9497c7bc420551a29f4be3543a373665eafd6e3 0.0s => CACHED [2/5] COPY [package.json, package-lock.json, /usr/src/] 0.0s => CACHED [3/5] WORKDIR /usr/src 0.0s => CACHED [4/5] RUN npm install 0.0s => CACHED [5/5] COPY [index.js,/usr/src/index.js] 0.0s => exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:c5ce3d88b9c0b45d95aa2973011e88a90f8fe1098c322bf48187506c37deb479 0.0s => => naming to docker.io/library/my-app-image docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE my-app-image latest c5ce3d88b9c0 2 minutes ago 931MB
Como se puede ver, se combinan ambos, y las directivas del .override sobre escriben las del docker-compose.yml
La idea es por ejemplo levantar dos instancias de app
docker compose up -d --scale app=2 [+] Running 2/4 - Network 014-docker_default Created 0.8s - Container 014-docker_db_1 Started 3.6s - Container 014-docker_app_2 Starting 4.7s - Container 014-docker_app_1 Starting 4.7sError response from daemon: driver failed programming external connectivity on endpoint 014-docker_app_2 (5564ae0d218fa49057b0926045db8ac79965d6c047716e9ba28bb1baeff4fa69): Bind for 0.0.0.0:3000 failed: port is already allocated docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 042772e51f1b c5ce3d88b9c0 "docker-entrypoint.s…" 20 seconds ago Created 014-docker_app_2 00e18fc49cf6 c5ce3d88b9c0 "docker-entrypoint.s…" 21 seconds ago Up 15 seconds 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp 014-docker_app_1 37f6f651df2a 269b735e72cb "docker-entrypoint.s…" 21 seconds ago Up 17 seconds 27017/tcp 014-docker_db_1
Como se puede ver la segunda instancia genera un error al no poder asociarse al puerto 3000, y no arranca, aparece su status como created
Para especificar un rango de puertos que se puedan mapear en el afitrion podemos hacerlo en el docker-compose.yml mediante un rango de puertos, ej. del 2000 al 2001
docker compose up -d --scale app=2 Creating network "014-docker_default" with the default driver Creating 014-docker_db_1 ... done WARNING: The "app" service specifies a port on the host. If multiple containers for this service are created on a single host, the port will clash. Creating 014-docker_app_1 ... done Creating 014-docker_app_2 ... done docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 125bfdf7c244 my-app-image "docker-entrypoint.s…" 9 seconds ago Up 6 seconds 0.0.0.0:2001->3000/tcp, :::2001->3000/tcp 014-docker_app_2 e90532bb1187 my-app-image "docker-entrypoint.s…" 10 seconds ago Up 7 seconds 0.0.0.0:2000->3000/tcp, :::2000->3000/tcp 014-docker_app_1 52778a603da6 mongo "docker-entrypoint.s…" 11 seconds ago Up 10 seconds 27017/tcp 014-docker_db_1
Este tema es para observar la diferencia en la forma de especificar el CMD en el Dockerfile
loop.sh
Dockerfile.shell-form
Dockerfile.exec-form
Construimos las imagenes necesarias
docker build -f Dockerfile.shell-form -t loop-shell-form . [+] Building 0.2s (7/7) FINISHED docker build -f Dockerfile.exec-form -t loop-exec-form . [+] Building 0.1s (7/7) FINISHED docker image list REPOSITORY TAG IMAGE ID CREATED SIZE loop-exec-form latest c433c20457b1 49 seconds ago 72.8MB loop-shell-form latest 85af1449a747 49 seconds ago 72.8MB docker run -d --name pillo-shell-form loop-shell-form 10641c52b1119cbc064ba7385fd06f433fb049d2344070479697a60b6663fa68 docker run -d --name pillo-exec-form loop-exec-form 2ea8acd3565b445892476ae1da7488cf64735225f6baccfd14b1ffb93dcd9621
Notar la diferencia en el arbol de procesos entre ambas formas:
docker exec -it pillo-shell-form ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 03:25 ? 00:00:00 /bin/sh -c /loop.sh root 8 1 99 03:25 ? 00:02:24 bash /loop.sh root 18 0 0 03:27 pts/0 00:00:00 ps -ef docker exec -it pillo-exec-form ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 99 03:28 ? 00:01:35 bash /loop.sh root 7 0 0 03:29 pts/0 00:00:00 ps -ef
Paramos los contenedores, notar el exit code en cada caso:
docker stop pillo-exec-form docker stop pillo-shell-form docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2ea8acd3565b loop-exec-form "/loop.sh" 3 minutes ago Exited (0) 42 seconds ago pillo-exec-form 10641c52b111 loop-shell-form "/bin/sh -c /loop.sh" 6 minutes ago Exited (137) 12 seconds ago pillo-shell-form
Docker envia la señal SIGTERM al proceso con PID 1, pero este no necesariamente la reenvia a los procesos hijos , lo que se requiere para un graceful shutdown.
Haciendo limpieza
docker rm pillo-exec-form pillo-shell-form docker image rm loop-exec-form loop-shell-form
Vamos a construir una imagen que ejecute el comando ping en un contenedor
Para ello vamos a generar una imagen con el siguiente Dockerfile
Generamos la imagen alpine-ping
docker build -t alpine-ping . [+] Building 3.0s (6/6) FINISHED
Intentemos ejecutar la imagen y obtener un bash como normalmente hacemos
docker run --rm alpine-ping bash ping: bad address 'bash'
Como puede verse se trata de hacer ping a la dirección bash, es decir docker ejecuta por defecto
el comando especificado en el ENTRYPOINT como base
y añade como parametro lo que se pasa como CMD en la llamada
Ejecutamos la imagen para probar que se hace ping 10 veces (-c10) a 127.0.0.1 (localhost)
docker run --rm alpine-ping PING 127.0.0.1 (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.047 ms 64 bytes from 127.0.0.1: seq=1 ttl=64 time=0.110 ms 64 bytes from 127.0.0.1: seq=2 ttl=64 time=0.111 ms 64 bytes from 127.0.0.1: seq=3 ttl=64 time=0.056 ms 64 bytes from 127.0.0.1: seq=4 ttl=64 time=0.112 ms 64 bytes from 127.0.0.1: seq=5 ttl=64 time=0.113 ms 64 bytes from 127.0.0.1: seq=6 ttl=64 time=0.116 ms 64 bytes from 127.0.0.1: seq=7 ttl=64 time=0.111 ms 64 bytes from 127.0.0.1: seq=8 ttl=64 time=0.087 ms 64 bytes from 127.0.0.1: seq=9 ttl=64 time=0.111 ms --- 127.0.0.1 ping statistics --- 10 packets transmitted, 10 packets received, 0% packet loss round-trip min/avg/max = 0.047/0.097/0.116 ms
Debido a lo anterior es posible pasar el nombre del dominio al que queremos hacer ping como parametro
docker run --rm alpine-ping google.com PING google.com (216.58.195.238): 56 data bytes 64 bytes from 216.58.195.238: seq=0 ttl=37 time=13.399 ms 64 bytes from 216.58.195.238: seq=1 ttl=37 time=11.562 ms 64 bytes from 216.58.195.238: seq=2 ttl=37 time=18.470 ms 64 bytes from 216.58.195.238: seq=3 ttl=37 time=11.932 ms 64 bytes from 216.58.195.238: seq=4 ttl=37 time=17.515 ms 64 bytes from 216.58.195.238: seq=5 ttl=37 time=12.425 ms 64 bytes from 216.58.195.238: seq=6 ttl=37 time=13.718 ms 64 bytes from 216.58.195.238: seq=7 ttl=37 time=14.281 ms 64 bytes from 216.58.195.238: seq=8 ttl=37 time=9.918 ms 64 bytes from 216.58.195.238: seq=9 ttl=37 time=9.906 ms --- google.com ping statistics --- 10 packets transmitted, 10 packets received, 0% packet loss round-trip min/avg/max = 9.906/13.312/18.470 ms
Cuando construimos una imagen a partir del Dockerfile, el último argumento es la ruta para el
contexto de build.
Si en el Dockerfile hacemos COPY [".","/destination/path"], se terminan copiando
todos los archivos que se encuentran en la ruta del contexto de build.
Podemos usar el archivo .dockerignore para especificar que archivos del contexto no se deben incluir al hacer COPY, es un concepto similar al .gitignore