Sitecore on Docker

Sitecore on Docker

Lets discuss the issue first. The actual problem is unicorn serialization but lets bring an example to make it clear.
you might work on a new sitecore feature in a branch called "feature/payment" which is not going to get released soon and there is another branch called BAU which is gonna be released every forth monthly.
Whenever you switch the branches.

The files are just deleted and replaced with the new files. So, basically you need to run the unicorn to serialize all the files.

I run my docker inside the Virtual Box so you need to config some extra options to get it worked.

Steps

Install/upgrade your windows to windows pro or enterprise

if you have a msdn subscription then you would be able to get the key from http://my.visualstudio.com/
and upgrade your windows from windows property=> setting=>system=>about =>upgrade your windows

Install Docker for windows

Get docker from https://docs.docker.com/docker-for-windows/install/
and simply install it on your windows.

Docker inside VirtualBox

Run this command line :

docker version

You probably see this error if you are running docker inside the virtual box
error

Hyper-v manager

You need to run Hyper-v manager and make sure that your virtual machine and the MobyLinuxVM is up and run.
Hyper-v-menu
Hyper-v-Manager
If it is not click connect or start to make it up.

Adjut your Vm setting

make sure adaptive hypervisor option and nested hyper in cpu section are checked.
nested-virtualization-vm
adaptive-hypervisor

Turn on Hyper-v windows feature

win-feature-Hyper-v

Cpu performance

Just make sure that virtualization is on and enabled.
Virtualization

Hyper virtual machine management service

Look at list of your services and you will figure out if this service is running or not.
Hyper-virtual-machine-management-service

Docker for windows service

Look at list of your services and you will figure out if this service is running or not.

docker-for-windows-service

switch to windows container

If still you cannot get it worked, have a look at icons on windows right corner and right click on docker menu. click to switch to windows container
switch-docker

Start docker

Docker is set to be run once you logged in. However, if it was not, then there is an icon that you can run it.
quick-start-docker

docker commands:

docker version

Once we check the version we will see client and server daemon and it is possible to point each to a different machine even out of the network.
client-server-docker

docker info

docker info

get the list of containers and images running on this machine

docker run

docker run hello-world

Run me a new container and to run the container, you potentially need an image which is hello-world. If you already created the image on your local it will fetch it otherwise it will use the docker hub which is the library of images.
Client talks to the daemon to see if it had a copy of hello-world image locally or not?
if there is no local image then go and grab the hello-world from docker hub and use that image to create a new container.
These are the steps which are taken behind the scene:

docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
ca4f61b1923c: Pull complete
Digest: sha256:083de497cff944f969d8499ab94f07134c50bcf5e6b9559b27182d3fa80ce3f7
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://cloud.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/

docker ps (-a)

docker ps

show the running containers and little -a flag just make all the containers which were running but now they are not also how up.
If your container is probably a short living container and exit quickly, you can see the list of previously running containers which -a flag command. Here is the result:

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
769b52925c10        hello-world         "/hello"            2 minutes ago       Exited (0) 2 minutes ago                       objective_curie

docker images

will list the repository which is our image name.

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              f2a91732366c        3 months ago        1.85kB

Infrastructure

There is docker host which can be windows, linux or ... then there is docker client and docker daemon which all together is called docker engine
docker-engin
Each command make an api call from docker client to docker daemon.
docker-api
once docker client asked for a new container based on an image, docker daemon takes a look at the local library, if it does nit exists , then will make a call to the docker hub which is the image registry and try to fetch the image.
docker-hub
However we can make a search in our container registry instead of the public one. So when we run a container it will download the image, run the container and exit but left a copy of the image on our local.

docker pull

You would not have the image if you don't run a new container unless you pull the image you need.

docker pull ubuntu
or
docker pull alpine:14.0

container vs images

image is basically like a template or class in dev languages and container is an instantiation of the image. so while it is image it means it is not running but when it is run it is now container.

docker rmo tag / name

remove the docker container

docker stop/start

if you want to change the port or something in the container, we will stop it and run it in different ports.

Keep docker state

After you installed your images and containers once you quit your windows everything will be removes unless you save your docker state.

install sql

docker run -d -p 1433:1433 -e sa_password=Password123456 -e ACCEPT_EULA=Y microsoft/mssql-server-windows-express --name sql

it takes sometime to download and install the sqlexpress on the docker.
when it is done you can run docker ps to see the container along with your image:

CONTAINER ID        IMAGE                                    COMMAND                  CREATED             STATUS              PORTS                    NAMES
6c465e00ae97        microsoft/mssql-server-windows-express   "powershell -Command…"   About an hour ago   Up About an hour    0.0.0.0:1433->1433/tcp   cranky_dijkstra

How to connect to sqlexpress?

you need to see on what port and IP this container is up and running, so run:

docker ps
* Grab the #CONTAINER ID

then run:

docker inspect #CONTAINER ID 

you will see the detail on your container will come up:
docker-inspect
Just open Sql management console and connect to the IP address and Port.
sql

docker-machine command

get the sql files

run this command in sql management to see where are the mdf and log files.

SELECT * FROM sys.database_files

Map container port to port 1433

in sitecore config you would say my dbconnection is localhost:1433 and at one time only one sql instance should be activated and up and run.
Then you need to map your sql port inside container to the same port so it means whoever wants to have access to this port from outside will map to indternal port of sql. Then we don't have to change the sitecore folder connection string

Mount volums in the container

containers use the hard disk like overlay so it means that my windows host does have access to some folders which container does not, The only way to give access is mounting a folder from host to the container to be able to read the db mdf,ldf files and then run a sql command to attach those files.

$ docker run -d
-it
--name mydbcontainer
-v C:/sitecore/my.local/Databases:c/my-vol:ro
nginx:latest

$ docker run -d
-it
--name mydbcontainer
--mount type=bind,source="$(pwd)"/test.txt,target=/app, readonly
nginx:latest

  • add a volum
    docker run -d -v my-named-volume:C:\MyNamedVolume testimage:latest
    docker run -d -v my-named-volume:C:\sitecore\my.local\Databases testimage:late
  • mount a host folder
    docker run -d -v C:\sitecore\my.local\Databases:C:\Dir testimage:latest
    docker run -d -v C:\Temp\123:C:\My\Shared\Dir testimage:latest

docker run -d -p 1433:1433 -e sa_password=Password123456 -e ACCEPT_EULA=Y microsoft/mssql-server-windows-express -v my-vol:/data

docker run -d -p 1433:1433 -e sa_password=Password123 -e ACCEPT_EULA=Y microsoft/mssql-server-windows-express -v C:/temp/:C:/temp/ -e attach_dbs="[{'dbName':'my.local_core','dbFiles':['C:\temp\Sitecore.Core.mdf','C:\temp\Sitecore.Core.ldf']}]"

docker run -d -p 1433:1433 -v C:/temp/:C:/temp/ -e sa_password=Password123 -e ACCEPT_EULA=Y -e attach_dbs="my.local_master" microsoft/mssql-server-windows-express

copy files to the container
docker cp c:/temp/Sitecore.Core.mdf [containername-fervent_shannon]:/c:/temp
you might get this error : Error response from daemon: filesystem operations against a running Hyper-V container are not supported
so you need to stop the container and start it again :

docker stop fervent_shannon
copy files
docker start -i fervent_shannon

It actually brings your container in the interactive mode. it means you will see the messages that you don't normally see.

powershell in container

 docker exec -it fervent_shannon cmd

I am not sure if this one works or not docker exec -it <CONTAINER_ID> sqlcmd -i c:\create_databases.sql

copy the script to container and run it:

Run a script
Now it will launch the cmd env for you in your container

del /F /Q /S c:\mySql
rd c:\mySql /s /q

md c:\mySql
docker stop fervent_shannon
docker cp c:/temp/Sitecore.Core.mdf fervent_shannon:/c:/mySql
docker cp c:/temp/Sitecore.Web.mdf fervent_shannon:/c:/mySql
docker cp c:/temp/Sitecore.Master.mdf fervent_shannon:/c:/mySql
docker cp c:/temp/Sitecore.reporting.mdf fervent_shannon:/c:/mySql
docker cp c:/temp/nrma.local_master_log.ldf fervent_shannon:/c:/mySql
docker cp c:/temp/nrma.local_web_log.ldf fervent_shannon:/c:/mySql
docker cp c:/temp/nrma.local_core_log.ldf fervent_shannon:/c:/mySql
docker cp c:/temp/nrma.local_reporting_log.ldf fervent_shannon:/c:/mySql
docker cp c:/temp/create_databases.sql fervent_shannon:/c:/mySql
 
exit
 docker start -i fervent_shannon
 
Then get the ip to be abale to attachj files 

ATTACHING FILES:

you can either run this script or commands:

sqlcmd -i c:\temp\create_databases.sql

Could not get the command worked so I attached manually

sqlcmd -S .\SQLEXPRESS
use master
GO
CREATE DATABASE my_local_core ON
(FILENAME=n'C:\mysQL\Sitecore.Core.mdf')
FOR ATTACH;
GO

USE master;  
GO 
CREATE DATABASE [my.local_core]
   ON (FILENAME = 'C:\MySQLServer\AdventureWorks2012_Data.mdf'),  
   (FILENAME = 'C:\MySQLServer\AdventureWorks2012_Log.ldf')  
   FOR ATTACH;  
GO

update the Sitecore connection string

inspect the docker and fing the ip or instance name so update your sitecore connectionstring.config file
To see the result it is important to switch your connection string to point to the BAU databses in the docker or other branches. Then during the development time you potentially switch to your branches as many as you want without running Unicorn each time.

Side effects

In some cases you might face some issues after this consequent switchings. For example the SOLR might be broken since it will get confused between the databases. {Needs proper solution maybe I discuss it in another post}

Troubleshooting

If you use VM you might get some error regarding the Hyper VM so you need to deactivate nested hyoper in your VM.
ex) if you are using Paralle, you can activate it through
parallel

References

hyper-v-in-virtualbox-guide
docker-ce-desktop-windows
docker
https://mathaywardhill.com/2017/05/08/how-to-attach-a-sql-server-database-in-a-linux-docker-container/