Introducción a Dapr .NET SDK (7/N): Docker Compose & HTTPS


En este post vamos a ver como con Docker Compose definimos y configuramos una aplicación multi-container para ejecutarla localmente sin Kubernetes. Aquí, el peso recae, como ya podemos imaginar, en el fichero «docker-compose.yml» donde tendremos que incluir la definición de los sidecars para Dapr. Necesitaremos también, los ficheros Dockerfile de cada proyecto y, por supuesto, complicaremos el ejemplo un poco más, incluyendo HTTPS.

En particular, y como viene siendo habitual, para ver todo esto en funcionamiento nos apoyaremos en este ejemplo de mi github.

Recordemos que este articulo forma parte de un listado (aún por cerrar) y que seguirá creciendo:

  1. Introducción a Dapr .NET SDK (1/N) y «Service-to-service invocation»
  2. Introducción a Dapr .NET SDK (2/N): State management
  3. Introducción a Dapr .NET SDK (3/N): Secrets
  4. Introducción a Dapr .NET SDK (4/N): Pub/Sub
  5. Introducción a Dapr .NET SDK (5/N): Bindings y Triggers
  6. Introducción a Dapr .NET SDK (6/N): Debugging (VSCode y VS) + Sidekick
  7. [ -> ] Introducción a Dapr .NET SDK (7/N): Docker Compose and HTTPS
  8. Introducción a Dapr .NET SDK (8/N): Kubernetes mode

Antes de comenzar, veamos en que consiste nuestra aplicación de ejemplo, formada por tres proyectos ASP.NET además de su Dockerfile:

  • Website. Simple aplicación web que consume los servicios siguientes mediante Dapr.
  • WeatherService. Servicio/Api Rest que es consumido mediante Service Invocaction desde el WebSite.
  • CounterService. Servicio/Api Rest que es consumido vía Pub/Sub desde el WebSite

Adicionalmente:

  • dapr\components. Carpeta que agrupa la configuración de los componentes Dapr para ser usados localmente, tal y como veníamos haciendo en post anteriores. Podemos usar start.ps1, para su ejecución.
  • dapr\components\docker-compose. Carpeta que agrupa los componentes Dapr configurados para ser usados con docker-compose.
  • Paquetes Nuget: Dapr.AspNetCore y, Man.Dapr.Sidekick.AspNetCore (Dapr Sidekick for .NET), que ya vimos superficialmente en el post anterior.

Dockerfiles

Estos tres proyectos que conforman la aplicación cuentan con un Dockerfile igual al que vemos a continuación, donde unicamente cambia la carpeta en la que se encuentra y el nombre del .csproj, por lo que se incluye el de Website y el resto lo omitimos :

FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["WebSite/WebSite.csproj", "WebSite/"]
RUN dotnet restore "WebSite/WebSite.csproj"
COPY . .
WORKDIR "/src/WebSite"
RUN dotnet build "WebSite.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "WebSite.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebSite.dll"]

Los puertos 80 y 443 los exponeos para así poder usarlos desde docker-compose y por consiguiente, desde el sidecar de Dapr.

Configuración previa para HTTPS

Para la configuración de HTTPS vía docker/docker-compose y en concreto, para hacer uso en contenedores Linux, la configuración es la siguiente:

Desde la terminal de Windows ejecutar las siguientes sentencias, cuyo propósito no es otro que el de:

  • Elimiar el certificado de desarrollo anterior de la máquina local.
  • Instalar un nuevo certificado en la máquina local y exportarlo a un ruta cualquiera (fuera del sitio web) con un password, que resulta ser un parámetro (-p) requerido para que docker-compose pueda realizar la lectura del certificado.
  • Validar el certificado
dotnet dev-certs https --clean
dotnet dev-certs https -ep $HOME\.aspnet\https\aspnetapp.pfx -p password1
dotnet dev-certs https --trust 

Nota: Si estas usando la terminal de Linux o Mac, las sentencias anteriores cambian ligeramente, por lo que es interesante que eches un ojo a este link.

Docker Compose

Ahora que ya tenemos los Dockerfile y el certificado para HTTPS, tenemos que configurarlo todo en nuestro docker-compose.yml.

version: "3.8"
services:
  website:
    image: "alltogether.website"
    build:
      context: .
      dockerfile: WebSite/Dockerfile
    ports:
      - 5000:80
      - 5001:443
    depends_on:
      - redis
    environment:      
      - ASPNETCORE_URLS=https://+:443;http://+:80
      - ASPNETCORE_HTTPS_PORT=5001
      - ASPNETCORE_Kestrel__Certificates__Default__Password=password1
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
    volumes:
      - ~/.aspnet/https:/https:ro
    networks:
      - alltogether
  website-dapr:
    image: "daprio/daprd:latest"
    command:
      [
        "./daprd",
        "-app-id",
        "website",
        "-app-port",
        "443",
        "-dapr-http-port",
        "3500",
        "-dapr-grpc-port",
        "50001",
        "-app-ssl",
        "-components-path",
        "/components",
        "-config",
        "/components/config.yaml",
      ]
    depends_on:
      - website
    volumes:
      - ./components/docker-compose:/components
    network_mode: "service:website"
  ... Omitido el resto de servicios por simplicidad puesto que son similares ...
  # Redis state store  
  redis:
    image: "redis:alpine"
    hostname: redis
    ports:
      - 6380:6379
    environment:
      - ALLOW_EMPTY_PASSWORD=yes
    networks:
      - alltogether
  # Observavility
  zipkin:
    image: openzipkin/zipkin
    # hostname: zipkin
    container_name: zipkin
    ports:      
      - 9413:9411
    networks:
      - alltogether
networks:
  alltogether:

En este código cabe destacar, en primer lugar:

  • services.website. Nombre del servicio.
  • services.website.build.dockerfile. Fichero docker file
  • services.website.ports. Listado de mapeos de puertos a exponer hacia el exterior, con el siguiente formato: <Puerto-exterior>:<puerto-interno>.
  • services.website.ports. Listado de variables de entorno y configuración para el contenedor. En este caso se incluyen las necesarias para la configuración HTTPS.
    • El password a especificar debe ser el mismo que el indicado en el apartado anterior al exportar el certificado .pfx, es decir: «password1»
    • El puerto 5001, es el puerto expuesto/publico al que navegaremos para ejecutar la aplicación. Este puerto debe coincider con el valor del parámetro «-app-port» que necesita el sidecar de dapr.
  • services.website.volumes: Listado de volúmenes, es decir mapeos entre rutas locales (maquina host) y contenedores docker. En concreto se trata del mapeo de la ruta en la que hemos exportado el certificado .pfx. Formato: <ruta-local>:<ruta-contenedor>. La sintaxis aquí puede variar dependiendo de si la máquina local es Windows, Linux o Mac.
  • services.website.networks. Red docker a la que pertenecerá el servicio.

En segundo lugar, el servicio correspondiente al sidecar de Dapr:

  • services.website-dapr. Configuración del sidecar para el servicio anterior «website». Debe coincidir en nombre y añadir el sufijo «-dapr».
  • services.website-dapr.commands. Aquí se incluyen todos los parámetros que necesita Dapr para su ejecución. Practicamente todos y cada uno de los parámetrosque ya conocemos de posts anteriores.
    • -app-ssl.
    • -components-path. Ruta dentro del contenedor donde se cuentran los componentes Dapr.
    • -config. Ruta completa donde se encuetra el fichero de configuración config.yml de Dapr.
    • 443. Puerto interno para SSL. ¡Importante que el puerto se encuentre expuesto en el Dockerfile!
  • services.website-dapr.volumes.
  • services.website-dapr.network_mode. Incorpora el servicio «service:website» al namespace de la red donde está el servicio «website». Su formato es: «servcie:<nombre-servicio>».

A continuación, los servicios correspondientes a la infraestructura que soportará los componetes Dapr. Un Redis para este caso particular y zipkin (para observabilidad) que usaremos de manera opcional:

  • services.redis.ports. Mapeo de puertos, donde exponemos el puerto 6380, dado que en la máquina local (o host) el 6379 debe estar ocupado dado que hemos ejecutado previamente un «dapr init». Se trata del puerto que usa el componente Redis predeterminado de Dapr.
  • services.zipkin.ports. Mapeo de puertos, donde, al igual que para Redis, se expone zipkin. Usaremos el 9413 dado que el 9411 se encuentra usado por el componente zipkin predeterminado de Dapr.

Ejecutando la aplicación

Compilamos las imágenes docker de acuerdo a los Dockerfile. Bastará con hacerlo la primera vez y siempre que realicemos cambios en el código.

docker compose build

Finalmente, levantamos el entorno completo y navegamos a la url: https://localhost:5001.

docker compose up

Podemos comprobar que las dos opciones del menu de la aplicación: «Dapr Counter» y «Dapr Fecth data» funcionan correctamente haciendo uso de Dapr.

Ya tenemos un entorno completo de desarrollo, que puede ser usado por cada uno de los miembros de nuestro equipo sin necesidad de instalaciones individuales y evitando dependencias y otros problemas derivados.

Una vez más, espero que sea de utilidad.

Happy #Dapr coding !!!

Referencias

8 comentarios sobre “Introducción a Dapr .NET SDK (7/N): Docker Compose & HTTPS

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Salir /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.