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 dependencies
RUN["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 R
RUN["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
USER mmenendezg
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: true
tty: 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/data
environment:
- 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.7
ports:
- '3306:3306'
volumes:
- ./data/mysql:/var/lib/mysql
environment:
- 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.