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
Hyper-v manager
You need to run Hyper-v manager and make sure that your virtual machine and the MobyLinuxVM is up and run.
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.
Turn on Hyper-v windows feature
Cpu performance
Just make sure that virtualization is on and enabled.
Hyper virtual machine management service
Look at list of your services and you will figure out if this service is running or not.
Docker for windows service
Look at list of your services and you will figure out if this service is running or not.
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
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.
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.
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
Each command make an api call from docker client to docker daemon.
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.
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:
Just open Sql management console and connect to the IP address and Port.
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
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/