11

Entorno de Docker para la carrera de Data Science

Entorno de Docker

Luego de tomar el curso de Docker, me plantee la idea de trasladar mi entorno de trabajo a Docker, ya que eventualmente esto me permitirá tener mi entorno de trabajo disponible sin importar si migro de sistema operativo, algo que me ha pasado antes usando Deepin, Debian o Fedora.

Lo principal es poder determinar los requisitos del entorno de trabajo para poder desarrollar los cursos que faltan y eventualmente convertirlo en mi entorno de trabajo y desarrollo.

Los requisitos de mi entorno son:

  • Python (version 3.8.7)
  • PostgreSQL
  • MySQL (version 5.7)
  • MongoDB
  • R

Para solucionar esto he decidido hacer pull a las imágenes de PostgreSQL, MySQL y MongoDB. Posteriormente uniré todo con docker compose para poder crear la red y tener acceso a todos los engines.

En cuanto a Python y R, decidí instalarlos en una sola imagen personalizada. La razón por la cual usaré una sola imagen para Python y R es que quiero instalar el kernel de R para poder ejecutar código en R dentro de Jupyter.

<h3>Python y R</h3>

Para crear la imagen de Python con R instalado tome como base la imagen de Python 3.8.7. Decidí usar particularmente esta versión para poder instalar en un futuro Tensorflow. Elegi la version slim para reducir peso en la imagen final.

También agregué un usuario y un directorio de home para poder montar los archivos de Platzi.

FROM python:3.8-slim

# Create a newuser
RUN["useradd", "--create-home", "mmenendezg"]

# Select the working directoryto home of the user
WORKDIR/home/mmenendezg/

Esta imagen de Python está creada tomando como base Debian 10, por lo que podemos usar apt y apt-get para instalar dependencias.

Lo siguiente que hice fue actualizar las dependencias e instalar Zsh (preferencias personales). El parametro -y es para evitar error cuando la terminal pide que aceptemos la instalación del paquete.

# Update and upgrade dependenciesRUN["apt-get", "update"]
RUN["apt-get", "upgrade"]

# Install zsh RUN["apt-get", "install", "-y", "zsh"]

Lo siguiente es poder instalar los paquetes del entorno de Python. Lo primero es copiar el archivo requirements.txt a la carpeta de trabajo (WORKDIR), y luego ejecutar pip install.

# Copy the requirements file and install it  
COPY["requirements.txt", "."]
RUN["pip", "install", "--no-cache-dir", "-r", "requirements.txt"]

Lo siguiente es instalar R.

# Install RRUN["apt", "install", "-y", "r-base"]

COPY["packages.r", "."]
RUN["Rscript", "packages.r"]

El archivo packages.r es el archivo que contiene los paquetes a instalar para el kernel de R en Jupyter. Pueden ver como instalarlo aquí.

Por último, seleccionamos el user por defecto de la imagen y la zsh por defecto.

# Select the user USERmmenendezg

CMD["zsh"]

El archivo final de dockerfile es el siguiente:

FROM python:3.8-slim

# Create a newuser
RUN["useradd", "--create-home", "--shell", "/bin/bash", "mmenendezg"]

# Select the working directoryto home of the user
WORKDIR/home/mmenendezg/

# Updateandupgrade dependencies
RUN["apt-get", "update"]
RUN["apt-get", "upgrade"]

# Install zsh 
RUN["apt-get", "install", "-y", "zsh"]

# Copy the requirements fileandinstall it  
COPY["requirements.txt", "."]
RUN["pip", "install", "--no-cache-dir", "-r", "requirements.txt"]

# Install R
RUN["apt", "install", "-y", "r-base"]

COPY["packages.r", "."]
RUN["Rscript", "packages.r"]

# Select the user USERmmenendezg

CMD["zsh"]

<h3>Docker compose para las bases de datos</h3>

Para poder unificar todo cree un dockerfile que permite correr las imágenes al mismo tiempo.

En mi file hay 4 servicios: el de Python y R, el de PostgreSQL, el de MySQL y el de MongoDB.

El de Python luce asi:

app:
    build: .
    image: marlonmg/data-science
    volumes:
      - ./:/home/mmenendezg/
    ports: 
      - '8888:8888'stdin_open: truetty: true

El puerto 8888 lo expuse para poder acceder a Jupyter desde el browser. En un futuro quizá sea necesario exponer un puerto adicional para el puerto 80 de la imagen.

La opcion stdin_open seria el equivalente a la opcion docker run -i, mientras que la opcion tty es el equivalente a docker run -t.

Para el servicio de PostgreSQL exponemos el puerto 543. También agregué las variables de entorno de usuario y password para la conexión. Monte en mis archivos una carpeta de data donde guardaré las bases de datos de PostgreSQL, MySQl y MongoDB. Estoy usando la última versión de PostgreSQL.

postgres:image: postgres
    ports: 
        - '5432:5432'volumes: 
        - ./data/postgres:/var/lib/postgresql/dataenvironment: 
        - POSTGRES_USER=user
        - POSTGRES_PASSWORD=super-pass

Para la imagen de MongoDB expuse el puerto 27017 y monte el almacenamiento en mi carpeta data. Igualmente agregue las variables de entorno.

  mongodb:
    image: mongo
    ports: 
      -'27017:27017'    volumes: 
      - ./data/mongodb:/data/db
    environment: 
      - MONGO_INITDB_ROOT_USERNAME=user
      - MONGO_INITDB_ROOT_PASSWORD=otro_super-pass

Finalmente para la imagen de MySQL, usaré la versión 5.7, ya que es la versión que se usa en los cursos.

mysql:image:mysql:5.7ports:
      - '3306:3306'volumes: 
      - ./data/mysql:/var/lib/mysqlenvironment: 
      - MYSQL_USER=user
      - MYSQL_PASSWORD=otro_super-pass_mas

Mi archivo docker-compose.yml final quedo asi:

version: "3.8"

services: 
  app:
    build: .
    image: marlonmg/data-science
    volumes:
      - ./:/home/mmenendezg/    ports: 
      -'8888:8888'    stdin_open: true
    tty: true

  postgres:
    image: postgres
    ports: 
      -'5432:5432'    volumes: 
      - ./data/postgres:/var/lib/postgresql/data
    environment: 
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=super-pass

  mongodb:
    image: mongo
    ports: 
      -'27017:27017'    volumes: 
      - ./data/mongodb:/data/db
    environment: 
      - MONGO_INITDB_ROOT_USERNAME=user
      - MONGO_INITDB_ROOT_PASSWORD=otro_super-pass

  mysql:
    image: mysql:5.7
    ports:
      -'3306:3306'    volumes: 
      - ./data/mysql:/var/lib/mysql
    environment: 
      - MYSQL_USER=user
      - MYSQL_PASSWORD=otro_super-pass_mas
<h3>Notas adicionales</h3>

Por si alguien se anima a hacer un entorno similar permítanme darles algunos consejos:

  • Siempre usen la opcion -y cuando instalen dependencias en sus imagenes. Tengan cuidado con cuales dependencias instalan.

  • Verifiquen previamente por separado la configuración de cada imagen.

  • Si quieren correr Jupyter Lab dentro de docker para luego verlo en el browser, ejecutenlo como jupyter lab --ip 0.0.0.0 --no-browser para evitar inconvenientes.

Espero que les haya servido mi tutorial.

Y recuerden: Nunca paren de aprender.

Escribe tu comentario
+ 2
3
14338Puntos

Excelente texto, y gracias por tus tips finales. 🐍