Diferencia entre revisiones de «Docker»

De Ardemans Wiki
Saltar a: navegación, buscar
(Instalacioń en Centos 7)
(Saber los tags de una imagen en un registry remoto)
 
(5 revisiones intermedias por el mismo usuario no mostrado)
Línea 34: Línea 34:
 
</pre>
 
</pre>
 
* Añadimos servicio de registro de Docker de ECI como "origen inseguro" de imágenes docker
 
* Añadimos servicio de registro de Docker de ECI como "origen inseguro" de imágenes docker
  * Tendremos que modificar el fichero de servicio de systemd, así que lo copiamos en el /etc:
+
** Tendremos que modificar el fichero de servicio de systemd, así que lo copiamos en el /etc:
<pre>
+
<pre>
$ cp /lib/systemd/system/docker.service /etc/systemd/system/
+
$ cp /lib/systemd/system/docker.service /etc/systemd/system/
</pre>
+
</pre>
  * Modificamos el fichero /etc/systemd/system/docker.service con el siguiente contenido (en negrita la parte que tenemos que añadir y modificar)
+
** Modificamos el fichero /etc/systemd/system/docker.service con el siguiente contenido (en negrita la parte que tenemos que añadir y modificar)
 
<pre>
 
<pre>
 
[Unit]
 
[Unit]
Línea 63: Línea 63:
 
WantedBy=multi-user.target
 
WantedBy=multi-user.target
 
</pre>
 
</pre>
    * Recorgar configuracion de systemd
+
** Recorgar configuracion de systemd
 
<pre>
 
<pre>
 
$ systemctl daemon-reload
 
$ systemctl daemon-reload
Línea 322: Línea 322:
 
<pre>
 
<pre>
 
$ curl localhost:5000/v2/<nombre-imagen>/tags/list
 
$ curl localhost:5000/v2/<nombre-imagen>/tags/list
 +
</pre>
 +
 +
Contra una versión antigua de registry me ha funcionado la siguiente consulta
 +
 +
<pre>
 +
$ curl http://server.domain.int:5000/v1/repositories/devel/my-nginx/tags
 
</pre>
 
</pre>

Última revisión de 14:54 11 abr 2016

Introducción

Mis notas mientras aprendo a usar docker. Como siempre en mis notas puede haber cosas erróneas que iré corrigiendo según vaya descubriendo.


Lo que entiendo por Docker

Un gestor de ejecución de aplicaciones en entornos cerrados, lo que se conoce como 'contenedores', como se podria hacer con chroot, pero que se extiende mucho mas allá con el manejo de los puertos que abre cada, acceso a volumenes de datos, etc.

Esos contenedores se pueden personalizar con los servicios o scripts que queramos y se pueden exoprtar fácilmente a otros host que tenga docker. Esa exportación hasta donde he visto se hace mediante el uso de Docker Hub, que es un servicio en la nube (a modo github) donde se almacenan esos contenedoresñ, aunque también he visto que existe el servicio "privado" para que lo montes de forma interna en tu red (ver docker-registry en github)

Documentación

Hasta el momento impecable, con un tutorial online para probar los primeros pasos y después extensa guía de usuario bien estructurada donde paso a paso se van aprendiendo todas las carácterísticas.

Instalación

Muy bien documentada también la instalación para cada S.O. en URL. La instalación se hace mediante la descarga y ejecución de un script, que al final realiza una serie de pasos, añade un source al apt e instala los paquetes de ubuntu.

Instalacioń en Centos 7

Apunto aquí una instalación especifica para un Centos 7 con SystemD y al que hay que cambiar ciertos parámetros en el arranque de docker.

En Centos7, en el repositorio por defecto se instala docker versión 1.8, pero con este método vamos a instalar una versión más moderna (en este ejemplo se instala la version 1.10)

  • Hacerse root (sudo -i)
  • Instalar docker mediante el script que hay en la web
$ curl -fsSL https://get.docker.com/ | sh
  • Creamos el grupo docker
$ groupadd docker
  • Añadimos al usuario spindrift al grupo de docker
$ usermod -aG docker spindrift
  • Añadimos servicio de registro de Docker de ECI como "origen inseguro" de imágenes docker
    • Tendremos que modificar el fichero de servicio de systemd, así que lo copiamos en el /etc:
 $ cp /lib/systemd/system/docker.service /etc/systemd/system/
 
    • Modificamos el fichero /etc/systemd/system/docker.service con el siguiente contenido (en negrita la parte que tenemos que añadir y modificar)
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target docker.socket
Requires=docker.socket

[Service]
Type=notify
Environment=http_proxy=http://t0000104:12345678@proxycorp.geci:8080/
Environment=https_proxy=https://t0000104:12345678@proxycorp.geci:8080/
Environment=no_proxy=localhost,MX00000018W0001.eci.geci:5000
Environment='INSECURE_REGISTRY_PARAMETER=--insecure-registry=MX00000018W0001.eci.geci:5000,localhost:5000'
Environment='DOCKER_DNS_PARAMETER=--dns=[192.168.50.170,192.168.50.171]'
ExecStart=/usr/bin/docker daemon ${INSECURE_REGISTRY_PARAMETER} -H fd://
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
TimeoutStartSec=0

[Install]
WantedBy=multi-user.target
    • Recorgar configuracion de systemd
$ systemctl daemon-reload
  • Arrancamos servicio de docker
$ systemctl start docker

Ya tenemos docker en la máquina

Uso básico

Trabajo con las Imagenes

Para listar las imágenes que tenemos descargadas

docker images

Para buscar una imagen nueva podemos buscar directamente en la web de docker hub o podemos buscar a través de la línea de comandos

docker search <palabra>

Para descargar una imagen podemos usar el siguiente comando, aunque no es extrictamente necesario, ya que si hacemos uso de una imagen que no tenemos en local irá a buscarlo al repositorio externo

docker pull ubuntu:14.04

Si queremos borrar una de las imagenes que nos hemos descargado podemos usar el siguiente comando

docker rmi ubuntu


Los contenedores

A partir de una imagen podemos levantar un contenedor ejecutando alguna aplicación que contenga. Un ejemplo muy sencillo sería ejecutar un echo

docker run ubuntu:14.04 echo "Una prueba"

Esto lo que hará será crear el contenedor a partir de la imagen ubuntu (con el tag 10.04) y ejecutar el echo dentro del contenedor. Una vez finalizada la ejecución el contenedor permanece creado

Podemos ver las ejecuciones que se están realizando en los diferentes contenedores

docker ps

Si queremos ver además todos los conetenedores, incluso los que no están actualmente ejecutando nada podemos añadir el parámetro -a.

Cada contenedor que se crea tiene asignado un ID y un nombre. Se puede hacer referencia al contenedor a través del ID o del nombre. El nombre se asigna de forma automática a no ser que nosotros se lo especifiquemos en el run con el parámetro --name


Cualquiera de esos contenedores "parados" se pueden volver a ejecutar con:

docker start <id_contenedor>

Lo que se ejecutará será el comando que hayamos ejecutado la última vez, que en el caso anterior será el echo "Una Prueba" que hemos hecho antes.

Si queremos borrar uno de los contenedores (se perderán los cambios o datos que se hayan generado) podremos usar:

docker rm <id_contenedor>


Opciones al ejecutar un contenedor

Si ejecutamos con "run" el contenedor a partir de una imagen, sin parámetros como hemos hecho antes, el proceso se quedará en consola, pero podemos ejecutarlo con la opción detached, para que se ejecute en segundo plano.

docker run -d ubuntu find /usr

De esta forma hemos ejecutado el comando find (que tarda un rato) y nos ha devuelto el control a la consola inmediatamente y no hemos visto la salida por consola. Si queremos ver el resultado que ha salido por consola de ese comando, en ese contenedor, siempre podemos conslutar con el comando:

docker logs <id_contenedor>

en el caso anterior veremos la salida de "find /usr" que hemos hecho.

Si el proceso que vamos a ejecutar dentro del contenedor va a pedir algun tipo de entrada por consola entonces tendremos que usar el parámetro -i

docker run -i register rm -i /bin/true

Preguntará por consola si queremos borrar ese fichero, pero si no ponemos el -i no nos dará oportunidad para contestar y directamente se terminará el proceso.

Si además el proceso que vamos a ejecutar es una shell tendremos que usar el parametro -t que asigna una pseudo-tty, de esta forma podremos acceder al contenedor como si de una máquina fuera:

docker run -t -i register /bin/bash

Redes

Si, hay comunicación entre los contenedores que arrancamos, y hasta podemos definir diferentes redes en las que arrancamos cada uno de ellos, y contenedores que pueden estar en varias redes a la vez.

Si no nos preocupamos de entrada de esto de la redes, los contenedores que arrancamos tendrán incluido un iface en la red "bridge", que se crea por defecto cuando instalamos docker. En esta red tenemos una forma de comunicar un contenedor con otro, usando el parámetro --link.

Link de contenedores (legacy)

Técnica para que un contenedor pueda conectarse a un puerto de otro. Par esto se usa la opción --link, a la hora de arrancar al contenedor que hará la conexión de origen. Por ejemplo, un servidor web se arrancaría con esta opción para poder hacer peticiones a un puerto de un contenedor de DB.

A este comando link tendremos que pasar como parámetro el nombre del contenedor al que nos vamos a conectar, y el nombre interno con el que queremos referenciar a ese servidor dentro del contenedor. Por eso es importante usar el nombrado de contenedores a la hora de arrancar el contenedor al que nos vamos a conectar:

Ejemplo

Arrancamos un contenedor de DB de Mongo

$ docker run --name mydb -d mongo

A destacar el parámetro --name que da un nombre a nuestro nuevo contenedor ejecutando mongo. También es destacable el hecho de que no hemos publicado ningún puerto.

Arrancamos el servidor web:

$ docker run -p 80:80 -d --link mydb:db httpd

El parámetro link hace que en el servidor WEB estén disponibles ciertas variables de entorno que hacen referencia al contenedor de DB, y que se pueden usar en configuraciones. Estas variables de entorno se crean por cada puerto expuesto del contenedor al que nos queremos conectar, en nuestro caso el de DB solo tiene uno.

DB_PORT_27017_TCP=tcp://172.17.0.1:27017
DB_PORT=tcp://172.17.0.1:27017
DB_PORT_27017_TCP_PORT=27017
DB_PORT_27017_TCP_PROTO=tcp
DB_PORT_27017_TCP_ADDR=172.17.0.1

También se crea una entrada en el fichero de /etc/hosts con los datos del servidor de DB:

172.17.0.1	db 5f128b6d3df6 jolly_pasteur

Mucha más información aquí

Uso de redes definidas por el usuario

Enlace a la página oficial con la documentación de user defined networks

Lo mejor es mostrar ejemplos:

Crear una nueva red:

$ docker network create --subnet 172.10.0.0 mired

En realidad no hace falta poner el parámetro --subnet, ya que se define de forma automática una subred.

Teniendo una red definida podemos arrancar nuevos contenedores usando esa nueva red:

$ docker run -itd --net=mired --name mongo1 mongo:latest

La red por defecto si no especificamos el parámetro --net es la red "bridge", que tenemos de inicio en docker. La diferencia de la red que hemos definido nosotros y la red por defecto es que en la nuestra podemos hacer link a un contenedor que todaviá no hemos creado:

$ docker run -itd --net=mired --name mongo2 --link mongo1:mongo1 mongo:latest
$ docker run -itd --net=mired --name mongo1 --link mongo2:mongo2 mongo:latest

De esta forma tenemos dos contenedores que se pueden comunicar en ambos sentidos.

Otras operaciones que podemos realizar es la de añadir un contenedor ya arrancado a una red de forma dinámica, o tambien quitarlo (connect, disconnect)

$ docker network connect mired mongo3


Almacenamiento

Si queremos que un contenedor exporte un volumen que tenemos en nuestra máquina, usamos la opción -v

$ docker run -d -v /data/db --name mymongo mongo

Podemos buscar donde ha creado ese directorio en nuestro host local con un:

$ docker inspect mymongo

Pero también podemos especificar un directorio de nuestra máquina directamente, a la hora de crear el contenedor

$ docker run -d -v /opt/mongodata:/data/db --name mymongo mongo

Siempre se tiene que especificar un path absoluto. Se puede especificar un fichero, y solo se compartirá ese fichero en el contenedor que estamos arrancando

Contenedor de volumen de datos

Se llama así a los contenedores que se crean solo para proveer de volumenes de datos a otros contenedores. Por así decirlo, es una forma de separar los datos del proceso. De esta manera, de forma sencilla, se puede recrear el contenedor del proceso sin cambiar por ello el contenedor que realmente tiene los datos.

Un ejemplo de como usar esto, para una máquina de DB de Mongo:

$ docker create -v /data/db --name mongo_data --entrypoint /bin/true mongod_2_6_7

con esto vamos a crear en local un volumen con el directorio de DB de mongo. Este contenedor solo se crea, no se arranca nunca, y además se especifica un entrypoint que realmente no hace nada.

Después podemos arrancar el contenedor de proceso indicando que queremos usar los volumenes definidos en el contenedor de datos:

$ docker run -d --name mymongo --volumes-from mongo_data mongod_2_6_7

Con el parámetro --volumes-from decimos que queremos montar los mismos volumenes que tiene el contenedor de datos creado antes. Ojo, porque también se montan los volúmenes especificados durante el proceso de construcción de la imagen. No solo estará el volumen /data/db, sino también el volumen /logs y el /security que ya venía de serie con la imagen que hemos usado para crear estos dos contenedores.

Más sobre el tema de volumenes en esta página

Configuración del servicio de docker

DNS

he notado que las imágenes por defecto vienen con su configuración propia de DNS en el fichero /etc/resolv.conf. En concreto, en mi máquina Ubuntu (que utiliza dnsmasq) cuando arranco un contenedor desdel a imagen básica de Centos me aparece configurado los DNS's publicos de google.

Si queremos personalizar esa configuración, podemos cambiarla desde la creación de una imagen propia, o podemos hacer que sea dependiente de la infraestructrua que ejecuta ese contenedor, es decir, del servicio docker que lo ejecuta. De esta forma, al crear una imagen usara unos DNS diferentes si la arrancamos en local o si la arrancamos en una cloud pública... por ejemplo.

Tendremos que añadir la siguiente configuración a nuestro servicio de docker

# Fichero /etc/defaul/docker

# Use DOCKER_OPTS to modify the daemon startup options.
DOCKER_OPTS="--dns 192.168.50.170 --dns 192.168.50.171"

Registros locales

Es muy probable que queramos conectarnos a servicios de registro de docker locales. No podremos hacer uso de estos registros hasta que especifiquemos a nuestro servicio docker que ese registro es inseguro pero conocido, para eso tendremos que añadir un nuevo parámetro al arranque de nuestro servicio docker:

# Fichero /etc/default/docker
DOCKER_OPTS="--insecure-registry MX00000018W0001:5000"

Algunos trucos

Borrar todos los contenedores de mi máquina

Yo que se... si estás haciendo pruebas te puede interesar... Haciendo uso del parámetro -q del docker ps, que muestra solo los id's de los contenedores, podemos mezclarlo con un docker rm:

docker rm -f $(docker ps -a -q)

Saber los tags de una imagen en un registry remoto

Al parecer no es una cosa sencilla, y buscando he visto que se puede consultar a través de una URL de la API.

$ curl -s -S 'https://registry.hub.docker.com/v2/repositories/library/centos/tags/

Contra registros internos no me ha funcionado, y además depende de la versión del registro que estás consultando. En un servicio de registro de docker (levantado desde imagen de docker) de la versión 2.3 me ha funcionado la consluta:

$ curl localhost:5000/v2/<nombre-imagen>/tags/list

Contra una versión antigua de registry me ha funcionado la siguiente consulta

$ curl http://server.domain.int:5000/v1/repositories/devel/my-nginx/tags