Guía comandos para Docker
Docker es un sistema de contenedores orientado a microservicios. Están pensados para funcionar en cualquier entorno de trabajo, ya sea producción, desarrollo o QA, ya que permite desplegar un docker (contenedor) con un servicio y que este tenga todas las librerías necesarias para el entorno, lo que la hace una herramienta perfecta para el desarrollo de aplicaciones, debido a su flexibilidad y potencia.
Los docker están pensados para ser stateless; es decir, que no tengan información que varíe. Para esto, hay que hacer un mappeo de los directorios del docker donde se va a almacenar los datos que cambian y dejarlos en el host.
En esta entrada os daremos los comandos básicos para manejar docker, así como la configuración del DockerFile.
Comandos para Docker
Iniciar docker:
$ sudo systemctl start docker
Parar docker:
sudo systemctl stop docker
Obtener la IP de un contenedor:
$ docker inspect CONTENEDOR | grep '"IPAddress"' | head -n 1 | awk -v x=2 '{ gsub("\"",""); gsub(",",""); print $x}'
Imágenes docker
Ver las imágenes:
$ docker images
Borrar una imagen:
r rmi <image>
Crear una imagen desde un contenedor:
$ docker commit -a “creador” –m “comentario” <contenedor> <imagen_a_crear>
Crear una imagen desde un dockerfile:
$ docker build -t <nombre_imagen> -f <dockerfile> <path_de_destino_de_la_imagen>
Crear imagen a partir de un .tar:
docker load -i archivo.tar
Contenedores
Ver contenedores inactivos:
$ docker ps –a
Ver contenedores activos:
$ docker ps
Borrar contenedor:
$ docker rm <contenedor id>
Parar contenedor:
$ docker stop <contenedor id>
Arrancar contenedor parado:
$ docker start <contenedor id>
Iniciar contenedor:
$ docker run --name <contenedor> -p <puerto_origen>:<puerto_contenedor> <imagen_que_queremos_utilizar>
Entrar en un contenedor iniciado:
docker exec -it <contenedor> sh
Copiar fichero externo del contenedor a dentro del contenedor:
$ docker cp file <container-name>:/directorio/
Mostrar el registro de logs del contenedor:
$ docker logs <container>
Mostrar estadísticas de recursos del contenedor:
$ docker stats <container>
Instrucciones para Dockerfile
- FROM <image>: inicializa una nueva fase para la construcción de la imagen e indica que imagen se va a usar como base en las siguientes instrucciones.
- LABEL <key>=<value>: añade metadata a una imagen en modo par clave-valor.
- ADD <origin> <destiny>: copia nuevos ficheros o directorios (locales o remotos) al sistema de archivos de la imagen en el destino especificado.
- COPY <origin> <destiny>: copia ficheros o directorios al sistema de archivos de la imagen en el destino especificado.
- RUN <command>: ejecuta el/los comando/s indicados en una nueva capa por encima de la actual y guarda los cambios.
- ENV <key>=<value>: define variables de entorno para la imagen que se está creando, a partir de pares clave-valor.
- EXPOSE <port>: indica que el contenedor tendrá el puerto indicado disponible para escuchar peticiones en tiempo de ejecución.
- USER <user_to_change>: especifica el usuario a usar cuando se lance la imagen o para cualquier comando RUN, CMD y ENTRYPOINT.
- VOLUME [“<volume>”]: crea los volúmenes con el nombre especificado.
- WORKDIR /path/to/workdir: marca el directorio de trabajo para cualquier comando RUN, CMD, COPY, ADD y ENTRYPOINT.
- ARG <key>: define una variable que los usuarios pueden pasar en tiempo de construcción al constructor con el comando docker build –build-arg <varname>=<value>
- ENTRYPOINT <command> <param1> <param2>: permite configurar un contenedor que vaya a ser lanzado como un ejecutable.
Si te interesa conocer definiciones más extensas para su uso, puedes encontrarlas en la documentación oficial de Docker.
A continuación, se muestra un ejemplo de cómo quedaría definido uno de nuestros Dockerfile:
Dockerfile
# Selecciona la imagen a usar como base
FROM openjdk:8-jdk-alpine
# Añade etiquetas a los metadata de la imagen
LABEL module.maintainer="user@mail.es" \
module.name="project"
# Copia todos los ficheros exec.jar al fichero app.jar del contenedor
ADD *-exec.jar app.jar
# Crea las carpetas para los logs y el target de la aplicación
RUN mkdir -p /var/log/admin-logs && \
mkdir ./target
# Crea el grupo y el usuario onesait
RUN addgroup -S onesait -g 433 && adduser -u 431 -S -g onesait -h /usr/local -s /sbin/nologin onesait
# Da permisos al usuario y le hace propietario de las carpetas que necesitamos
RUN chown -R onesait:onesait /usr/local && \
chown -R onesait:onesait /var/log/admin-logs && \
chown -R onesait:onesait ./target && \
chown onesait:onesait app.jar && \
chmod -R 777 ./target && \
chmod -R 777 /var/log && \
chmod -R 777 /usr/local
# Define los volumenes que necesitamos para la imagen
VOLUME ["/tmp", "/var/log/admin-logs"]
# Indica el usuario onesait como el usuario a usar al lanzar la imagen
USER onesait
# Indica que la imagen usará el puerto 8080
EXPOSE 8080
# Pone valor a algunas variables entornos que tengamos definidas
ENV JAVA_OPTS="$JAVA_OPTS -Xms1G -Xmx3G" \
SERVER_NAME=localhost
# Indicamos el comando con el que se lanzará la imagen al ser ejecutada
ENTRYPOINT sh -c "java $JAVA_OPTS -Dspring.application.json=$ONESAIT_PROPERTIES -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -jar /app.jar" && 1
Dockerfile Templates
Springboot
FROM openjdk:8-jdk-alpine
# Metadata
LABEL module.maintainer="user@email.es" \
module.name="project"
ADD *-exec.jar app.jar
# logs folder
RUN mkdir -p /var/log/project-logs && \
mkdir ./target
# create onesait user/group
RUN addgroup -S onesait -g 433 && adduser -u 431 -S -g onesait -h /usr/local -s /sbin/nologin onesait
RUN chown -R onesait:onesait /usr/local && \
chown -R onesait:onesait /var/log/project-logs && \
chown -R onesait:onesait ./target && \
chown onesait:onesait app.jar && \
chmod -R 777 ./target && \
chmod -R 777 /var/log && \
chmod -R 777 /usr/local
VOLUME ["/tmp", "/var/log/project-logs"]
USER onesait
EXPOSE 8080
ENV JAVA_OPTS="$JAVA_OPTS -Xms1G -Xmx3G" \
SERVER_NAME=localhost
ENTRYPOINT sh -c "java $JAVA_OPTS -Dspring.application.json=$ONESAIT_PROPERTIES -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -jar /app.jar" && 1
Vue.js app
FROM node:lts-alpine as build-stage
# Metadata
LABEL module.maintainer="user@email.es" \
module.name="project"
WORKDIR /app
COPY package*.json ./
COPY .npmrc /root/.npmrc
COPY .npmrc ./
RUN npm config set registry https://registry.npmjs.org/ && \
npm install
COPY . .
RUN npm run build
# production stage
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
VOLUME ["/tmp", "/var/log/nginx"]
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Python app
FROM python:3.6
LABEL maintainer="arquitecturaDSP@indra.es"
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8
ENV http_proxy=${HTTP_PROXY}
ENV https_proxy=${HTTP_PROXY}
# create onesait user/group
#RUN addgroup onesait -g 433 && adduser -u 431 -g onesait onesait
RUN groupadd -r onesait && useradd --no-log-init -r -g onesait onesait
WORKDIR /app
COPY . /app
RUN chown -R onesait:onesait /usr/local && \
chown -R onesait:onesait /app && \
chmod -R 777 /var/log && \
chmod -R 777 /usr/local
# Update Python tools
RUN pip install --upgrade pip setuptools wheel
RUN pip install --upgrade -r requirements.txt
USER onesait
WORKDIR /app
# Expose the application's port
EXPOSE 5000
# Start service
CMD ["gunicorn", "-b 0.0.0.0:5000", "-w 2", "wsgi:app"]
Imagen de cabecera: Lanju Fotografie en Unsplash