centos · docker · linux · ubuntu · Virtualización · zonas

Jugando con Docker

Últimamente se esta oyendo mucho hablar de Docker. Se trata de una tecnología similar a la que ya existía en Solaris con las zonas, y en Linux con LXC (de hecho utiliza LXC por debajo). Parece que viene patrocinado por algunas de las grandes en internet como eBay, Spotify e incluso Google parece que venia utilizando algo parecido desde hace tiempo.

Docker

La gran ventaja, como en el caso de las zonas, es que te permite “virtualizar” sin depender de un hipervisor y con un overhead mínimo en comparación a la virtualización tradicional.

Instalación

Como todo en Linux es muy fácil de instalar y ya viene preparado en la mayoría de distribuciones. En el caso de CentOS hay que habilitar el repositorio EPEL editando el fichero de configuración del repositorio y poniendo la variable enabled a 1:

[root@centos1 ~]# vi /etc/yum.repos.d/epel.repo

[epel]
name=Extra Packages for Enterprise Linux 6 – $basearch
#baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6

A continuación ya podemos instalar docker con yum. Como veremos, una de las dependencias es LXC:

*[root@centos1 ~]# yum install docker-io
*

*Dependencies Resolved

================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
docker-io x86_64 1.0.0-3.el6 epel 4.5 M
Installing for dependencies:
lxc x86_64 0.9.0-2.el6 epel 78 k
lxc-libs x86_64 0.9.0-2.el6 epel 116 k

Transaction Summary
================================================================================
Install 3 Package(s)

Total download size: 4.7 M
Installed size: 24 M
Is this ok [y/N]: y

Así de sencillo es instalarlo. Y como vemos, la versión es la primera estable que se ha publicado recientemente:

[root@centos1 ~]# docker -v
Docker version 1.0.0, build 63fe64c/1.0.0

Para empezar a utilizarlo se debe iniciar el servicio y configurarlo para que arranque en el runlevel predeterminado:

[root@centos1 ~]# service docker start
Starting cgconfig service: [ OK ]
Starting docker: [ OK ]
[root@centos1 ~]# chkconfig docker on

Imágenes y contenedores

Con el servicio ya en marcha podemos descargar las imágenes que docker mantiene, así como imágenes que la comunidad ha creado y ha subido. Por ejemplo descargaremos las últimas para centos y para ubuntu:

[root@centos1 ~]# docker pull centos:latest
Pulling repository centos
0c752394b855: Download complete
511136ea3c5a: Download complete
34e94e67e63a: Download complete

[root@centos1 ~]# docker pull ubuntu:latest
Pulling repository ubuntu
e54ca5efa2e9: Download complete
511136ea3c5a: Download complete
d7ac5e4f1812: Download complete
2f4b4d6a4a06: Download complete
83ff768040a0: Download complete
6c37f792ddac: Download complete

Para ver las imágenes que tenemos descargadas y disponibles para utilizar bastará con ejecutar el subcomando “images”:

[root@centos1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu latest e54ca5efa2e9 41 hours ago 276.1 MB
centos latest 0c752394b855 10 days ago 124.1 MB

Pasando el parámetro -a podemos ver el historial de versiones de cada imagen:

[root@centos1 ~]# docker images -a
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu latest e54ca5efa2e9 41 hours ago 276.1 MB
6c37f792ddac 41 hours ago 276.1 MB
83ff768040a0 41 hours ago 192.7 MB
2f4b4d6a4a06 41 hours ago 192.7 MB
d7ac5e4f1812 41 hours ago 192.5 MB
centos latest 0c752394b855 10 days ago 124.1 MB
34e94e67e63a 2 weeks ago 0 B
511136ea3c5a 12 months ago 0 B

Podremos arrancar instancias o contenedores con las imágenes que queramos de la siguiente manera:

[root@centos1 ~]# docker run -i -t centos /bin/bash
bash-4.1# more /etc/centos-release
CentOS release 6.5 (Final)
bash-4.1# hostname
3ce460cbb9d8

[root@centos1 ~]# docker run -i -t ubuntu /bin/bash
root@60d6e0455be0:/# more /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION=”Ubuntu 14.04 LTS”
root@60d6e0455be0:/# hostname
60d6e0455be

Al pasar el parámetro -i al comando run se ejecutará el contenedor de forma interactiva, de forma que, en cuanto termine el comando que pasamos como parámetro la ejecución del contenedor terminará.

Mientras estemos ejecutando la shell, veremos que el contenedor está ejecutándose:

[root@centos1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
49087a343e7f centos:latest /bin/bash 12 seconds ago Up 11 seconds dreamy_curie

Si quisiesemos ver un historial de las instancias ejecutadas pasaríamos el parámetro -a:

[root@centos1 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
15dc7c59189c centos:latest /bin/bash 27 seconds ago Up 26 seconds compassionate_fermi
49087a343e7f centos:latest /bin/bash 12 minutes ago Exited (0) 17 seconds ago dreamy_curie
9e69f5b64254 ubuntu:latest uname -r 15 minutes ago Exited (0) 15 minutes ago high_engelbart
f5aa352a5ce9 centos:latest uname -r 15 minutes ago Exited (0) 15 minutes ago jovial_meitner
60d6e0455be0 ubuntu:latest /bin/bash 17 minutes ago Exited (0) 16 minutes ago cocky_leakey
961b10b9bbbf ubuntu:latest hostname 17 minutes ago Exited (0) 17 minutes ago insane_mayer
3ce460cbb9d8 centos:latest /bin/bash 19 minutes ago Exited (0) 17 minutes ago loving_yonath

Si por contra, quisiesemos ejecutar un contenedor en background o demonizado, como sucede en Solaris con las zonas, al comando run le pasaríamos el parámetro -d. En el siguiente ejemplo arrancaríamos una instancia de la imagen ubuntu y dos instancias de la imagen de centos y finalmente veríamos que se están ejecutando las tres:

[root@centos1 ~]# docker run -d -t ubuntu /bin/bash
abc254ab2e8eb392ce80938c8f2b8fa8cb1603ab6935b2121b7cb0cddbdd64c3
[root@centos1 ~]# docker run -d -t centos /bin/bash
59adfe1998cc678cf2c9db964f1b57e60a301ffa2139c7a4635ebe315db2b718
[root@centos1 ~]# docker run -d -t centos /bin/bash
6714217732adadec19f47399fe5f7252823787869a96e8fed72457cd5106589c
[root@centos1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6714217732ad centos:latest /bin/bash 3 seconds ago Up 2 seconds romantic_shockley
59adfe1998cc centos:latest /bin/bash 7 seconds ago Up 6 seconds thirsty_bartik
abc254ab2e8e ubuntu:latest /bin/bash 14 seconds ago Up 13 seconds naughty_yonath

Al arrancar cada contenedor nos devuelve un número muy largo. Este número es el container_id que mas adelante vemos en la primera columna del comando ps. La última columna es un nombre que se asigna automáticamente y servirá para identificar las instancias de una forma mas amigable. Para parar las zonas que están corriendo podríamos pasar como identificador tanto el container_id como el nombre:

[root@centos1 ~]# docker stop romantic_shockley
romantic_shockley
[root@centos1 ~]# docker stop thirsty_bartik
thirsty_bartik
[root@centos1 ~]# docker stop naughty_yonath
naughty_yonath
[root@centos1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

Como vemos, el kernel que se está ejecutando es el del host:

[root@centos1 ~]# uname -r
2.6.32-431.el6.x86_64
[root@centos1 ~]# docker run -i -t centos uname -r
2.6.32-431.el6.x86_64
[root@centos1 ~]# docker run -i -t ubuntu uname -r
2.6.32-431.el6.x86_64

Otra forma de arrancar un contenedor es con el comando start y pasando como parámetro el id del contenedor o el nombre que docker le asigno en su momento (lo podemos encontrar con docker ps -a)

[root@centos1 ~]# docker start romantic_shockley
romantic_shockley
[root@centos1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6714217732ad centos:latest /bin/bash 15 minutes ago Up 3 seconds romantic_shockley

Para acceder a la consola del contenedor ejecutaríamos el comando attach:

[root@centos1 ~]# docker attach romantic_shockley

Obtener información

Existe una serie de comandos que nos servirán para obtener información, tanto de docker, como de las imagenes o contenedores que tenemos creados. El comando info nos devolverá información general de la instalación actual de docker:

[root@centos1 ~]# docker info
Containers: 6
Images: 8
Storage Driver: devicemapper
Pool Name: docker-8:1-132310-pool
Data file: /var/lib/docker/devicemapper/devicemapper/data
Metadata file: /var/lib/docker/devicemapper/devicemapper/metadata
Data Space Used: 784.9 Mb
Data Space Total: 102400.0 Mb
Metadata Space Used: 1.4 Mb
Metadata Space Total: 2048.0 Mb
Execution Driver: native-0.2
Kernel Version: 2.6.32-431.el6.x86_64

Con el comando history veremos el historial de versiones de la imagen que le hayamos especificado:

[root@centos1 ~]# docker history centos
IMAGE CREATED CREATED BY SIZE
0c752394b855 10 days ago /bin/sh -c #(nop) ADD file:ce8fdb737386beb5fd 124.1 MB
34e94e67e63a 2 weeks ago /bin/sh -c #(nop) MAINTAINER The CentOS Proje 0 B
511136ea3c5a 12 months ago 0 B

También tendremos el comando inspect, que nos devolverá un objeto JSON con información detallada de la imagen. Tambien sirve para obetner información de un contenedor.

[root@centos1 ~]# docker inspect centos
[{
“Architecture”: “amd64”,
“Author”: “The CentOS Project \u003ccloud-ops@centos.org\u003e – ami_creator”,
“Comment”: “”,
“Config”: {
“AttachStderr”: false,
“AttachStdin”: false,
“AttachStdout”: false,
“Cmd”: null,
“CpuShares”: 0,
“Cpuset”: “”,
“Domainname”: “”,
“Entrypoint”: null,
“Env”: [
“HOME=/”,
“PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin”
],
“ExposedPorts”: null,
“Hostname”: “b2d0f1281acd”,
“Image”: “34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a”,
“Memory”: 0,
“MemorySwap”: 0,
“NetworkDisabled”: false,
“OnBuild”: [],
“OpenStdin”: false,
“PortSpecs”: null,
“StdinOnce”: false,
“Tty”: false,
“User”: “”,
“Volumes”: null,
“WorkingDir”: “”
},
“Container”: “b2d0f1281acd040292b36f6623feca10a89df1637c8d86e54079d473da4d05e3”,
“ContainerConfig”: {
“AttachStderr”: false,
“AttachStdin”: false,
“AttachStdout”: false,
“Cmd”: [
“/bin/sh”,
“-c”,
“#(nop) ADD file:ce8fdb737386beb5fd9aff7c9bbe9e6c9e60db290809dd6407c61b377e444b59 in /”
],
“CpuShares”: 0,
“Cpuset”: “”,
“Domainname”: “”,
“Entrypoint”: null,
“Env”: [
“HOME=/”,
“PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin”
],
“ExposedPorts”: null,
“Hostname”: “b2d0f1281acd”,
“Image”: “34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a”,
“Memory”: 0,
“MemorySwap”: 0,
“NetworkDisabled”: false,
“OnBuild”: [],
“OpenStdin”: false,
“PortSpecs”: null,
“StdinOnce”: false,
“Tty”: false,
“User”: “”,
“Volumes”: null,
“WorkingDir”: “”
},
“Created”: “2014-06-09T21:38:41.281490617Z”,
“DockerVersion”: “0.10.0”,
“Id”: “0c752394b855e8f15d2dc1fba6f10f4386ff6c0ab6fc6a253285bcfbfdd214f5”,
“Os”: “linux”,
“Parent”: “34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a”,
“Size”: 124078508
}

Para obtener informacion específica de un contenedor especificaremos al comando inspect la clave que queremos que nos devuelva, como por ejemplo el hostname o la dirección IP:

[root@centos1 ~]# docker run -d -t centos /bin/bash
d7e7938ab7e98ff8e2413179d5222201de6a0c66716b99aafb35a0805fbf279e
[root@centos1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d7e7938ab7e9 centos:latest /bin/bash 11 seconds ago Up 11 seconds nostalgic_newton

[root@centos1 ~]# docker inspect -f ‘{{ .Config.Hostname }}’ nostalgic_newton
d7e7938ab7e9
[root@centos1 ~]# docker inspect -f ‘{{ .NetworkSettings.IPAddress }}’ nostalgic_newton
172.17.0.22

Borrado de contenedores

Para norrar contenedores utilizaremos el comando rm. Le podremos pasar un único identificador de contenedor o varios en el mismo comando:

[root@centos1 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
abc254ab2e8e ubuntu:latest /bin/bash 22 minutes ago Exited (0) 18 minutes ago naughty_yonath
90ae553f4384 centos:latest /bin/bash 23 minutes ago Exited (-1) 22 minutes ago ecstatic_mcclintock

[root@centos1 ~]# docker rm ecstatic_mcclintock naughty_yonath
ecstatic_mcclintock
naughty_yonath