GNU/Linux >> Tutoriales Linux >  >> Panels >> Docker

Cómo implementar microservicios con Docker

¿Qué es un microservicio?

Los microservicios son una arquitectura cada vez más popular para crear aplicaciones a gran escala. En lugar de utilizar un único código base monolítico, las aplicaciones se dividen en una colección de componentes más pequeños llamados microservicios. Este enfoque ofrece varios beneficios, incluida la capacidad de escalar microservicios individuales, mantener el código base más fácil de entender y probar, y permitir el uso de diferentes lenguajes de programación, bases de datos y otras herramientas para cada microservicio.

Docker es una excelente herramienta para administrar e implementar microservicios. Cada microservicio se puede dividir aún más en procesos que se ejecutan en contenedores Docker separados, que se pueden especificar con archivos de configuración Dockerfiles y Docker Compose. En combinación con una herramienta de aprovisionamiento como Kubernetes, un equipo de desarrolladores puede implementar, escalar y colaborar fácilmente en cada microservicio. Especificar un entorno de esta manera también facilita la vinculación de microservicios para formar una aplicación más grande.

Esta guía muestra cómo crear e implementar un microservicio de ejemplo con Docker y Docker Compose.

Antes de comenzar

  1. Si aún no lo ha hecho, cree una cuenta de Linode y una instancia de cómputo. Consulte nuestras guías Introducción a Linode y Creación de una instancia informática.

  2. Siga nuestra guía de configuración y protección de una instancia informática para actualizar su sistema. También puede establecer la zona horaria, configurar su nombre de host, crear una cuenta de usuario limitada y fortalecer el acceso SSH.

Nota Esta guía está escrita para un usuario no root. Los comandos que requieren privilegios elevados tienen el prefijo sudo . Si no está familiarizado con sudo comando, puede consultar nuestra guía de Usuarios y Grupos.

Instalar Docker

Para instalar Docker CE (Community Edition), siga las instrucciones de una de las siguientes guías:

  • Instalación y uso de Docker en Ubuntu y Debian

  • Instalación y uso de Docker en CentOS y Fedora

Para obtener instrucciones completas sobre aún más distribuciones de Linux, consulte la sección Instalar el motor Docker de la documentación oficial de Docker.

Instalar Docker Compose

  1. Descarga la última versión de Docker Compose. Consulte la página de lanzamientos y reemplace 1.25.4 en el siguiente comando con la versión etiquetada como Última versión :

     sudo curl -L https://github.com/docker/compose/releases/download/1.25.4/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
    
  2. Establecer permisos de archivo:

     sudo chmod +x /usr/local/bin/docker-compose
    

Preparar el entorno

Esta sección usa Dockerfiles para configurar imágenes de Docker. Para obtener más información sobre la sintaxis y las mejores prácticas de Dockerfile, consulte nuestra guía Cómo usar Dockerfiles y la guía de mejores prácticas de Dockerfile de Docker.

  1. Cree un directorio para el microservicio:

     mkdir flask-microservice
    
  2. Cree una estructura de directorio para los componentes de microservicio dentro del nuevo directorio:

     cd flask-microservice
     mkdir nginx postgres web
    

NGINX

  1. Dentro del nuevo nginx subdirectorio, cree un Dockerfile para la imagen NGINX:

    Archivo:nginx /Dockerfile
  2. Crea el nginx.conf referenciado en el Dockerfile:

    Archivo:/ nginx/nginx.conf
  3. 1
    2
    
    from nginx:alpine
    COPY nginx.conf /etc/nginx/nginx.conf

    PostgreSQL

    La imagen de PostgreSQL para este microservicio utilizará el postgresql oficial imagen en Docker Hub, por lo que no es necesario Dockerfile.

    En el postgres subdirectorio, cree un init.sql archivo:

    Archivo:postgres /init.sql
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    
    user  nginx;
    worker_processes 1;
    error_log  /dev/stdout info;
    error_log off;
    pid        /var/run/nginx.pid;
    
    events {
        worker_connections  1024;
        use epoll;
        multi_accept on;
    }
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /dev/stdout main;
        access_log off;
        keepalive_timeout 65;
        keepalive_requests 100000;
        tcp_nopush on;
        tcp_nodelay on;
    
        server {
            listen 80;
            proxy_pass_header Server;
    
            location / {
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
    
                # app comes from /etc/hosts, Docker added it for us!
                proxy_pass http://flaskapp:8000/;
            }
        }
    }
    Precaución En la línea 22 de init.sql , asegúrese de que su editor de texto no convierta tabulaciones en espacios. La aplicación no funcionará sin pestañas entre las entradas de esta línea.

    Web

    La web la imagen contendrá una aplicación Flask de ejemplo. Agregue los siguientes archivos a la web directorio para preparar la aplicación:

    1. Crear una .python-version archivo para especificar el uso de Python 3.6:

       echo "3.6.0" >> web/.python-version
      
    2. Crea un Dockerfile para la web imagen:

      Archivo:web /Dockerfile
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    SET statement_timeout = 0;
    SET lock_timeout = 0;
    SET idle_in_transaction_session_timeout = 0;
    SET client_encoding = 'UTF8';
    SET standard_conforming_strings = on;
    SET check_function_bodies = false;
    SET client_min_messages = warning;
    SET row_security = off;
    CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
    COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
    SET search_path = public, pg_catalog;
    SET default_tablespace = '';
    SET default_with_oids = false;
    CREATE TABLE visitors (
        site_id integer,
        site_name text,
        visitor_count integer
    );
    
    ALTER TABLE visitors OWNER TO postgres;
    COPY visitors (site_id, site_name, visitor_count) FROM stdin;
    1 	linodeexample.com  	0
    \.
  4. Crear web/linode.py y agregue la secuencia de comandos de la aplicación de ejemplo:

    Archivo:web /linode.py
  5.  1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    from python:3.6.2-slim
    RUN groupadd flaskgroup && useradd -m -g flaskgroup -s /bin/bash flask
    RUN echo "flask ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
    RUN mkdir -p /home/flask/app/web
    WORKDIR /home/flask/app/web
    COPY requirements.txt /home/flask/app/web
    RUN pip install --no-cache-dir -r requirements.txt
    RUN chown -R flask:flaskgroup /home/flask
    USER flask
    ENTRYPOINT ["/usr/local/bin/gunicorn", "--bind", ":8000", "linode:app", "--reload", "--workers", "16"]
  6. Agregue un requirements.txt archivo con las dependencias de Python requeridas:

    Archivo:web /requisitos.txt
  7.  1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    
    from flask import Flask
    import logging
    import psycopg2
    import redis
    import sys
    
    app = Flask(__name__)
    cache = redis.StrictRedis(host='redis', port=6379)
    
    # Configure Logging
    app.logger.addHandler(logging.StreamHandler(sys.stdout))
    app.logger.setLevel(logging.DEBUG)
    
    def PgFetch(query, method):
    
        # Connect to an existing database
        conn = psycopg2.connect("host='postgres' dbname='linode' user='postgres' password='linode123'")
    
        # Open a cursor to perform database operations
        cur = conn.cursor()
    
        # Query the database and obtain data as Python objects
        dbquery = cur.execute(query)
    
        if method == 'GET':
            result = cur.fetchone()
        else:
            result = ""
    
        # Make the changes to the database persistent
        conn.commit()
    
        # Close communication with the database
        cur.close()
        conn.close()
        return result
    
    @app.route('/')
    def hello_world():
        if cache.exists('visitor_count'):
            cache.incr('visitor_count')
            count = (cache.get('visitor_count')).decode('utf-8')
            update = PgFetch("UPDATE visitors set visitor_count = " + count + " where site_id = 1;", "POST")
        else:
            cache_refresh = PgFetch("SELECT visitor_count FROM visitors where site_id = 1;", "GET")
            count = int(cache_refresh[0])
            cache.set('visitor_count', count)
            cache.incr('visitor_count')
            count = (cache.get('visitor_count')).decode('utf-8')
        return 'Hello Linode!  This page has been viewed %s time(s).' % count
    
    @app.route('/resetcounter')
    def resetcounter():
        cache.delete('visitor_count')
        PgFetch("UPDATE visitors set visitor_count = 0 where site_id = 1;", "POST")
        app.logger.debug("reset visitor count")
        return "Successfully deleted redis and postgres counters"

    Composición de Docker

    Docker Compose se utilizará para definir las conexiones entre los contenedores y sus ajustes de configuración.

    Crea un docker-compose.yml archivo en el flask-microservice directorio y agregue lo siguiente:

    Archivo:docker -compose.yml
    1
    2
    3
    4
    
    flask
    gunicorn
    psycopg2-binary
    redis

    Probar el microservicio

    1. Use Docker Compose para compilar todas las imágenes e iniciar el microservicio:

      cd flask-microservice/ && docker-compose up
      

      Debería ver que todos los servicios se inician en su terminal.

    2. Abra una nueva ventana de terminal y realice una solicitud a la aplicación de ejemplo:

      curl localhost
      
      Hello Linode! This page has been viewed 1 time(s).
    3. Restablecer el contador de visitas de la página:

      curl localhost/resetcounter
      
      Successfully deleted redis and postgres counters
    4. Regrese a la ventana de terminal donde se inició Docker Compose para ver el registro de salida estándar:

      flaskapp_1  | DEBUG in linode [/home/flask/app/web/linode.py:56]:
      flaskapp_1  | reset visitor count

    Uso de contenedores en producción:mejores prácticas

    Los contenedores usados ​​en el microservicio de ejemplo están destinados a demostrar las siguientes prácticas recomendadas para usar contenedores en producción:

    Los contenedores deben ser:

    1. Efímero :Debería ser fácil detener, destruir, reconstruir y volver a implementar contenedores con una instalación y configuración mínimas.

      El microservicio Flask es un ejemplo ideal de esto. Todo el microservicio se puede activar o desactivar mediante Docker Compose. No es necesaria ninguna configuración adicional una vez que se ejecutan los contenedores, lo que facilita la modificación de la aplicación.

    2. Desechable :Idealmente, cualquier contenedor único dentro de una aplicación más grande debería poder fallar sin afectar el rendimiento de la aplicación. Usando un restart: on-failure opción en docker-compose.yml El archivo, además de tener un recuento de réplicas, hace posible que algunos contenedores en el microservicio de ejemplo fallen sin problemas mientras siguen sirviendo la aplicación web, sin degradación para el usuario final.

      Nota La directiva de recuento de réplicas solo será efectiva cuando esta configuración se implemente como parte de un Docker Swarm, que no se trata en esta guía.
    3. Rápido para comenzar :evitar pasos de instalación adicionales en el archivo de Docker, eliminar dependencias que no son necesarias y crear una imagen de destino que se pueda reutilizar son tres de los pasos más importantes para crear una aplicación web que tenga un tiempo de inicialización rápido dentro de Docker. La aplicación de ejemplo utiliza archivos Dockerfile predefinidos, breves y concisos para minimizar el tiempo de inicialización.

    4. Rápido para detener :validar que un docker kill --signal=SIGINT {APPNAME} detiene la aplicación con gracia. Esto, junto con una condición de reinicio y una condición de réplica, asegurará que cuando los contenedores fallen, se volverán a poner en línea de manera eficiente.

    5. Ligero :use el contenedor base más pequeño que proporcione todas las utilidades necesarias para compilar y ejecutar su aplicación. Muchas imágenes de Docker se basan en Alpine Linux, una distribución de Linux ligera y sencilla que ocupa solo 5 MB en una imagen de Docker. El uso de una distribución pequeña ahorra gastos generales operativos y de red, y aumenta considerablemente el rendimiento del contenedor. La aplicación de ejemplo utiliza imágenes alpinas cuando corresponda (NGINX, Redis y PostgreSQL) y una imagen base delgada de Python para la aplicación Gunicorn/Flask.

    6. Apátrida :Dado que son efímeros, los contenedores normalmente no deben mantener el estado. El estado de una aplicación debe almacenarse en un volumen de datos persistente e independiente, como es el caso del almacén de datos PostgreSQL del microservicio. El almacén de clave-valor de Redis mantiene datos dentro de un contenedor, pero estos datos no son críticos para la aplicación; la tienda de Redis recuperará correctamente la base de datos en caso de que el contenedor no pueda responder.

    7. Portátil :todas las dependencias de una aplicación que se necesitan para el tiempo de ejecución del contenedor deben estar disponibles localmente. Todas las dependencias del microservicio de ejemplo y los scripts de inicio se almacenan en el directorio de cada componente. Estos se pueden verificar en el control de versiones, lo que facilita compartir e implementar la aplicación.

    8. Modulares :Cada contenedor debe tener una responsabilidad y un proceso. En este microservicio, cada uno de los principales procesos (NGINX, Python, Redis y PostgreSQL) se implementa en un contenedor independiente.

    9. Registro :Todos los contenedores deben iniciar sesión en STDOUT . Esta uniformidad facilita la visualización de los registros de todos los procesos en un solo flujo.

    10. Resistente :La aplicación de ejemplo reinicia sus contenedores si se cierran por algún motivo. Esto ayuda a que su aplicación dockerizada tenga alta disponibilidad y rendimiento, incluso durante los períodos de mantenimiento.

    Más información

    Es posible que desee consultar los siguientes recursos para obtener información adicional sobre este tema. Si bien estos se proporcionan con la esperanza de que sean útiles, tenga en cuenta que no podemos garantizar la precisión o la puntualidad de los materiales alojados externamente.

    • Repositorio de Github para ejemplo de microservicio
    • Uso de contenedores para crear una arquitectura de microservicios

    Docker
    1. Cómo implementar un servidor DNS dinámico con Docker en Debian 10

    2. Cómo implementar Modsecurity con Nginx en Ubuntu 20.04 LTS

    3. Cómo instalar Jenkins con Docker

    4. Cómo implementar un contenedor nginx con Docker en Linode

    5. Cómo implementar PostgreSQL como un contenedor Docker

    Cómo implementar Pi-Hole en Debian 11

    Cómo implementar pilas de Docker Compose en Kubernetes con Kompose

    Cómo implementar CouchDB como un clúster con Docker

    Cómo implementar Rocket Chat con Nginx en Ubuntu 18.04

    Cómo implementar una aplicación PHP con Nginx y MySQL usando Docker y Docker Compose

    ¿Cómo implementar la aplicación Laravel con Nginx en Ubuntu?

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      
      version: '3'
      services:
       # Define the Flask web application
       flaskapp:
      
         # Build the Dockerfile that is in the web directory
         build: ./web
      
         # Always restart the container regardless of the exit status; try and restart the container indefinitely
         restart: always
      
         # Expose port 8000 to other containers (not to the host of the machine)
         expose:
           - "8000"
      
         # Mount the web directory within the container at /home/flask/app/web
         volumes:
           - ./web:/home/flask/app/web
      
         # Don't create this container until the redis and postgres containers (below) have been created
         depends_on:
           - redis
           - postgres
      
         # Link the redis and postgres containers together so they can talk to one another
         links:
           - redis
           - postgres
      
         # Pass environment variables to the flask container (this debug level lets you see more useful information)
         environment:
           FLASK_DEBUG: 1
      
         # Deploy with three replicas in the case one of the containers fails (only in Docker Swarm)
         deploy:
           mode: replicated
           replicas: 3
      
       # Define the redis Docker container
       redis:
      
         # use the redis:alpine image: https://hub.docker.com/_/redis/
         image: redis:alpine
         restart: always
         deploy:
           mode: replicated
           replicas: 3
      
       # Define the redis NGINX forward proxy container
       nginx:
      
         # build the nginx Dockerfile: http://bit.ly/2kuYaIv
         build: nginx/
         restart: always
      
         # Expose port 80 to the host machine
         ports:
           - "80:80"
         deploy:
           mode: replicated
           replicas: 3
      
         # The Flask application needs to be available for NGINX to make successful proxy requests
         depends_on:
           - flaskapp
      
       # Define the postgres database
       postgres:
         restart: always
         # Use the postgres alpine image: https://hub.docker.com/_/postgres/
         image: postgres:alpine
      
         # Mount an initialization script and the persistent postgresql data volume
         volumes:
           - ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
           - ./postgres/data:/var/lib/postgresql/data
      
         # Pass postgres environment variables
         environment:
           POSTGRES_PASSWORD: linode123
           POSTGRES_DB: linode
      
         # Expose port 5432 to other Docker containers
         expose:
           - "5432"