Jan
29
Sitecore demo in a Docker Container

Una instancia de Sitecore 8 require un conjunto de servicios trabajando juntos, como son IIS, SQL Server, y MongoDB. Para preparar un sitio web de demostración, esos servicios han de estar disponibles, de modo que nuestra instalación debe asegurar su presencia y resolver cualquier conflicto de nombres con otras bases de datos o sitios web existentes. La herramienta Sitecore Instance Manager puede ayudar a instalar una instancia de Sitecore, aunque deja todavía mucho trabajo manual para instalar las personalizaciones de la demo.

Me preguntaba si Docker podría ayudar. Estaría bien tener una imagen de Docker con una demo de Sitecore ya instalada con todas sus dependencias, de forma que sólo se necesitara instanciar un contenedor para tener una demo lista para la acción. De esta forma no hace falta instalar o mantener software ya sea en un portatil del equipo de ventas o en un servidor en la nube. Sólo un comando sería necesario para levantar el contenedor con todo lo necesario. Este blog va precisamente de eso.

¿Qué es Docker y por qué usarlo?

Hay infinidad de sitios web proporcionando introducciones a Docker. De modo que evitaremos los detalles aquí. Si necesitas ayuda con ello sólo tienes que escribir “Introducción a Docker” en Google para encontrar información al respecto.

Muy a alto nivel, Docker es un sistema de virtualización, parecido a Hyper-V o VMWare. Tiene varias ventajas, de entre las cuales, teniendo en cuenta el propósito de esta entrada de blog, quiero destacar las siguientes:

  • Necesita menos espacio en disco. Los contenedores Docker necesitan menos espacio en dico que las máquinas virtuales tradicionales. Esto es así porque varios contenedores comparten el mismo kernel, mientras las máquinas virtuales tienen cada una su propio sistema operativo (kernel).
  • Debido a otras ventajas omitidas en este artículo, Docker puede ser adecuado para incorporarlo a los procesos modernos de desarrollo y desplegado de software (tambián llamados DevOps). El uso de esta tecnología en ámbitos de demostraciones comerciales es una forma sencilla de entrar en contacto con Docker y empezar a utilizarlo. Si ya se utiliza en nuestra empresa, entonces éste sería un ámbito más.

Descripción de mi Demo de Sitecore

El software necesario para soportar un sitio de Sitecore depende de la versión de Sitecore y las características y módulos instalados.

El sitio de Sitecore utilizado en este artículo está basado en Sitecore 8 con el módulo Email Experience Manager (EXM), con la Experience Database (XDB) habilitada con una instancia de MongoDB local. El proveedor de búsqueda utilizado es Lucene.

Crear una imagen Docker para mi Demo de Sitecore

Un contenedor Docker se crea siempre a partir de una imagen. En términos de programación, es como instanciar un objeto (contenedor) a partir de su clase (imagen). Así pues, lo primero a hacer será una imagen Docker con todo lo necesario para nuestra demo.

Elementos necesarios

Estos son los elementos necesarios para crear una imagen Docker con un sitio web de Sitecore.

    • Máquina con Docker.
    • Carpeta de trabajo
    • Archivo “Dockerfile”
    • Archivos y bases de datos de Sitecore
    • Paquetes de instalación de:
      • SQL Server Express x64
      • Microsoft Visual C++ 2012 Redistributable
    • Carpeta con archiovos y configuración de MongoDB
    • PowerShell scripts para installar u habilitar los siguientes prerequisitos:
      • SQL Server
      • IIS
      • MongoDB
      • Microsoft Visual C++ 2012 Redistributable: requerido por Sitecore EXM. Sólo se necesita si la demo de Sitecore incluye el módulo “Email Experience Manager”.

A continuación veremos en detalle cada uno de estos puntos.

Máquina con Docker

Para crear una imagen y después ejecutar contenedores necesitaremos Docker. En este caso utilizaremos una máquina con Windows 10 con “Docker for Windows”, aunque también se puede utilizar Windows Server 2016 a demás de máquinas Apple o Linux.

Docker debe estar configurado en modo “Windows containers”, esto nos permitirá crear contenedores Windows.

Carpeta de trabajo

Todo lo necesario para el sitio web a crear debe estar en una sola carpeta. El nombre o la ruta a la misma es irrelevante ya que no será referenciada desde su interior. Se podrá renombrar y mover libremente más adelante. En mi caso la he creado en:

C:\docker\scdemo\

Todas las carpetas y archivos descritas a continuación serán guardados en esta carpeta a la que consideraremos nivel raíz.

Archivo “Dockerfile”

El archivo “Dockerfile” (sin extensión) establece los pasos a seguir, por Docker para crear la imagen deseada. Se debe crear dentro de la carpeta de trabajo a nivel raíz.

Este es el archivo utilizado en mi caso:

FROM microsoft/windowsservercore

LABEL Description="Sitecore 8.2 rev. 160729" Vendor="Sitecore" Version="8.2 rev. 160729"

# Adding the files
COPY . /
WORKDIR /

# Install dependencies
RUN vcredist_x64.exe /passive /norestart

# Installing MS SQL Server
RUN SQLEXPR_x64_ENU.exe /qs /x:setup && /setup/setup.exe /q /ACTION=Install /INSTANCENAME=SQLEXPRESS /FEATURES=SQLEngine /UPDATEENABLED=0 /SQLSVCACCOUNT="NT AUTHORITY\System" /SQLSYSADMINACCOUNTS="BUILTIN\ADMINISTRATORS" /TCPENABLED=1 /NPENABLED=0 /IACCEPTSQLSERVERLICENSETERMS && del /F /Q SQLEXPR_x64_ENU.exe && rd /q /s setup

# Setting up MS SQL Server and attaching databases
RUN powershell ./sql.ps1 -Verbose

# Setting up IIS and adding the website
RUN powershell ./iis.ps1 -Verbose

# Setting up MongoDB
RUN powershell ./mongo.ps1

EXPOSE 80

Lo primero es copiar todo el contenido de la carpeta raíz dentro de la unidad principal del contenedor (o imagen en este caso) y establecer la ruta de destino como carpeta de trabajo. A continuación se instala todo el software necesario utilizando en unos casos los paquetes de instalación proporcioandos por el proveedor o utilizando scripts de PowerShell.

En los siguentes apartados veremos todos los elementos utilizados por este archivo de Docker.

Archivos y bases de datos de Sitecore

La forma más sencialla de instalar un sitio de Sitecore con sus correspondientes personalizaciones es utilizando las bases de datos y los archivos de un entorno donde ya esté funcionando. Puede ser el mismo entorno de desarrollo donde se haya hecho las correspondientes personalizaciones (layouts, sublayouts, etc). Es lo que haremos aquí.

Crearemos una carpeta en el nivel raíz llamada “sitecore”. En mi caso es: “C:\docker\scdemo\sitecore

En el interior de la carpeta “sitecore” crearemos las siguientes subcarpetas:

  • Data: Contendrá el contenido de la carpeta “Data” del sitio procedente del entorno de origen. Se puede vaciar todas las carpetas de su interior a excepción de “indexes” de esta forma se conservarán los índices de Lucene al tiempo que se reduce el tamaño de la imagen y contenedores de Docker. La carpeta “Data” es el lugar donde se guarda, por defecto, el archivo de licencia de Sitecore (“license.xml”). Se debe utilizar un archivo de licencia válido.
  • Databases: Contendrá las bases de datos de SQL Server utilizadas por el sitio web. En mi caso son las siguientes (con sus correspondientes archivos de log):
    • Sitecore.Core.mdf
    • Sitecore.Exm.Master.mdf
    • Sitecore.Exm.Web.mdf
    • Sitecore.Master.mdf
    • Sitecore.Reporting.mdf
    • Sitecore.Web.mdf
  • Website: Contendrá los archivos del sitio web. Se puede obtener de la carpeta señalada por el servidor IIS del entorno de origen.
Paquetes de instalación

Dos de los requisitos de nuestro sitio de Sitecore se instalan mediante paquetes redistribuíbles, como son:

 SQL Server Express x64: Se puede descargar de aquí. Este paquete es instalado por el archivo “dockerfile” con la siguiente lína:

RUN SQLEXPR_x64_ENU.exe /qs /x:setup && /setup/setup.exe /q /ACTION=Install /INSTANCENAME=SQLEXPRESS /FEATURES=SQLEngine /UPDATEENABLED=0 /SQLSVCACCOUNT="NT AUTHORITY\System" /SQLSYSADMINACCOUNTS="BUILTIN\ADMINISTRATORS" /TCPENABLED=1 /NPENABLED=0 /IACCEPTSQLSERVERLICENSETERMS && del /F /Q SQLEXPR_x64_ENU.exe && rd /q /s setup

Microsoft Visual C++ 2012 Redistributable: Se puede descargar de aquí. La línea, dentro del archivo “dockerfile” encargada de su instalación es:

RUN vcredist_x64.exe /passive /norestart
Carpeta con archivos y configuración de MongoDB

Los detalles de instalación y administración de MongoDB están fuera del alcance de este documento. Para simplificar las cosas, se puede copiar los archivos de una instancia de MongoDB de un entorno de desarrollo, donde normalmente no se aplica sharding ni replicación ni ninguna característica avanzada de MongoDB. Necesitaremos la carpeta “bin” con los binarios de MongoDB, carpeta “data” con las bases de datos, y si hay alguna “config” con un archivo de configuración que, siendo opcional, facilita la tarea de indicar a MongoDB dónde encontrar las carpetas de datos y logs, junto con otros detalles como el motor de almacenamiento etc.

Un detalle a tener en cuenta en la configuración de MongoDB es que la ruta completa a las carpetas necesarias, dentro del conteneder será distinta a la ruta donde se guardan las mismas en la máquina donde se creará la imágen de Docker. Por ejemplo, en mi entorno de desarrollo la carpeta con las bases de datos de MongoDB está en “c:\docker\scdemo\MongoDB\3.4\data\dbs”, en cambio, en el archivo de configuración de MongoDB (usado dentro del contenedor) la ruta será “c:/MongoDB/3.4/data/dbs”. Como vemos, el directorio raíz donde se crea el la imágen del contenedor (“c:\docker\scdemo\”) pasa a ser la ruta raíz (“c:/”) dentro del contenedor.

Un ejemplo de archivo de configuración de MongoDB sería el siguiente:

storage: 
  dbPath: "c:/MongoDB/3.4/data/dbs"
  # Stores each DB within a folder (not default)
  directoryPerDB: true

  # Storage Engine:
  # Memory Map:
  #engine: mmapv1
  # Wired Tiger: It
  engine: wiredTiger

systemLog:
  destination: "file"
  path: "c:/MongoDB/3.4/data/logs/mongod.log"

  # Log files management:
  # Rename existing log file and create a new one
  logRotate: rename
  # Append to existing log file
  #logAppend: true
  #logRotate: reopen

PowerShell scripts para installar u habilitar prerequisitos

El archivo “dockerfile”, se apolla en los siguientes scripts de PowerShell para las tareas descritas a continuación.

  • “sql.ps1”: Configura SQL Server para asegurar el acceso de Sitecore y adjunta las bases de datos necesarias:
    Set-StrictMode -Version latest ;
    
    Stop-Service MSSQL`$SQLEXPRESS ;
    
    Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL14.SQLEXPRESS\MSSQLServer\SuperSocketNetLib\Tcp\IPAll' -Name TcpDynamicPorts -Value '0' ;
    Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL14.SQLEXPRESS\MSSQLServer\SuperSocketNetLib\Tcp\IPAll' -Name TcpPort -Value '1433' ;
    Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL14.SQLEXPRESS\MSSQLServer' -Name LoginMode -Value 2 ;
    
    Start-Service MSSQL`$SQLEXPRESS ;
    
    Invoke-Sqlcmd -Query "ALTER LOGIN sa with password='saPassword'; ALTER LOGIN sa ENABLE;" -ServerInstance ".\SQLEXPRESS" ;
    
    Invoke-Sqlcmd -Query "CREATE DATABASE [demo.local_core]       ON (FILENAME = 'C:\sitecore\Databases\Sitecore.core.mdf'),       (FILENAME = 'C:\sitecore\Databases\demo.local_core_log.ldf')       FOR ATTACH ;" -ServerInstance ".\SQLEXPRESS" ;
    Invoke-Sqlcmd -Query "CREATE DATABASE [demo.local_exm.master] ON (FILENAME = 'C:\sitecore\Databases\Sitecore.exm.master.mdf'), (FILENAME = 'C:\sitecore\Databases\demo.local_exm.master_log.ldf') FOR ATTACH ;" -ServerInstance ".\SQLEXPRESS" ;
    Invoke-Sqlcmd -Query "CREATE DATABASE [demo.local_exm.web]    ON (FILENAME = 'C:\sitecore\Databases\Sitecore.exm.web.mdf'),    (FILENAME = 'C:\sitecore\Databases\demo.local_exm.web_log.ldf')    FOR ATTACH ;" -ServerInstance ".\SQLEXPRESS" ;
    Invoke-Sqlcmd -Query "CREATE DATABASE [demo.local_master]     ON (FILENAME = 'C:\sitecore\Databases\Sitecore.master.mdf'),     (FILENAME = 'C:\sitecore\Databases\demo.local_master_log.ldf')     FOR ATTACH ;" -ServerInstance ".\SQLEXPRESS" ;
    Invoke-Sqlcmd -Query "CREATE DATABASE [demo.local_reporting]  ON (FILENAME = 'C:\sitecore\Databases\Sitecore.reporting.mdf'),  (FILENAME = 'C:\sitecore\Databases\demo.local_reporting_log.ldf')  FOR ATTACH ;" -ServerInstance ".\SQLEXPRESS" ;
    Invoke-Sqlcmd -Query "CREATE DATABASE [demo.local_web]        ON (FILENAME = 'C:\sitecore\Databases\Sitecore.web.mdf'),        (FILENAME = 'C:\sitecore\Databases\demo.local_web_log.ldf')        FOR ATTACH ;" -ServerInstance ".\SQLEXPRESS" ;
    
  • “iis.ps1”: Crea y configura el sitio web de la demo dentro de Internet Information Services (IIS):
    Add-WindowsFeature Web-Server
    Add-WindowsFeature NET-Framework-45-ASPNET
    Add-WindowsFeature Web-Asp-Net45
    
    C:\Windows\System32\inetsrv\appcmd.exe delete site "default web site"
    
    C:\Windows\System32\inetsrv\appcmd.exe add site /name:Sitecore /bindings:http/*:80: /physicalPath:c:\sitecore\Website
    
    # Site Bindings
    New-WebBinding -name Sitecore -port 80 -Protocol http -HostHeader demo.local -IPAddress "*"
    New-WebBinding -name Sitecore -port 80 -Protocol http -HostHeader demo.demo.local -IPAddress "*"
    New-WebBinding -name Sitecore -port 80 -Protocol http -HostHeader habitat.demo.local -IPAddress "*"
    New-WebBinding -name Sitecore -port 80 -Protocol http -HostHeader legal.demo.local -IPAddress "*"
    New-WebBinding -name Sitecore -port 80 -Protocol http -HostHeader retail.demo.local -IPAddress "*"
    New-WebBinding -name Sitecore -port 80 -Protocol http -HostHeader finance.demo.local -IPAddress "*"
    New-WebBinding -name Sitecore -port 80 -Protocol http -HostHeader storefront.demo.local -IPAddress "*"
    New-WebBinding -name Sitecore -port 80 -Protocol http -HostHeader utilities.demo.local -IPAddress "*"
    
    
    C:\Windows\System32\inetsrv\appcmd.exe start site Sitecore
    
    iisreset
    
  • “mongo.ps1”: Configura el servicio de Windows que ejecutará MongoDB:
    c:\MongoDB\3.4\bin\mongod.exe --service --config=c:\MongoDB\3.4\config\mongod.cfg --install
    Get-Service | Where-Object {$_.displayName -eq "MongoDb"} | Start-Service
    

Proceso de creación de la Imagen de Docker

Una vez preparados los elementos necesarios, la creación de la imagen consiste en ejecutar el siguiente comando:

docker build -t sitecore %~dp0

Instanciar un contenedor Docker con mi Demo de Sitecore

Una vez disponemos de nuestra imagen de Docker, crear un contenedor con la demo lista para ser usada, es tan sencillo como ejecutar el siguiente comando:

docker run --name sitecore -p 80:80 -it -m 8g sitecore powershell

Una vez se ejecuta el contenedor, accederemos a él a través de su IP. Se puede usar el siguiente comando de PowerShell para obtener dicha IP:

docker inspect --format '{{ .NetworkSettings.Networks.nat.IPAddress }}' sitecore

La versión de Docker para Windows 10 presenta ciertas limitaciones que impiden poder acceder al sitio de Sitecore en el contenedor a través de un dominio más amigable (como “localhost”). Más información al respecto puede encontrarse aquí. Afortunadamente, la versión de Docker para Windows Server 2016 soluciona esta limitación.

Referencias

The following articles helped me a lot to develop this docker solution.

  • https://medium.com/@romaklimenko/running-sitecore-in-a-docker-container-is-easier-than-you-might-think-298050b507ff
  • https://blog.sixeyed.com/published-ports-on-windows-containers-dont-do-loopback/