Saltar a contenido

40. Docker

40.1 Instalación de Docker en Ubuntu

40.1.1 Usando script oficial

En un entorno de desarrollo

sudo curl -fsSL https://get.docker.com | sh 
Descarga y ejecuta el script de instalación

40.1.2 Usando el repositorio Linux de docker

doc oficial 1. Instala paquetes necesarios

 sudo apt-get update

$ sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
2. Añadimos la clave oficial gpg de Docker

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
3. Añadimos el repositorio

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
4. Instalamos

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

# Comprobamos que funciona
sudo docker run hello-world

40.2 Persistencia de datos de contenedores, volumes y bind

Si no se utiliza ni bind ni volume los datos desaparecen al borrar el contenedor. Sin embargo con bin o volume se almacenan en directorios del host

40.2.1 bind mounts

Es un punto de montaje ente un archivo o directorio del host y un archivo o directorio del contenedor.
Casos para usar bind mounts: * Para compartir código fuente * Compartir archivos de configuracion entre host y contenedor

Para crear un bind mount dos posibilidades:
1. -v, --volume Se utiliza la síntasix:

path_host:path_contenedor [:opciones]
Posibles opciones: * ro sólo lectura * z compartido con varios contenedores * * Z contenedor privado y no compartido.

Ejemplo:

docker run -it --name ubuntu_c -v "$(pwd)":/test ubuntu

  1. Opcion mount .

Se utiliza una lista de clave valor.

Ejemplo:

docker run -it --name ubuntu_c --mount type=bind,source=$(pwd):/test ubuntu 
Las posibles claves: * type, opciones bind, volume, tmpfs * source, src : ruta completa en el host * destination, dest, target : directorio en el contenedor * readonly * bind-propagation :

La diferencia entre mount y -v , a parte de la sintaxis, con -v si no existe el directorio host , se crea; con mount se muestra un error

40.2.2 Volume

Los volumenes son gestionados por Docker y el directorio en el host depende del SO Para contenedores linux se creab en: /var/lib/docker/volumes

Se recomiendan los volumenes: * Para compartir datos entre multiples contenedores * Cuando el contenido del volumen puede estar en una máquina remota * Para almacenar el contenido de bases de datos de contenedores

40.2.2.1 Administar volumenes

Los volumenes se pueden crear mediatne comando de docker "volume" o en el comando run

Usando:

docker volume CMD
ge:  docker volume COMMAND

Manage volumes

Commands:
  create      Create a volume
  inspect     Display detailed information on one or more volumes
  ls          List volumes
  prune       Remove all unused local volumes
  rm          Remove one or more volumes
Con el comando run:
y opcion -v --volume --mount

[nombre_volumen_host:] path_contenedor [:opciones]
Si no aparece el nombre, Docker asigna uno aleatorio.

Posibles opciones: * ro sólo lectura * z compartido con varios contenedores * * Z contenedor privado y no compartido.

docker inspect nombre_contenedor
Muestra también información del volumen
Para consultar el volumen
docker volume inspect
##### Crear volumen
Usage: docker volume create [OPTIONS] [VOLUME]

Create a volume

Options: -d, --driver string Specify volume driver name (default "local") --label list Set metadata for a volume -o, --opt map Set driver specific options (default map[]) ```

40.3 Redes

Seguir en local redes .

40.4 Crear imagenes Docker

Podemos crear imagenes a partir de un contenedor o de otra imamgen. Para empezar un video :

40.4.1 Desde contenedor.

Podemos utilizarlo como una instantanea del desarrollo a la cual podemos volver

40.4.2 Dockerfile

La ventaja de usar un fichero dockerfile es que quedan registrados los cambios en la configuración y podemos modificar

Algunos enlaces: * referencia * Mejores practicas *

Un dockerfile está formado por capas de solo lectura. Cada capa es una instrucción docker, y se apilan y cada una es una delta (cambios) de la previa.

Ejemplo de dockerfile:

FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py
Cada instrucción crea una capa: 1. FROM indica la imagen base.Se recomienda imagenes de confianza como las alpine 2. COPY Añade ficheros desde el directorio actual a la imagen 3. RUN Construye la app con make 4. CMD Comando para ejecutar dentro de laimagen

Al crear un contenedor, se crea una capa en lo más alto container layer . Todos los cambios a partir de ahí se almacenan en esta capa.

40.4.3 Enteder el contexto de construcción de imagenes

Cuandos se ejecuta docker build , el directorio actual se llama build context . Este directorio se puede cambiar con la opciónn -f

40.4.4 Excluir ficheros con .dockerignore.

Se añade el fichero .dockerignore al directorio y es similar a .gitignore

40.4.5 Construcción multi capa.

Multi-stage build permite reducir el tamaño de la imagen y el tiempo de generación.Para ello se usa el cache de construcción. Por ejemplo, ordenar las capas de las menos usadas a las más frecuentes.

Varios ejemplos:

# syntax=docker/dockerfile:1
FROM golang:1.16-alpine AS build

# Install tools required for project
# Run `docker build --no-cache .` to update dependencies
RUN apk add --no-cache git
RUN go get github.com/golang/dep/cmd/dep

# List project dependencies with Gopkg.toml and Gopkg.lock
# These layers are only re-built when Gopkg files are updated
COPY Gopkg.lock Gopkg.toml /go/src/project/
WORKDIR /go/src/project/
# Install library dependencies
RUN dep ensure -vendor-only

# Copy the entire project and build it
# This layer is rebuilt when a file changes in the project directory
COPY . /go/src/project/
RUN go build -o /bin/project

# This results in a single layer image
FROM scratch
COPY --from=build /bin/project /bin/project
ENTRYPOINT ["/bin/project"]
CMD ["--help"]

40.4.6 Minimizar el número de capas

Sólo RUN, COPY ,ADD crean layer

40.4.7 Instrucciones en Dockerfile

  • FROM : referencia.
  • LABEL: Identifica las imagnes
  • RUN : Conviene dividir sentencias run complejas en varias. Referencia
  • RUN apt-get: Siempre convinar con apt-get update. Si se usa por separado puede crear problemas de cache.
         RUN apt-get update && apt-get install -y \
         package-bar \
         package-baz \
            package-foo  \
            && rm -rf /var/lib/apt/lists/*
    
    No olvidar -y para evitar preguntas
  • Usar pipes. Ejemplo

 RUN wget -O - https://some.site | wc -l > /number
* CMD : Ejecuta comandos incluidos en la imagen que pueden incluir argumentos. Por ejemplo: CMD ["apache2","-DFOREGROUND"]. para iniciar servicios. * EXPOSE Indica los puertos que el contenedor escuchará. Y por tanto se debe saber los puertos de los servicios incluidos, por ejemplo, con servidor apache el puerto 80 * ENV Establece las variables de entorno en la imagen. Por ejemplo puede usarse para cambiar la versión de la imagen . Cada ENV crea una nueva capa intermedia. Esto significa que aunte se haga un "unset" de la variable de entorno en una capa superior, persiste en esta capa y el valor puede ser usado:
  # syntax=docker/dockerfile:1
FROM alpine
ENV ADMIN_USER="mark"
RUN echo $ADMIN_USER > ./mark
RUN unset ADMIN_USER
Si se ejecuta:
docker run --rm test sh -c 'echo $ADMIN_USER'
el resultado sera mark

  • ADD or COPY Similares, se prefiere COPY Se prefiere utilizar varios COPY uno por fichero:

    COPY requirements.txt /tmp/
    RUN pip install --requirement /tmp/requirements.txt
    COPY . /tmp/
    
    Mejor que COPY . /tmp
    -- Añadir consejos de la página sobre ADD wget

  • ENTRYPOINT : Referencia.

40.5 Docker compose

Para crear contenedores mediante fichero.

Ejemplo:

version: '3' 
services: 
    web:
        container_name: ag_tensorflow
        image: tensorflow/tensorflow:latest-py3-jupyter
        ports: 
            - 8081:8888
            - 6006:6006
        volumes:
            - /home/asuarez/aworkspace:/tf

40.6 Herramientas

40.6.1 Portainer

Se instala como contenedor y sirve como interfaz de control de contenedores Instalación de Portainer versión C.E. (Community Edition). Al comando de instalación añadir -p 9000:9000 para que el puerto 9000 del host sea el puerto 9000 del contenedor. Esto nos permitirá acceder a la interfaz web de Portainer desde el navegador del host. Quedaria de la siguiente forma:

docker volume create portainer_data
docker run -d -p 8000:8000 -p 9443:p442 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce

40.7 tips and tricks

  • Si por algún motivo se modifican los ficheros de configuración de docker, se puede borrar el directorio /var/lib/docker y volver a instalar docker.

40.7.1 Cambiar el directorio para los volumenes

Paramos el servicio docker

sudo service docker stop
añadimos la siguiente linea a daemon.json
{
  "data-root": "/path/to/your/docker"
}
daemon .json puede encontrarse en
/etc/docker
# para Ubuntu puede estar en :
/var/snap/docker/current/config
Se copia el directorio actual para los volumenes a la nueva localización:
sudo rsync -aP /var/lib/docker/ /path/to/your/docker
# en ubuntu puede los volumenes pueden esdtar en
/var/snap/docker/common/var-lib-docker/volumes
Es conveniente renombrar el directorio origen por seguridad y comprobar que toda ha ido bien.
Reiniciar servicio
sudo service docker start

40.8 Algunos enlaces:

Enlaces:

  • https://docs.docker.com/compose/gettingstarted/
  • https://blog.dinahosting.com/servicio-web-con-docker-y-docker-compose/
  • https://jsitech1.gitbooks.io/meet-docker/archivo_docker-compose_en_detalle.html